summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2014-12-09 15:28:15 -0600
committerDavid Teigland <teigland@redhat.com>2014-12-19 16:30:32 -0600
commit81c1b0cd21e56c9b0b6ff46770efd3cdbf5683ec (patch)
tree915a2577c9dd7b0ea4330c6168c3056f0b5498ec
parente8cd749873011283464b1766b4743f53764aa853 (diff)
downloadlvm2-dev-dct-lvmlockd-M.tar.gz
vgrename: for lockd VGsdev-dct-lvmlockd-M
-rw-r--r--daemons/lvmlockd/lvmlockd-core.c59
-rw-r--r--daemons/lvmlockd/lvmlockd-internal.h2
-rw-r--r--daemons/lvmlockd/lvmlockd-sanlock.c155
-rw-r--r--lib/locking/lvmlockd.c126
-rw-r--r--lib/locking/lvmlockd.h8
-rw-r--r--man/lvmlockd.8.in2
-rw-r--r--tools/vgrename.c16
7 files changed, 360 insertions, 8 deletions
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
index 28e9825c4..de796f1d5 100644
--- a/daemons/lvmlockd/lvmlockd-core.c
+++ b/daemons/lvmlockd/lvmlockd-core.c
@@ -731,6 +731,10 @@ static const char *op_str(int x)
return "start_wait";
case LD_OP_STOP_ALL:
return "stop_all";
+ case LD_OP_RENAME_BEFORE:
+ return "rename_before";
+ case LD_OP_RENAME_FINAL:
+ return "rename_final";
default:
return "op_unknown";
};
@@ -2121,6 +2125,23 @@ static void *lockspace_thread_main(void *arg_in)
break;
}
+ if (act->op == LD_OP_RENAME_BEFORE && act->rt == LD_RT_VG) {
+ /* vgrename */
+ log_debug("S %s checking for lockspace hosts", ls->name);
+ rv = lm_hosts(ls, 1);
+ if (rv) {
+ log_error("S %s lockspace hosts %d", ls->name, rv);
+ list_del(&act->list);
+ act->result = -EBUSY;
+ add_client_result(act);
+ continue;
+ }
+ ls->thread_work = 0;
+ ls->thread_stop = 1;
+ /* Do we want to check hosts again below like vgremove? */
+ break;
+ }
+
list_del(&act->list);
/* applies to all resources */
@@ -2224,6 +2245,8 @@ out_act:
act->result = 0;
else if (act->op == LD_OP_STOP)
act->result = 0;
+ else if (act->op == LD_OP_RENAME_BEFORE)
+ act->result = 0;
else
act->result = -ENOLS;
list_del(&act->list);
@@ -3325,6 +3348,25 @@ static int work_init_vg(struct action *act)
return rv;
}
+static int work_rename_vg(struct action *act)
+{
+ char ls_name[MAX_NAME+1];
+ int rv = 0;
+
+ memset(ls_name, 0, sizeof(ls_name));
+
+ vg_ls_name(act->vg_name, ls_name);
+
+ if (act->lm_type == LD_LM_SANLOCK)
+ rv = lm_rename_vg_sanlock(ls_name, act->vg_name, act->flags, act->vg_args);
+ else if (act->lm_type == LD_LM_DLM)
+ return 0;
+ else
+ rv = -EINVAL;
+
+ return rv;
+}
+
static void work_test_gl(void)
{
struct lockspace *ls;
@@ -3480,6 +3522,11 @@ static void *worker_thread_main(void *arg_in)
act->result = work_init_lv(act);
add_client_result(act);
+ } else if ((act->op == LD_OP_RENAME_FINAL) && (act->rt == LD_RT_VG)) {
+ log_debug("work rename_vg %s", act->vg_name);
+ act->result = work_rename_vg(act);
+ add_client_result(act);
+
} else if (act->op == LD_OP_UPDATE_LOCAL) {
if (delayed_update_local) {
log_debug("work update_local ignore repeat");
@@ -4078,6 +4125,16 @@ static int str_to_op_rt(const char *req_name, int *op, int *rt)
*op = LD_OP_UPDATE_LOCAL;
return 0;
}
+ if (!strcmp(req_name, "rename_vg_before")) {
+ *op = LD_OP_RENAME_BEFORE;
+ *rt = LD_RT_VG;
+ return 0;
+ }
+ if (!strcmp(req_name, "rename_vg_final")) {
+ *op = LD_OP_RENAME_FINAL;
+ *rt = LD_RT_VG;
+ return 0;
+ }
out:
return -1;
}
@@ -4697,6 +4754,7 @@ static void client_recv_action(struct client *cl)
case LD_OP_UPDATE_LOCAL:
case LD_OP_START_WAIT:
case LD_OP_STOP_ALL:
+ case LD_OP_RENAME_FINAL:
add_work_action(act);
rv = 0;
break;
@@ -4705,6 +4763,7 @@ static void client_recv_action(struct client *cl)
case LD_OP_ENABLE:
case LD_OP_DISABLE:
case LD_OP_FREE:
+ case LD_OP_RENAME_BEFORE:
rv = add_lock_action(act);
break;
case LD_OP_ADD_LOCAL:
diff --git a/daemons/lvmlockd/lvmlockd-internal.h b/daemons/lvmlockd/lvmlockd-internal.h
index eed732dcf..80a4c2fdf 100644
--- a/daemons/lvmlockd/lvmlockd-internal.h
+++ b/daemons/lvmlockd/lvmlockd-internal.h
@@ -50,6 +50,8 @@ enum {
LD_OP_STOP_ALL,
LD_OP_DUMP_INFO,
LD_OP_DUMP_LOG,
+ LD_OP_RENAME_BEFORE,
+ LD_OP_RENAME_FINAL,
};
/* resource types */
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
index b3980d64f..ec7a12b0c 100644
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
@@ -492,6 +492,161 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
return rv;
}
+/*
+ * Read the lockspace and each resource, replace the lockspace name,
+ * and write it back.
+ */
+
+int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
+{
+ struct sanlk_lockspace ss;
+ struct sanlk_resourced rd;
+ struct sanlk_disk disk;
+ char lock_lv_name[MAX_ARGS];
+ uint64_t offset;
+ uint32_t io_timeout;
+ int align_size;
+ int i, rv;
+
+ memset(&disk, 0, sizeof(disk));
+ memset(lock_lv_name, 0, sizeof(lock_lv_name));
+
+ if (!vg_args || !vg_args[0] || !strcmp(vg_args, "none")) {
+ log_error("S %s rename_vg_san vg_args missing", ls_name);
+ return -EINVAL;
+ }
+
+ rv = lock_lv_name_from_args(vg_args, lock_lv_name);
+ if (rv < 0) {
+ log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
+ ls_name, rv, vg_args);
+ return rv;
+ }
+
+ snprintf(disk.path, SANLK_PATH_LEN, "/dev/mapper/%s-%s", vg_name, lock_lv_name);
+
+ log_debug("S %s rename_vg_san path %s", ls_name, disk.path);
+
+ if (daemon_test)
+ return 0;
+
+ /* FIXME: remove this, device is not always ready for us here */
+ sleep(1);
+
+ align_size = sanlock_align(&disk);
+ if (align_size <= 0) {
+ log_error("S %s rename_vg_san bad align size %d %s",
+ ls_name, align_size, disk.path);
+ return -EINVAL;
+ }
+
+ /*
+ * Lockspace
+ */
+
+ memset(&ss, 0, sizeof(ss));
+ memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
+ ss.host_id_disk.offset = LS_BEGIN * align_size;
+
+ rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
+ if (rv < 0) {
+ log_error("S %s rename_vg_san read_lockspace error %d %s",
+ ls_name, rv, ss.host_id_disk.path);
+ return rv;
+ }
+
+ strncpy(ss.name, ls_name, SANLK_NAME_LEN);
+
+ rv = sanlock_write_lockspace(&ss, 0, 0, 0);
+ if (rv < 0) {
+ log_error("S %s rename_vg_san write_lockspace error %d %s",
+ ls_name, rv, ss.host_id_disk.path);
+ return rv;
+ }
+
+ /*
+ * GL resource
+ */
+
+ memset(&rd, 0, sizeof(rd));
+ memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
+ rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
+ rd.rs.num_disks = 1;
+
+ rv = sanlock_read_resource(&rd.rs, 0);
+ if (rv < 0) {
+ log_error("S %s rename_vg_san read_resource gl error %d %s",
+ ls_name, rv, rd.rs.disks[0].path);
+ return rv;
+ }
+
+ strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
+
+ rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
+ if (rv < 0) {
+ log_error("S %s rename_vg_san write_resource gl error %d %s",
+ ls_name, rv, rd.rs.disks[0].path);
+ return rv;
+ }
+
+ /*
+ * VG resource
+ */
+
+ memset(&rd, 0, sizeof(rd));
+ memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
+ rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
+ rd.rs.num_disks = 1;
+
+ rv = sanlock_read_resource(&rd.rs, 0);
+ if (rv < 0) {
+ log_error("S %s rename_vg_san write_resource vg error %d %s",
+ ls_name, rv, rd.rs.disks[0].path);
+ return rv;
+ }
+
+ strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
+
+ rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
+ if (rv < 0) {
+ log_error("S %s rename_vg_san write_resource vg error %d %s",
+ ls_name, rv, rd.rs.disks[0].path);
+ return rv;
+ }
+
+ /*
+ * LV resources
+ */
+
+ offset = align_size * LV_LOCK_BEGIN;
+
+ for (i = 0; i < LVMLOCKD_SANLOCK_MAX_LVS_IN_VG; i++) {
+ memset(&rd, 0, sizeof(rd));
+ memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
+ rd.rs.disks[0].offset = offset;
+ rd.rs.num_disks = 1;
+
+ rv = sanlock_read_resource(&rd.rs, 0);
+ if (rv < 0) {
+ log_error("S %s rename_vg_san read_resource resource area %llu error %d",
+ ls_name, (unsigned long long)offset, rv);
+ break;
+ }
+
+ strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
+
+ rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
+ if (rv) {
+ log_error("S %s rename_vg_san write_resource resource area %llu error %d",
+ ls_name, (unsigned long long)offset, rv);
+ break;
+ }
+ offset += align_size;
+ }
+
+ return 0;
+}
+
/* lvremove */
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
{
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index 521f937c1..ab24dae6a 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -12,6 +12,7 @@
#include "toolcontext.h"
#include "metadata.h"
#include "segtype.h"
+#include "activate.h"
#include "lvmetad.h"
#include "lvmlockd.h"
#include "lvmcache.h"
@@ -1947,3 +1948,128 @@ int lockd_update_local(struct cmd_context *cmd)
return ret;
}
+
+int lockd_rename_vg_before(struct cmd_context *cmd, struct volume_group *vg)
+{
+ struct lv_list *lvl;
+ daemon_reply reply;
+ int result;
+ int ret;
+
+ if (!is_lockd_type(vg->lock_type))
+ return 1;
+
+ if (lvs_in_vg_activated(vg)) {
+ log_error("LVs must be inactive before vgrename.");
+ return 0;
+ }
+
+ /* Check that no LVs are active on other hosts. */
+
+ dm_list_iterate_items(lvl, &vg->lvs) {
+ if (!lockd_lv(cmd, lvl->lv, "ex", 0)) {
+ log_error("LV %s/%s must be inactive on all hosts before vgrename.",
+ vg->name, lvl->lv->name);
+ return 0;
+ }
+
+ if (!lockd_lv(cmd, lvl->lv, "un", 0)) {
+ log_error("Failed to unlock LV %s/%s.", vg->name, lvl->lv->name);
+ return 0;
+ }
+ }
+
+ /*
+ * lvmlockd:
+ * checks for other hosts in lockspace
+ * leaves the lockspace
+ */
+
+ reply = _lockd_send("rename_vg_before",
+ "pid = %d", getpid(),
+ "vg_name = %s", vg->name,
+ "vg_lock_type = %s", vg->lock_type,
+ "vg_lock_args = %s", vg->lock_args,
+ NULL);
+
+ if (!_lockd_result(reply, &result, NULL)) {
+ ret = 0;
+ } else {
+ ret = (result < 0) ? 0 : 1;
+ }
+
+ daemon_reply_destroy(reply);
+
+ if (!ret) {
+ log_error("lockd_rename_vg_before lvmlockd result %d", result);
+ return 0;
+ }
+
+ if (!strcmp(vg->lock_type, "sanlock")) {
+ log_debug("lockd_rename_vg_before deactivate sanlock lv");
+ _deactivate_sanlock_lv(cmd, vg);
+ }
+
+ return 1;
+}
+
+int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int success)
+{
+ daemon_reply reply;
+ int result;
+ int ret;
+
+ if (!is_lockd_type(vg->lock_type))
+ return 1;
+
+ if (!success) {
+ /*
+ * Depending on the problem that caused the rename to
+ * fail, it may make sense to not restart the VG here.
+ */
+ if (!lockd_start_vg(cmd, vg))
+ log_error("Failed to restart VG %s lockspace.", vg->name);
+ return 1;
+ }
+
+ if (!strcmp(vg->lock_type, "sanlock")) {
+ if (!_activate_sanlock_lv(cmd, vg))
+ return 0;
+
+ /*
+ * lvmlockd needs to rewrite the leases on disk
+ * with the new VG (lockspace) name.
+ */
+ reply = _lockd_send("rename_vg_final",
+ "pid = %d", getpid(),
+ "vg_name = %s", vg->name,
+ "vg_lock_type = %s", vg->lock_type,
+ "vg_lock_args = %s", vg->lock_args,
+ NULL);
+
+ if (!_lockd_result(reply, &result, NULL)) {
+ ret = 0;
+ } else {
+ ret = (result < 0) ? 0 : 1;
+ }
+
+ daemon_reply_destroy(reply);
+
+ if (!ret) {
+ /*
+ * The VG has been renamed on disk, but renaming the
+ * sanlock leases failed. Cleaning this up can
+ * probably be done by converting the VG to lock_type
+ * none, then converting back to sanlock.
+ */
+ log_error("lockd_rename_vg_final lvmlockd result %d", result);
+ return 0;
+ }
+ }
+
+ if (!lockd_start_vg(cmd, vg))
+ log_error("Failed to start VG %s lockspace.", vg->name);
+
+ return 1;
+}
+
diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h
index 19c3d6146..5374204e5 100644
--- a/lib/locking/lvmlockd.h
+++ b/lib/locking/lvmlockd.h
@@ -99,6 +99,11 @@ int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg);
int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg);
void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg);
+/* vgrename */
+
+int lockd_rename_vg_before(struct cmd_context *cmd, struct volume_group *vg);
+int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int success);
+
/* start and stop the lockspace for a vg */
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg);
@@ -144,6 +149,9 @@ int lockd_init_lv_args(struct cmd_context *cmd, struct volume_group *vg,
#define lockd_free_vg_before(cmd, vg) (1)
#define lockd_free_vg_final(cmd, vg) do { } while (0)
+#define lockd_rename_vg_before(cmd, vg) (1)
+#define lockd_rename_vg_final(cmd, vg, success) (1)
+
#define lockd_start_vg(cmd, vg) (1)
#define lockd_stop_vg(cmd, vg) (1)
#define lockd_start_wait(cmd) (1)
diff --git a/man/lvmlockd.8.in b/man/lvmlockd.8.in
index 39deda32f..1dfa1b0a4 100644
--- a/man/lvmlockd.8.in
+++ b/man/lvmlockd.8.in
@@ -588,8 +588,6 @@ Things that do not yet work in lockd VGs:
.br
- splitting raid1 mirror LVs
.br
-- vgrename
-.br
- vgsplit
.br
- vgmerge
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 438cbc63f..c0ed348c2 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -29,12 +29,6 @@ static struct volume_group *_get_old_vg_for_rename(struct cmd_context *cmd,
return_NULL;
}
- if (is_lockd_type(vg->lock_type)) {
- log_error("vgrename not allowed for lock_type %s", vg->lock_type);
- unlock_and_release_vg(cmd, vg, vg_name_old);
- return NULL;
- }
-
return vg;
}
@@ -120,6 +114,9 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
} else
vgid = NULL;
+ if (!lockd_vg(cmd, vg_name_old, "ex", 0))
+ return_0;
+
if (strcmp(vg_name_new, vg_name_old) < 0)
lock_vg_old_first = 0;
@@ -150,6 +147,9 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
if (!drop_cached_metadata(vg))
stack;
+ if (!lockd_rename_vg_before(cmd, vg))
+ return_0;
+
/* Change the volume group name */
vg_rename(cmd, vg, vg_name_new);
@@ -177,6 +177,8 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
}
}
+ lockd_rename_vg_final(cmd, vg, 1);
+
if (!backup(vg))
stack;
if (!backup_remove(cmd, vg_name_old))
@@ -196,6 +198,8 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
return 1;
error:
+ lockd_rename_vg_final(cmd, vg, 0);
+
if (lock_vg_old_first) {
unlock_vg(cmd, vg_name_new);
unlock_and_release_vg(cmd, vg, vg_name_old);