summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2014-11-18 13:56:40 -0600
committerDavid Teigland <teigland@redhat.com>2014-11-18 15:38:13 -0600
commit5cda7079816aa5c5651f59c2c5bc15cfff651a15 (patch)
tree63e009d67eefd47e43bc3a47f7f0448d1ed2556e
parent250737991a85d661c9889a7d6283f1401dc574c9 (diff)
downloadlvm2-dev-dct-lvmlockd5-startstop.tar.gz
lvmlockd: start and stop VG lockspacedev-dct-lvmlockd5-startstop
A lock manager requires an application to "start" or "join" a lockspace before using locks from it. Start is the point at which the lock manager on a host begins interacting with other hosts to coordinate access to locks in the lockspace. Similarly, an application needs to "stop" or "leave" a lockspace when it's done using locks from the lockspace so the lock manager can shut down and clean up the lockspace. lvmlockd uses a lockspace for each sanlock|dlm VG, and the lockspace for each VG needs to be started before lvm can use it. These commands tell lvmlockd to start or stop the lockspace for a VG: vgchange --lock-start vg_name vgchange --lock-stop vg_name To start the lockspace for a VG, lvmlockd needs to know which lock manager (sanlock or dlm) to use, and this is stored in the VG metadata as lock_type = "sanlock|dlm", along with data that is specific to the lock manager for the VG, saved as lock_args. For sanlock, lock_args is the location of the locks on disk. For dlm, lock_args is the name of the cluster the dlm should use. So, the process for starting a VG includes: - Reading the VG without a lock (no lock can be acquired because the lockspace is not started). - Taking the lock_type and lock_args strings from the VG metadata. - Asking lvmlockd to start the VG lockspace, providing the lock_type and lock_args strings which tell lvmlockd exactly which lock manager is needed. - lvmlockd will ask the specific lock manager to join the lockspace. The VG read in the first step, without a lock, is not used for for anything except getting the lock information needed to start the lockspace. Subsequent use of the VG would use the VG lock. In the case of a sanlock VG, there is an additional step in the sequence. Between the second and third steps, the vgchange lock-start command needs to activate the internal LV in the VG that holds the sanlock locks. This LV must be active before sanlock can join the lockspace. Starting and stopping VG's would typically be done automatically by the system, similar to the way LV's are automatically activated by the system. But, it is always possible to directly start/stop VG lockspaces, as it is always possible to directly activate/deactivate LVs. Automatic VG start/stop will be added by a later patch, using the basic functionality from this patch.
-rw-r--r--lib/locking/lvmlockd.c166
-rw-r--r--lib/locking/lvmlockd.h9
-rw-r--r--tools/args.h2
-rw-r--r--tools/commands.h2
-rw-r--r--tools/vgchange.c25
-rw-r--r--tools/vgcreate.c4
6 files changed, 202 insertions, 6 deletions
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index 6f392d994..29b72390f 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -545,11 +545,8 @@ static int _free_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
return 0;
}
- /*
- * Leave the dlm lockspace.
- * Joining and leaving the lockspaces to be added by later patch.
- * lvmlockd_stop_vg(cmd, vg);
- */
+ /* Leave the dlm lockspace. */
+ lvmlockd_stop_vg(cmd, vg);
return 1;
}
@@ -707,3 +704,162 @@ void lvmlockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg)
}
}
+/*
+ * Starting a vg involves:
+ * 1. reading the vg without a lock
+ * 2. getting the lock_type/lock_args from the vg metadata
+ * 3. doing start_vg in lvmlockd for the lock_type;
+ * this means joining the lockspace
+ *
+ * The vg read in step 1 should not be used for anything
+ * other than getting the lock_type/lock_args/uuid necessary
+ * for starting the lockspace. To use the vg after starting
+ * the lockspace, follow the standard method which is:
+ * lock the vg, read/use/write the vg, unlock the vg.
+ */
+
+int lvmlockd_start_vg(struct cmd_context *cmd, struct volume_group *vg)
+{
+ char uuid[64] __attribute__((aligned(8)));
+ daemon_reply reply;
+ const char *lock_type;
+ int result;
+ int ret;
+
+ memset(uuid, 0, sizeof(uuid));
+
+ /*
+ * We do not skip non-dlock vg's here (see add_local below).
+ * We use this to ensure lvmlockd has seen the local vg.
+ * It is an optimization in case lvmlockd has not seen the
+ * local vg yet.
+ */
+
+ if (!_lvmlockd_active)
+ return 1;
+ if (!lvmlockd_connected())
+ return 0;
+
+ /* Skip starting the vg lockspace when the vg lock is skipped. */
+
+ /* Added in a later patch. */
+ /*
+ if (cmd_mode && !strcmp(cmd_mode, "na"))
+ return 1;
+ */
+
+ log_debug("lvmlockd_start_vg %s lock_type %s", vg->name,
+ vg->lock_type ? vg->lock_type : "empty");
+
+ if (vg->lock_type && !strcmp(vg->lock_type, "sanlock")) {
+ /*
+ * This is the big difference between starting
+ * sanlock vgs vs starting dlm vgs: the internal
+ * sanlock lv needs to be activated before lvmlockd
+ * does the start because sanlock needs to use the lv
+ * to access locks.
+ */
+ if (!_activate_sanlock_lv(cmd, vg))
+ return 0;
+ }
+
+ id_write_format(&vg->id, uuid, sizeof(uuid));
+
+ if (!is_dlock_type(vg->lock_type)) {
+ char *sysid = NULL;
+
+ if (vg->system_id && (strlen(vg->system_id) > 0))
+ sysid = vg->system_id;
+
+ reply = _lvmlockd_send("add_local",
+ "pid = %d", getpid(),
+ "vg_name = %s", vg->name,
+ "vg_uuid = %s", uuid[0] ? uuid : "none",
+ "vg_sysid = %s", sysid ?: "none",
+ NULL);
+
+ lock_type = "local";
+ } else {
+ reply = _lvmlockd_send("start_vg",
+ "pid = %d", getpid(),
+ "vg_name = %s", vg->name,
+ "vg_lock_type = %s", vg->lock_type,
+ "vg_lock_args = %s", vg->lock_args,
+ "vg_uuid = %s", uuid[0] ? uuid : "none",
+ "version = %d", (int64_t)vg->seqno,
+ NULL);
+
+ lock_type = vg->lock_type;
+ }
+
+ if (!_lvmlockd_result(reply, &result, NULL)) {
+ result = -1;
+ ret = 0;
+ } else {
+ ret = (result < 0) ? 0 : 1;
+ }
+
+ if (result == -EEXIST) {
+ ret = 1;
+ goto out;
+ }
+
+ if (!ret)
+ log_error("Locking start %s VG %s %d", lock_type, vg->name, result);
+ else
+ log_debug("lvmlockd_start_vg %s done", vg->name);
+
+out:
+ daemon_reply_destroy(reply);
+
+ return ret;
+}
+
+int lvmlockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg)
+{
+ daemon_reply reply;
+ int result;
+ int ret;
+
+ if (!is_dlock_type(vg->lock_type))
+ return 1;
+
+ if (!_lvmlockd_active)
+ return 1;
+ if (!lvmlockd_connected())
+ return 0;
+
+ log_debug("lvmlockd_stop_vg %s lock_type %s", vg->name,
+ vg->lock_type ? vg->lock_type : "empty");
+
+ reply = _lvmlockd_send("stop_vg",
+ "pid = %d", getpid(),
+ "vg_name = %s", vg->name,
+ NULL);
+
+ if (!_lvmlockd_result(reply, &result, NULL)) {
+ ret = 0;
+ } else {
+ ret = (result < 0) ? 0 : 1;
+ }
+
+ if (result == -EBUSY) {
+ log_error("Cannot stop locking in busy VG %s", vg->name);
+ goto out;
+ }
+
+ if (!ret) {
+ log_error("Locking stop %s VG %s %d", vg->lock_type, vg->name, result);
+ goto out;
+ }
+
+ if (!strcmp(vg->lock_type, "sanlock")) {
+ log_debug("lvmlockd_stop_vg deactivate sanlock lv");
+ _deactivate_sanlock_lv(cmd, vg);
+ }
+out:
+ daemon_reply_destroy(reply);
+
+ return ret;
+}
+
diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h
index f2ab1a826..2aeaaee7d 100644
--- a/lib/locking/lvmlockd.h
+++ b/lib/locking/lvmlockd.h
@@ -91,6 +91,12 @@ int lvmlockd_init_vg(struct cmd_context *cmd, struct volume_group *vg);
int lvmlockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg);
void lvmlockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg);
+/* start and stop the lockspace for a vg */
+
+int lvmlockd_start_vg(struct cmd_context *cmd, struct volume_group *vg);
+int lvmlockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg);
+
+
#else /* LVMLOCKD_SUPPORT */
#define lvmlockd_init(cmd) do { } while (0)
@@ -106,6 +112,9 @@ void lvmlockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg);
#define lvmlockd_free_vg_before(cmd, vg) (0)
#define lvmlockd_free_vg_final(cmd, vg) do { } while (0)
+#define lvmlockd_start_vg(cmd, vg) (1)
+#define lvmlockd_stop_vg(cmd, vg) (1)
+
#endif /* LVMLOCKD_SUPPORT */
#endif
diff --git a/tools/args.h b/tools/args.h
index 5a2230ad8..afa4ce6f5 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -47,6 +47,8 @@ arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0)
arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", NULL, 0)
arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", NULL, 0)
arg(labelsector_ARG, '\0', "labelsector", int_arg, 0)
+arg(lockstart_ARG, '\0', "lock-start", string_arg, 0)
+arg(lockstop_ARG, '\0', "lock-stop", string_arg, 0)
arg(locktype_ARG, '\0', "lock-type", string_arg, 0)
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", size_kb_arg, 0)
arg(merge_ARG, '\0', "merge", NULL, 0)
diff --git a/tools/commands.h b/tools/commands.h
index 563200428..4f0e4cfd0 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -959,7 +959,7 @@ xx(vgchange,
metadataprofile_ARG, monitor_ARG, noudevsync_ARG, metadatacopies_ARG,
vgmetadatacopies_ARG, partial_ARG, physicalextentsize_ARG, poll_ARG,
refresh_ARG, resizeable_ARG, resizable_ARG, sysinit_ARG, test_ARG, uuid_ARG,
- systemid_ARG, systemidsource_ARG)
+ systemid_ARG, systemidsource_ARG, lockstart_ARG, lockstop_ARG)
xx(vgck,
"Check the consistency of volume group(s)",
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 5dac6eda9..f3e7aaa5a 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -521,9 +521,24 @@ change:
}
vg->system_id = system_id;
+
+ /* update system_id in lvmlockd's record for this vg */
+ lvmlockd_start_vg(cmd, vg);
+
return 1;
}
+static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg,
+ int auto_opt)
+{
+ return lvmlockd_start_vg(cmd, vg);
+}
+
+static int _vgchange_lock_stop(struct cmd_context *cmd, struct volume_group *vg)
+{
+ return lvmlockd_stop_vg(cmd, vg);
+}
+
static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg,
void *handle __attribute__((unused)))
@@ -639,6 +654,14 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
if (!_vgchange_background_polling(cmd, vg))
return_ECMD_FAILED;
+ if (arg_is_set(cmd, lockstart_ARG)) {
+ if (!_vgchange_lock_start(cmd, vg, 0))
+ return_ECMD_FAILED;
+ } else if (arg_is_set(cmd, lockstop_ARG)) {
+ if (!_vgchange_lock_stop(cmd, vg))
+ return_ECMD_FAILED;
+ }
+
return ret;
}
@@ -646,6 +669,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
{
int noupdate =
arg_count(cmd, activate_ARG) ||
+ arg_count(cmd, lockstart_ARG) ||
+ arg_count(cmd, lockstop_ARG) ||
arg_count(cmd, monitor_ARG) ||
arg_count(cmd, poll_ARG) ||
arg_count(cmd, refresh_ARG);
diff --git a/tools/vgcreate.c b/tools/vgcreate.c
index 7c6d9187e..5afffd857 100644
--- a/tools/vgcreate.c
+++ b/tools/vgcreate.c
@@ -134,6 +134,10 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
log_print_unless_silent("%s%colume group \"%s\" successfully created",
clustered_message, *clustered_message ? 'v' : 'V', vg->name);
+ /* Start the VG lockspace because it will likely be used right away. */
+ if (!lvmlockd_start_vg(cmd, vg))
+ log_error("Failed to start locking");
+
release_vg(vg);
return ECMD_PROCESSED;