summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2014-11-18 13:56:40 -0600
committerDavid Teigland <teigland@redhat.com>2015-02-27 13:44:55 -0600
commit873f9ba08044d64ac49b6a44753b31403894adc4 (patch)
treebd7dccfc2bd1894c5625ab6a22cc5e0e039e4f2c
parentbb4c66620630e83b2c7f7c95e501504f2487da74 (diff)
downloadlvm2-873f9ba08044d64ac49b6a44753b31403894adc4.tar.gz
lvmlockd: start and stop VG lockspace
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/config/config_settings.h1
-rw-r--r--lib/locking/lvmlockd.c171
-rw-r--r--lib/locking/lvmlockd.h8
-rw-r--r--tools/args.h2
-rw-r--r--tools/commands.h2
-rw-r--r--tools/vgchange.c24
-rw-r--r--tools/vgcreate.c4
7 files changed, 206 insertions, 6 deletions
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index c575b2e32..acbe712ba 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -287,5 +287,6 @@ cfg(tag_host_list_CFG, "host_list", tag_CFG_SUBSECTION, CFG_ALLOW_EMPTY | CFG_DE
cfg(local_system_id_CFG, "system_id", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL)
cfg_array(local_extra_system_ids_CFG, "extra_system_ids", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL)
+cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(2, 2, 112), NULL)
cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL)
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index d3349b701..db84a29d1 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -539,11 +539,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.
- * lockd_stop_vg(cmd, vg);
- */
+ /* Leave the dlm lockspace. */
+ lockd_stop_vg(cmd, vg);
return 1;
}
@@ -702,3 +699,167 @@ void lockd_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 lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg)
+{
+ char uuid[64] __attribute__((aligned(8)));
+ daemon_reply reply;
+ const char *lock_type;
+ int host_id = 0;
+ int result;
+ int ret;
+
+ memset(uuid, 0, sizeof(uuid));
+
+ /*
+ * We do not skip non-lockd 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("lockd_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;
+
+ host_id = find_config_tree_int(cmd, local_host_id_CFG, NULL);
+ }
+
+ id_write_format(&vg->id, uuid, sizeof(uuid));
+
+ if (!is_lockd_type(vg->lock_type)) {
+ const char *sysid = NULL;
+
+ if (vg->system_id && (strlen(vg->system_id) > 0))
+ sysid = vg->system_id;
+
+ reply = _lockd_send("add_local",
+ "pid = %d", getpid(),
+ "vg_name = %s", vg->name,
+ "vg_uuid = %s", uuid[0] ? uuid : "none",
+ "vg_sysid = %s", sysid ?: "none",
+ "our_system_id = %s", cmd->system_id ?: "none",
+ NULL);
+
+ lock_type = "local";
+ } else {
+ reply = _lockd_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,
+ "host_id = %d", host_id,
+ NULL);
+
+ lock_type = vg->lock_type;
+ }
+
+ if (!_lockd_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("lockd_start_vg %s done", vg->name);
+
+out:
+ daemon_reply_destroy(reply);
+
+ return ret;
+}
+
+int lockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg)
+{
+ daemon_reply reply;
+ int result;
+ int ret;
+
+ if (!is_lockd_type(vg->lock_type))
+ return 1;
+
+ if (!_lvmlockd_active)
+ return 1;
+ if (!lvmlockd_connected())
+ return 0;
+
+ log_debug("lockd_stop_vg %s lock_type %s", vg->name,
+ vg->lock_type ? vg->lock_type : "empty");
+
+ reply = _lockd_send("stop_vg",
+ "pid = %d", getpid(),
+ "vg_name = %s", vg->name,
+ NULL);
+
+ if (!_lockd_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("lockd_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 c7374d6d0..e35ec0d1e 100644
--- a/lib/locking/lvmlockd.h
+++ b/lib/locking/lvmlockd.h
@@ -78,6 +78,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);
+/* start and stop the lockspace for a vg */
+
+int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg);
+int lockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg);
+
#else /* LVMLOCKD_SUPPORT */
#define lvmlockd_init(cmd) do { } while (0)
@@ -91,6 +96,9 @@ void lockd_free_vg_final(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_start_vg(cmd, vg) (1)
+#define lockd_stop_vg(cmd, vg) (1)
+
#endif /* LVMLOCKD_SUPPORT */
#endif
diff --git a/tools/args.h b/tools/args.h
index 0a6778432..76f54de8e 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -48,6 +48,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 a89a8ab1a..3891fb373 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -988,7 +988,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, select_ARG, sysinit_ARG,
- systemid_ARG, test_ARG, uuid_ARG)
+ systemid_ARG, test_ARG, uuid_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 199ee8255..c871f45bd 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -556,9 +556,23 @@ static int _vgchange_system_id(struct cmd_context *cmd, struct volume_group *vg)
vg->system_id = system_id;
+ /* update system_id in lvmlockd's record for this vg */
+ if (!lockd_start_vg(cmd, vg))
+ log_debug("Failed to update lvmlockd.");
+
return 1;
}
+static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg)
+{
+ return lockd_start_vg(cmd, vg);
+}
+
+static int _vgchange_lock_stop(struct cmd_context *cmd, struct volume_group *vg)
+{
+ return lockd_stop_vg(cmd, vg);
+}
+
static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg,
struct processing_handle *handle __attribute__((unused)))
@@ -673,6 +687,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))
+ return_ECMD_FAILED;
+ } else if (arg_is_set(cmd, lockstop_ARG)) {
+ if (!_vgchange_lock_stop(cmd, vg))
+ return_ECMD_FAILED;
+ }
+
return ret;
}
@@ -680,6 +702,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 6d46d727b..52dcfd48a 100644
--- a/tools/vgcreate.c
+++ b/tools/vgcreate.c
@@ -135,6 +135,10 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
clustered_message, *clustered_message ? 'v' : 'V', vg->name,
vg->system_id ? " with system ID " : "", vg->system_id ? : "");
+ /* Start the VG lockspace because it will likely be used right away. */
+ if (!lockd_start_vg(cmd, vg))
+ log_error("Failed to start locking");
+
release_vg(vg);
return ECMD_PROCESSED;