summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-05-13 15:03:21 -0500
committerDavid Teigland <teigland@redhat.com>2015-05-28 16:34:36 -0500
commit0e76602814ec02c033a2705f625d4f4f0a679ad9 (patch)
tree0786ba34663cbc19805d3c5a2e4b5cfda18e2ed2
parent3cda1ce866f30f870ca1b68de65f00a25aded62c (diff)
downloadlvm2-0e76602814ec02c033a2705f625d4f4f0a679ad9.tar.gz
tools: use locks from lvmlockd
-rw-r--r--tools/lvchange.c30
-rw-r--r--tools/lvcreate.c9
-rw-r--r--tools/lvrename.c6
-rw-r--r--tools/lvresize.c6
-rw-r--r--tools/lvscan.c3
-rw-r--r--tools/pvchange.c7
-rw-r--r--tools/pvcreate.c3
-rw-r--r--tools/pvdisplay.c3
-rw-r--r--tools/pvremove.c3
-rw-r--r--tools/pvresize.c7
-rw-r--r--tools/pvscan.c6
-rw-r--r--tools/reporter.c3
-rw-r--r--tools/toollib.c291
-rw-r--r--tools/vgchange.c372
-rw-r--r--tools/vgcreate.c16
-rw-r--r--tools/vgextend.c3
-rw-r--r--tools/vgmerge.c12
-rw-r--r--tools/vgreduce.c11
-rw-r--r--tools/vgremove.c8
-rw-r--r--tools/vgrename.c23
-rw-r--r--tools/vgscan.c3
-rw-r--r--tools/vgsplit.c16
22 files changed, 765 insertions, 76 deletions
diff --git a/tools/lvchange.c b/tools/lvchange.c
index e790ea06b..57b96bb5c 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -601,6 +601,9 @@ static int _lvchange_persistent(struct cmd_context *cmd,
{
enum activation_change activate = CHANGE_AN;
+ /* The LV lock in lvmlockd should remain as it is. */
+ cmd->lockd_lv_disable = 1;
+
if (!get_and_validate_major_minor(cmd, lv->vg->fid->fmt,
&lv->major, &lv->minor))
return_0;
@@ -984,6 +987,22 @@ static int _lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
+ if (!arg_count(cmd, activate_ARG) && !arg_count(cmd, refresh_ARG)) {
+ /*
+ * If a persistent lv lock already exists from activation
+ * (with the needed mode or higher), this will be a no-op.
+ * Otherwise, the lv lock will be taken as non-persistent
+ * and released when this command exits.
+ *
+ * TODO: use "sh" if the options imply that the lvchange
+ * operation does not modify the LV.
+ */
+ if (!lockd_lv(cmd, lv, "ex", 0)) {
+ stack;
+ return ECMD_FAILED;
+ }
+ }
+
/*
* FIXME: DEFAULT_BACKGROUND_POLLING should be "unspecified".
* If --poll is explicitly provided use it; otherwise polling
@@ -1257,6 +1276,17 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, activate_ARG))
cmd->include_active_foreign_vgs = 1;
+ /*
+ * The default vg lock mode for lvchange is ex, but these options
+ * are cases where lvchange does not modify the vg, so they can use
+ * the sh lock mode.
+ */
+ if (arg_count(cmd, activate_ARG) || arg_count(cmd, refresh_ARG))
+ cmd->lockd_vg_default_sh = 1;
+
+ if (arg_tag_count(argc, argv) && !lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
return process_each_lv(cmd, argc, argv,
update ? READ_FOR_UPDATE : 0, NULL,
&_lvchange_single);
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index e41f76ccb..d1b95a6cf 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -1453,6 +1453,7 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
};
struct lvcreate_cmdline_params lcp = { 0 };
struct volume_group *vg;
+ uint32_t lockd_state;
if (!_lvcreate_params(cmd, argc, argv, &lp, &lcp)) {
stack;
@@ -1464,8 +1465,11 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (!lockd_vg(cmd, lp.vg_name, "ex", 0, &lockd_state))
+ return_ECMD_FAILED;
+
log_verbose("Finding volume group \"%s\"", lp.vg_name);
- vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
+ vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0, lockd_state);
if (vg_read_error(vg)) {
release_vg(vg);
return_ECMD_FAILED;
@@ -1517,6 +1521,9 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
lp.snapshot ? " as snapshot of " : "",
lp.snapshot ? lp.origin_name : "", lp.segtype->name);
+ if (vg->lock_type && !(lp.lock_type = dm_pool_strdup(cmd->mem, vg->lock_type)))
+ goto_out;
+
if (!lv_create_single(vg, &lp))
goto_out;
diff --git a/tools/lvrename.c b/tools/lvrename.c
index eeff76da2..6bbf31bf7 100644
--- a/tools/lvrename.c
+++ b/tools/lvrename.c
@@ -27,6 +27,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
char *st;
struct volume_group *vg;
struct lv_list *lvl;
+ uint32_t lockd_state;
int r = ECMD_FAILED;
if (argc == 3) {
@@ -98,8 +99,11 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (!lockd_vg(cmd, vg_name, "ex", 0, &lockd_state))
+ return_ECMD_FAILED;
+
log_verbose("Checking for existing volume group \"%s\"", vg_name);
- vg = vg_read_for_update(cmd, vg_name, NULL, 0);
+ vg = vg_read_for_update(cmd, vg_name, NULL, 0, lockd_state);
if (vg_read_error(vg)) {
release_vg(vg);
return_ECMD_FAILED;
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 08248bbec..30ac4f987 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -169,13 +169,17 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
struct volume_group *vg;
struct dm_list *pvh = NULL;
struct logical_volume *lv;
+ uint32_t lockd_state;
int r = ECMD_FAILED;
if (!_lvresize_params(cmd, argc, argv, &lp))
return EINVALID_CMD_LINE;
+ if (!lockd_vg(cmd, lp.vg_name, "ex", 0, &lockd_state))
+ return_ECMD_FAILED;
+
log_verbose("Finding volume group %s", lp.vg_name);
- vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
+ vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0, lockd_state);
if (vg_read_error(vg)) {
release_vg(vg);
return_ECMD_FAILED;
diff --git a/tools/lvscan.c b/tools/lvscan.c
index e98c73d00..4042204fb 100644
--- a/tools/lvscan.c
+++ b/tools/lvscan.c
@@ -98,6 +98,9 @@ int lvscan(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (!lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
return process_each_lv(cmd, argc, argv, 0, NULL,
&lvscan_single);
}
diff --git a/tools/pvchange.c b/tools/pvchange.c
index 3e0894f61..1b5e2a43f 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -82,6 +82,10 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
}
}
+ /* Convert sh to ex. gl only needed for orphans. */
+ if (is_orphan(pv) && !lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+
if (tagargs) {
/* tag or deltag */
if (arg_count(cmd, addtag_ARG) && !change_tag(cmd, NULL, NULL, pv, addtag_ARG))
@@ -191,6 +195,9 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv)
goto out;
}
+ if (!lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
if (!argc) {
/*
* Take the global lock here so the lvmcache remains
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index 139819883..8b4730103 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -96,6 +96,9 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
int ret = ECMD_PROCESSED;
struct pvcreate_params pp;
+ if (!lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+
pvcreate_params_set_defaults(&pp);
if (!pvcreate_restore_params_validate(cmd, argc, argv, &pp)) {
diff --git a/tools/pvdisplay.c b/tools/pvdisplay.c
index 2763889a9..b72651e04 100644
--- a/tools/pvdisplay.c
+++ b/tools/pvdisplay.c
@@ -107,6 +107,9 @@ int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
}
}
+ if (!lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
ret = process_each_pv(cmd, argc, argv, NULL, 0, NULL,
_pvdisplay_single);
diff --git a/tools/pvremove.c b/tools/pvremove.c
index b40ff794a..1baf1ac5e 100644
--- a/tools/pvremove.c
+++ b/tools/pvremove.c
@@ -32,6 +32,9 @@ int pvremove(struct cmd_context *cmd, int argc, char **argv)
dm_list_init(&pv_names);
+ if (!lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+
for (i = 0; i < argc; i++) {
dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
if (!str_list_add(cmd->mem, &pv_names, argv[i]))
diff --git a/tools/pvresize.c b/tools/pvresize.c
index 3057a7fb9..a86ddd4da 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -36,6 +36,10 @@ static int _pvresize_single(struct cmd_context *cmd,
}
params->total++;
+ /* Convert sh to ex. gl is only needed for orphans. */
+ if (is_orphan(pv) && !lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+
if (!pv_resize_single(cmd, vg, pv, params->new_size))
return_ECMD_FAILED;
@@ -76,6 +80,9 @@ int pvresize(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &params;
+ if (!lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
ret = process_each_pv(cmd, argc, argv, NULL, READ_FOR_UPDATE, handle,
_pvresize_single);
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 2c997b7f4..7f6c34de8 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -106,7 +106,7 @@ static int _auto_activation_handler(struct cmd_context *cmd,
return_0;
/* NB. This is safe because we know lvmetad is running and we won't hit disk. */
- vg = vg_read(cmd, vgname, (const char *)&vgid_raw, 0);
+ vg = vg_read(cmd, vgname, (const char *)&vgid_raw, 0, 0);
if (vg_read_error(vg)) {
log_error("Failed to read Volume Group \"%s\" (%s) during autoactivation.", vgname, vgid);
release_vg(vg);
@@ -321,7 +321,6 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
out:
sync_local_dev_names(cmd);
unlock_vg(cmd, VG_GLOBAL);
-
return ret;
}
@@ -371,6 +370,9 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
+ if (!lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
if (cmd->full_filter->wipe)
cmd->full_filter->wipe(cmd->full_filter);
lvmcache_destroy(cmd, 1, 0);
diff --git a/tools/reporter.c b/tools/reporter.c
index eb6a4ed4e..4db40b552 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -629,6 +629,9 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
/* Check PV specifics and do extra changes/actions if needed. */
_check_pv_list(cmd, argc, argv, &report_type, &args_are_pvs);
+ if ((!argc || arg_tag_count(argc, argv)) && !lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
switch (report_type) {
case DEVTYPES:
keys = find_config_tree_str(cmd, report_devtypes_sort_CFG, NULL);
diff --git a/tools/toollib.c b/tools/toollib.c
index ca198dceb..52e6f0f58 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -220,6 +220,12 @@ static int _ignore_vg(struct volume_group *vg, const char *vg_name,
return 1;
}
+ if (read_error & FAILED_LOCK_TYPE) {
+ read_error &= ~FAILED_LOCK_TYPE; /* Check for other errors */
+ log_verbose("Skipping volume group %s", vg_name);
+ *skip = 1;
+ }
+
if (read_error != SUCCESS) {
*skip = 0;
log_error("Cannot process volume group %s", vg_name);
@@ -718,6 +724,12 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
struct vgcreate_params *vp_def)
{
const char *system_id_arg_str;
+ const char *lock_type = NULL;
+ int locking_type;
+ int use_lvmlockd;
+ int use_clvmd;
+ int clustery;
+ int lock_type_num; /* LOCK_TYPE_ */
vp_new->vg_name = skip_dev_dir(cmd, vp_def->vg_name, NULL);
vp_new->max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG,
@@ -730,12 +742,6 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
vp_new->extent_size =
arg_uint_value(cmd, physicalextentsize_ARG, vp_def->extent_size);
- if (arg_count(cmd, clustered_ARG))
- vp_new->clustered = arg_int_value(cmd, clustered_ARG, vp_def->clustered);
- else
- /* Default depends on current locking type */
- vp_new->clustered = locking_is_clustered();
-
if (arg_sign_value(cmd, physicalextentsize_ARG, SIGN_NONE) == SIGN_MINUS) {
log_error(_pe_size_may_not_be_negative_msg);
return 0;
@@ -766,16 +772,9 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
else
vp_new->vgmetadatacopies = find_config_tree_int(cmd, metadata_vgmetadatacopies_CFG, NULL);
- /* A clustered VG has no system ID. */
- if (vp_new->clustered) {
- if (arg_is_set(cmd, systemid_ARG)) {
- log_error("system ID cannot be set on clustered Volume Groups.");
- return 0;
- }
- vp_new->system_id = NULL;
- } else if (!(system_id_arg_str = arg_str_value(cmd, systemid_ARG, NULL)))
+ if (!(system_id_arg_str = arg_str_value(cmd, systemid_ARG, NULL))) {
vp_new->system_id = vp_def->system_id;
- else {
+ } else {
if (!(vp_new->system_id = system_id_from_string(cmd, system_id_arg_str)))
return_0;
@@ -790,6 +789,185 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
}
}
+ if ((system_id_arg_str = arg_str_value(cmd, systemid_ARG, NULL))) {
+ vp_new->system_id = system_id_from_string(cmd, system_id_arg_str);
+ } else {
+ vp_new->system_id = vp_def->system_id;
+ }
+
+ if (system_id_arg_str) {
+ if (!vp_new->system_id || !vp_new->system_id[0])
+ log_warn("WARNING: A VG without a system ID allows unsafe access from other hosts.");
+
+ if (vp_new->system_id && cmd->system_id &&
+ strcmp(vp_new->system_id, cmd->system_id)) {
+ log_warn("VG with system ID %s might become inaccessible as local system ID is %s",
+ vp_new->system_id, cmd->system_id);
+ }
+ }
+
+ /*
+ * Locking: what kind of locking should be used for the
+ * new VG, and is it compatible with current lvm.conf settings.
+ *
+ * The end result is to set vp_new->lock_type to:
+ * none | clvm | dlm | sanlock.
+ *
+ * If --lock-type <arg> is set, the answer is given directly by
+ * <arg> which is one of none|clvm|dlm|sanlock.
+ *
+ * If --clustered y (-cy) is set, then lock_type will be derived
+ * from other settings/config (see selection logic below.)
+ *
+ * Relevant lvm.conf configurations include:
+ *
+ * global/use_lvmlockd = 0, global/locking_type = 1
+ * ------------------------------------------------
+ * - no locking is enabled
+ * - clvmd is not used
+ * - lvmlockd is not used
+ * - VGs with CLUSTERED set are ignored (requires clvmd)
+ * - VGs with lock_type set are ignored (requires lvmlockd)
+ * - vgcreate can create new VGs with lock_type = none
+ *
+ * global/use_lvmlockd = 0, global/locking_type = 3
+ * ------------------------------------------------
+ * - locking through clvmd is enabled (traditional clvm config)
+ * - clvmd is used
+ * - lvmlockd is not used
+ * - VGs with CLUSTERED set can be used
+ * - VGs with lock_type set are ignored (requires lvmlockd)
+ * - vgcreate can create new VGs with CLUSTERED status flag
+ *
+ * global/use_lvmlockd = 1, global/locking_type = 1
+ * ------------------------------------------------
+ * - locking through lvmlockd is enabled (new lvmlockd config)
+ * - clvmd is not used
+ * - lvmlockd is used
+ * - VGs with CLUSTERED set are ignored (requires clvmd)
+ * - VGs with lock_type set can be used
+ * - vgcreate can create new VGs with lock_type (sanlock|dlm)
+ *
+ * VG metadata
+ * -----------
+ *
+ * A VG with lock_type sanlock|dlm has the metadata field:
+ * lock_type = "sanlock" or lock_type = "dlm"
+ *
+ * A VG with lock_type clvm has the metadata status flag CLUSTERED.
+ *
+ * A VG with lock_type none has no lock_type metadata field and
+ * no CLUSTERED status flag.
+ *
+ * A VG with lock_type sanlock|dlm also has a new metadata field
+ * lock_args = "..." where the specific string is set by the
+ * lock manager to lock-manager-specific data.
+ *
+ * deriving lock_type from -c
+ * --------------------------
+ *
+ * The --clustered (-c) option can have varying results depending
+ * on the lvm.conf settings and what is running. The resulting
+ * lock_type (none|clvm|sanlock|dlm) is derived as follows:
+ *
+ * When using lvmlockd:
+ *
+ * 1. --clustered n -> lock_type none
+ *
+ * 2. --clustered y -> lock_type sanlock|dlm based on which is running
+ *
+ * 3. Neither --clustered nor --lock-type specified -> lock_type none
+ *
+ * When using clvmd:
+ *
+ * 1. --clustered n -> lock_type none
+ *
+ * 2. --clustered y -> lock_type clvm
+ *
+ * 3. Neither --clustered nor --lock-type specified -> lock_type clvm
+ *
+ * The historical default is clvm.
+ */
+
+ locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL);
+ use_lvmlockd = find_config_tree_bool(cmd, global_use_lvmlockd_CFG, NULL);
+ use_clvmd = (locking_type == 3);
+
+ if (arg_is_set(cmd, locktype_ARG)) {
+ lock_type = arg_str_value(cmd, locktype_ARG, "");
+
+ } else if (arg_is_set(cmd, clustered_ARG)) {
+ const char *arg_str = arg_str_value(cmd, clustered_ARG, "");
+
+ if (!strcmp(arg_str, "y")) {
+ clustery = 1;
+ } else if (!strcmp(arg_str, "n")) {
+ clustery = 0;
+ } else {
+ log_error("Unknown clustered value");
+ return 0;
+ }
+
+ if (use_lvmlockd && clustery) {
+ if (!(lock_type = lockd_running_lock_type(cmd)))
+ return 0;
+ } else if (use_lvmlockd && !clustery) {
+ lock_type = "none";
+ } else if (use_clvmd && clustery) {
+ lock_type = "clvm";
+ } else if (use_clvmd && !clustery) {
+ lock_type = "none";
+ } else {
+ log_error("clustered vg requires use_lvmlockd or locking_type 3 (clvmd)");
+ return 0;
+ }
+
+ } else {
+ if (use_clvmd)
+ lock_type = locking_is_clustered() ? "clvm" : "none";
+ else if (use_lvmlockd)
+ lock_type = "none";
+
+ /*
+ * lock_type NULL is when there is no --lock-type,
+ * no --clustered, and locking_type is not 3.
+ */
+ if (!lock_type)
+ lock_type = "none";
+ }
+
+ /*
+ * Check that the lock_type is recognized, and is being
+ * used with the correct lvm.conf settings.
+ */
+ lock_type_num = lock_type_to_num(lock_type);
+
+ if (lock_type_num < 0) {
+ log_error("lock_type %s is invalid", lock_type);
+ return 0;
+ } else if ((lock_type_num == LOCK_TYPE_DLM || lock_type_num == LOCK_TYPE_SANLOCK) && !use_lvmlockd) {
+ log_error("lock_type %s requires use_lvmlockd configuration setting", lock_type);
+ return 0;
+ } else if ((lock_type_num == LOCK_TYPE_CLVM) && !use_clvmd) {
+ log_error("lock_type clvm requires locking_type 3 configuration setting");
+ return 0;
+ }
+
+ /*
+ * The vg is not owned by one host/system_id.
+ * Locking coordinates access from multiple hosts.
+ */
+ if (lock_type_num == LOCK_TYPE_DLM || lock_type_num == LOCK_TYPE_SANLOCK || lock_type_num == LOCK_TYPE_CLVM)
+ vp_new->system_id = NULL;
+
+ vp_new->lock_type = lock_type;
+
+ if (lock_type_num == LOCK_TYPE_CLVM)
+ vp_new->clustered = 1;
+ else
+ vp_new->clustered = 0;
+
+ log_debug("Setting lock_type to %s", vp_new->lock_type);
return 1;
}
@@ -850,22 +1028,8 @@ int lv_change_activate(struct cmd_context *cmd, struct logical_volume *lv,
int lv_refresh(struct cmd_context *cmd, struct logical_volume *lv)
{
- if (!cmd->partial_activation && (lv->status & PARTIAL_LV)) {
- log_error("Refusing refresh of partial LV %s."
- " Use '--activationmode partial' to override.",
- lv->name);
- return 0;
- }
-
- if (!suspend_lv(cmd, lv)) {
- log_error("Failed to suspend %s.", lv->name);
- return 0;
- }
-
- if (!resume_lv(cmd, lv)) {
- log_error("Failed to reactivate %s.", lv->name);
- return 0;
- }
+ if (!lv_refresh_suspend_resume(cmd, lv))
+ return_0;
/*
* check if snapshot merge should be polled
@@ -1711,6 +1875,7 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
struct vgnameid_list *vgnl;
const char *vg_name;
const char *vg_uuid;
+ uint32_t lockd_state;
int selected;
int whole_selected = 0;
int ret_max = ECMD_PROCESSED;
@@ -1735,17 +1900,17 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
vg_uuid = vgnl->vgid;
skip = 0;
- vg = vg_read(cmd, vg_name, vg_uuid, flags);
+ if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state))
+ continue;
+
+ vg = vg_read(cmd, vg_name, vg_uuid, flags, lockd_state);
if (_ignore_vg(vg, vg_name, arg_vgnames, flags & READ_ALLOW_INCONSISTENT, &skip)) {
stack;
ret_max = ECMD_FAILED;
- release_vg(vg);
- continue;
- }
- if (skip) {
- release_vg(vg);
- continue;
+ goto endvg;
}
+ if (skip)
+ goto endvg;
/* Process this VG? */
if ((process_all ||
@@ -1760,10 +1925,11 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
ret_max = ret;
}
- if (vg_read_error(vg))
- release_vg(vg);
- else
- unlock_and_release_vg(cmd, vg, vg_name);
+ if (!vg_read_error(vg))
+ unlock_vg(cmd, vg_name);
+endvg:
+ release_vg(vg);
+ lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
}
/* the VG is selected if at least one LV is selected */
@@ -2151,6 +2317,7 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
struct dm_str_list *sl;
struct dm_list *tags_arg;
struct dm_list lvnames;
+ uint32_t lockd_state;
const char *vg_name;
const char *vg_uuid;
const char *vgn;
@@ -2197,18 +2364,18 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
}
}
- vg = vg_read(cmd, vg_name, vg_uuid, flags);
+ if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state))
+ continue;
+
+ vg = vg_read(cmd, vg_name, vg_uuid, flags, lockd_state);
if (_ignore_vg(vg, vg_name, arg_vgnames, flags & READ_ALLOW_INCONSISTENT, &skip)) {
stack;
ret_max = ECMD_FAILED;
- release_vg(vg);
- continue;
+ goto endvg;
}
- if (skip) {
- release_vg(vg);
- continue;
- }
+ if (skip)
+ goto endvg;
ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg, 0,
handle, process_single_lv);
@@ -2217,7 +2384,10 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
if (ret > ret_max)
ret_max = ret;
- unlock_and_release_vg(cmd, vg, vg_name);
+ unlock_vg(cmd, vg_name);
+endvg:
+ release_vg(vg);
+ lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
}
return ret_max;
@@ -2668,6 +2838,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
struct vgnameid_list *vgnl;
const char *vg_name;
const char *vg_uuid;
+ uint32_t lockd_state;
int ret_max = ECMD_PROCESSED;
int ret;
int skip;
@@ -2680,14 +2851,15 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
vg_uuid = vgnl->vgid;
skip = 0;
- vg = vg_read(cmd, vg_name, vg_uuid, flags | READ_WARN_INCONSISTENT);
+ if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state))
+ continue;
+
+ vg = vg_read(cmd, vg_name, vg_uuid, flags | READ_WARN_INCONSISTENT, lockd_state);
if (_ignore_vg(vg, vg_name, NULL, flags & READ_ALLOW_INCONSISTENT, &skip)) {
stack;
ret_max = ECMD_FAILED;
- if (!skip) {
- release_vg(vg);
- continue;
- }
+ if (!skip)
+ goto endvg;
/* Drop through to eliminate a clustered VG's PVs from the devices list */
}
@@ -2704,10 +2876,11 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
if (ret > ret_max)
ret_max = ret;
- if (skip)
- release_vg(vg);
- else
- unlock_and_release_vg(cmd, vg, vg->name);
+ if (!skip)
+ unlock_vg(cmd, vg->name);
+endvg:
+ release_vg(vg);
+ lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
/* Quit early when possible. */
if (!process_all_pvs && dm_list_empty(arg_tags) && dm_list_empty(arg_devices))
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 1665d3e5d..a609cf60f 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -308,9 +308,18 @@ static int _vgchange_clustered(struct cmd_context *cmd,
struct volume_group *vg)
{
int clustered = arg_int_value(cmd, clustered_ARG, 0);
+ const char *lock_type = arg_str_value(cmd, locktype_ARG, NULL);
struct lv_list *lvl;
struct lv_segment *mirror_seg;
+ if (find_config_tree_bool(cmd, global_use_lvmlockd_CFG, NULL)) {
+ log_error("lvmlockd requires using the vgchange --lock-type option.");
+ return 0;
+ }
+
+ if (lock_type && !strcmp(lock_type, "clvm"))
+ clustered = 1;
+
if (clustered && vg_is_clustered(vg)) {
if (vg->system_id && *vg->system_id)
log_warn("WARNING: Clearing invalid system ID %s from volume group %s.",
@@ -506,6 +515,197 @@ static int _vgchange_profile(struct cmd_context *cmd,
return 1;
}
+static int _vgchange_locktype(struct cmd_context *cmd,
+ struct volume_group *vg)
+{
+ const char *lock_type = arg_str_value(cmd, locktype_ARG, NULL);
+ const char *lock_args = NULL;
+ struct lv_list *lvl;
+ struct logical_volume *lv;
+
+ /*
+ * This is a special/forced exception to change the lock type to none.
+ * It's needed for recovery cases and skips the normal steps of undoing
+ * the current lock type. It's a way to forcibly get access to a VG
+ * when the normal locking mechanisms are not working.
+ *
+ * It ignores: the current lvm locking config, lvmlockd, the state of
+ * the vg on other hosts, etc. It is meant to just remove any locking
+ * related metadata from the VG (cluster/lock_type flags, lock_type,
+ * lock_args).
+ *
+ * This can be necessary when manually recovering from certain failures.
+ * e.g. when a pv is lost containing the lvmlock lv (holding sanlock
+ * leases), the vg lock_type needs to be changed to none, and then
+ * back to sanlock, which recreates the lvmlock lv and leases.
+ */
+ if (!strcmp(lock_type, "none") && arg_is_set(cmd, force_ARG)) {
+ if (yes_no_prompt("Forcibly change VG %s lock type to none? [y/n]: ", vg->name) == 'n') {
+ log_error("VG lock type not changed.");
+ return 0;
+ }
+
+ vg->status &= ~CLUSTERED;
+ vg->lock_type = "none";
+ vg->lock_args = NULL;
+
+ dm_list_iterate_items(lvl, &vg->lvs) {
+ lvl->lv->lock_type = "none";
+ lvl->lv->lock_args = NULL;
+ }
+
+ return 1;
+ }
+
+ if (!strcmp(vg->lock_type, lock_type)) {
+ log_warn("New lock_type %s matches the current lock_type %s.",
+ lock_type, vg->lock_type);
+ return 1;
+ }
+
+ /*
+ * When lvm is currently using clvm, this function is just an alternative
+ * to vgchange -c{y,n}, and can:
+ * - change none to clvm
+ * - change clvm to none
+ * - it CANNOT change to or from a lockd type
+ */
+ if (locking_is_clustered()) {
+ if (is_lockd_type(lock_type)) {
+ log_error("Changing to lock type %s requires lvmlockd.", lock_type);
+ return 0;
+ }
+
+ return _vgchange_clustered(cmd, vg);
+ }
+
+ /*
+ * When lvm is currently using lvmlockd, this function can:
+ * - change none to lockd type
+ * - change none to clvm (with warning about not being able to use it)
+ * - change lockd type to none
+ * - change lockd type to clvm (with warning about not being able to use it)
+ * - change clvm to none
+ * - change clvm to lockd type
+ */
+
+ if (lvs_in_vg_activated(vg)) {
+ log_error("Changing VG %s lock type not allowed with active LVs",
+ vg->name);
+ return 0;
+ }
+
+ /*
+ * Check if there are any LV types in the VG that cannot be handled
+ * with the new lock type. Remove this once all LV types can be
+ * handled.
+ */
+ if (is_lockd_type(lock_type)) {
+ dm_list_iterate_items(lvl, &vg->lvs) {
+ lv = lvl->lv;
+
+ if ((lv->status & SNAPSHOT) || lv_is_cow(lv)) {
+ log_error("Changing to lock type %s is not allowed with cow snapshot LV %s/%s",
+ lock_type, vg->name, lv->name);
+ return 0;
+ }
+ }
+ }
+
+ /* none to clvm */
+ if (!strcmp(vg->lock_type, "none") && !strcmp(lock_type, "clvm")) {
+ log_warn("New clvm lock type will not be usable with lvmlockd.");
+ vg->status |= CLUSTERED;
+ vg->lock_type = "clvm"; /* this is optional */
+ return 1;
+ }
+
+ /* clvm to none */
+ if (!strcmp(vg->lock_type, "clvm") && !strcmp(lock_type, "none")) {
+ vg->status &= ~CLUSTERED;
+ vg->lock_type = "none";
+ return 1;
+ }
+
+ /* clvm to ..., first undo clvm */
+ if (!strcmp(vg->lock_type, "clvm")) {
+ vg->status &= ~CLUSTERED;
+ }
+
+ /*
+ * lockd type to ..., first undo lockd type
+ *
+ * To allow this, we need to do:
+ * lockd_stop_vg();
+ * lockd_free_vg_before();
+ * lockd_free_vg_after();
+ */
+ if (is_lockd_type(vg->lock_type)) {
+ /* TODO */
+ log_error("Changing VG %s from lock type %s not yet allowed.",
+ vg->name, vg->lock_type);
+ return 0;
+ }
+
+ /* ... to clvm */
+ if (!strcmp(lock_type, "clvm")) {
+ log_warn("New clvm lock type will not be usable with lvmlockd.");
+ vg->status |= CLUSTERED;
+ vg->lock_type = "clvm"; /* this is optional */
+ vg->system_id = NULL;
+ return 1;
+ }
+
+ /*
+ * ... to lockd type. These are the same steps vgcreate uses.
+ */
+ if (is_lockd_type(lock_type)) {
+ if (!vg_set_lock_type(vg, lock_type))
+ return 0;
+
+ if (!lockd_init_vg(cmd, vg)) {
+ log_error("Failed to initialize lock args for lock type %s", lock_type);
+ return 0;
+ }
+
+ vg->system_id = NULL;
+
+ /* These are the same steps lvcreate uses within a lockd type VG. */
+
+ dm_list_iterate_items(lvl, &vg->lvs) {
+ lv = lvl->lv;
+
+ /* Some LV types have no lock. */
+ if (!lv_is_visible(lv) ||
+ lv_is_thin_volume(lv) ||
+ lv_is_thin_pool_data(lv) ||
+ lv_is_thin_pool_metadata(lv) ||
+ lv_is_pool_metadata_spare(lv) ||
+ lv_is_cache_pool(lv) ||
+ lv_is_cache_pool_data(lv) ||
+ lv_is_cache_pool_metadata(lv))
+ continue;
+
+ if (!lockd_init_lv_args(cmd, vg, lv->name, lock_type, &lock_args)) {
+ log_error("Failed to init %s lock args LV %s/%s",
+ lock_type, vg->name, lv->name);
+ return 0;
+ }
+
+ lv->lock_type = dm_pool_strdup(cmd->mem, lock_type);
+ lv->lock_args = lock_args;
+ }
+
+ if (!lockd_start_vg(cmd, vg))
+ log_error("Failed to start locking for VG %s", vg->name);
+
+ return 1;
+ }
+
+ log_error("Unknown lock type");
+ return 0;
+}
+
/*
* This function will not be called unless the local host is allowed to use the
* VG. Either the VG has no system_id, or the VG and host have matching
@@ -577,9 +777,83 @@ static int _vgchange_system_id(struct cmd_context *cmd, struct volume_group *vg)
if (vg->lvm1_system_id)
*vg->lvm1_system_id = '\0';
+ /* 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 _passes_lock_start_filter(struct cmd_context *cmd,
+ struct volume_group *vg,
+ const int cfg_id)
+{
+ const struct dm_config_node *cn;
+ const struct dm_config_value *cv;
+ const char *str;
+
+ /* undefined list means no restrictions, all vg names pass */
+
+ cn = find_config_tree_node(cmd, cfg_id, NULL);
+ if (!cn)
+ return 1;
+
+ /* with a defined list, the vg name must be included to pass */
+
+ for (cv = cn->v; cv; cv = cv->next) {
+ if (cv->type == DM_CFG_EMPTY_ARRAY)
+ break;
+ if (cv->type != DM_CFG_STRING) {
+ log_error("Ignoring invalid string in lock_start list");
+ continue;
+ }
+ str = cv->v.str;
+ if (!*str) {
+ log_error("Ignoring empty string in config file");
+ continue;
+ }
+
+ /* ignoring tags for now */
+
+ if (!strcmp(str, vg->name))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg)
+{
+ const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL);
+ int auto_opt = 0;
+
+ if (!start_opt || arg_is_set(cmd, force_ARG))
+ goto do_start;
+
+ if (!strcmp(start_opt, "auto") || !strcmp(start_opt, "autowait"))
+ auto_opt = 1;
+
+ if (!_passes_lock_start_filter(cmd, vg, activation_lock_start_list_CFG)) {
+ log_verbose("Not starting %s since it does not pass lock_start_list", vg->name);
+ return 1;
+ }
+
+ if (auto_opt && !_passes_lock_start_filter(cmd, vg, activation_auto_lock_start_list_CFG)) {
+ log_verbose("Not starting %s since it does not pass auto_lock_start_list", vg->name);
+ return 1;
+ }
+
+do_start:
+ return lockd_start_vg(cmd, vg);
+}
+
+static int _vgchange_lock_stop(struct cmd_context *cmd, struct volume_group *vg)
+{
+ /* Disable the unlock in toollib because it's pointless after the stop. */
+ cmd->lockd_vg_disable = 1;
+ 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)))
@@ -605,6 +879,7 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
{ metadataprofile_ARG, &_vgchange_profile },
{ profile_ARG, &_vgchange_profile },
{ detachprofile_ARG, &_vgchange_profile },
+ { locktype_ARG, &_vgchange_locktype },
{ systemid_ARG, &_vgchange_system_id },
};
@@ -694,13 +969,92 @@ 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;
}
+/*
+ * vgchange can do different things that require different
+ * locking, so look at each of those things here.
+ *
+ * Set up overrides for the default VG locking for various special cases.
+ * The VG lock will be acquired in process_each_vg.
+ *
+ * Acquire the gl lock according to which kind of vgchange command this is.
+ */
+
+static int lockd_vgchange(struct cmd_context *cmd, int argc, char **argv)
+{
+ /* The default vg lock mode is ex, but these options only need sh. */
+
+ if (arg_is_set(cmd, activate_ARG) || arg_is_set(cmd, refresh_ARG))
+ cmd->lockd_vg_default_sh = 1;
+
+ /* Starting a vg lockspace means there are no locks available yet. */
+
+ if (arg_is_set(cmd, lockstart_ARG))
+ cmd->lockd_vg_disable = 1;
+
+ /*
+ * In most cases, lockd_vg does not apply when changing lock type.
+ * (We don't generally allow changing *from* lockd type yet.)
+ * lockd_vg could be called within _vgchange_locktype as needed.
+ */
+
+ if (arg_is_set(cmd, locktype_ARG))
+ cmd->lockd_vg_disable = 1;
+
+ /*
+ * Changing system_id or lock_type must only be done on explicitly
+ * named vgs.
+ */
+
+ if (arg_is_set(cmd, systemid_ARG) || arg_is_set(cmd, locktype_ARG))
+ cmd->command->flags &= ~ALL_VGS_IS_DEFAULT;
+
+ if (!argc || arg_tag_count(argc, argv) || arg_is_set(cmd, lockstart_ARG)) {
+ /*
+ * The first two standard conditions want the current
+ * list of all vg names. The lockstart condition takes
+ * the gl to serialize with any other host that tries to
+ * remove the VG while this tries to start it.
+ */
+ if (!lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
+ } else if (arg_is_set(cmd, systemid_ARG) ||
+ arg_is_set(cmd, uuid_ARG) ||
+ arg_is_set(cmd, locktype_ARG)) {
+ /*
+ * VG names, uuids and system_ids are the three things that
+ * other hosts cache related to local vg's, so we use the
+ * name-change counter in the global lock to indicate that
+ * one of these global VG identifiers has changed so other
+ * hosts will update these cached values in VG's that they
+ * otherwise ignore (because they have foreign system_ids).
+ */
+ if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES))
+ return_ECMD_FAILED;
+ }
+
+ return 1;
+}
+
int vgchange(struct cmd_context *cmd, int argc, char **argv)
{
+ int ret;
+
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);
@@ -721,6 +1075,7 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
arg_count(cmd, clustered_ARG) ||
arg_count(cmd, alloc_ARG) ||
arg_count(cmd, vgmetadatacopies_ARG) ||
+ arg_count(cmd, locktype_ARG) ||
arg_count(cmd, systemid_ARG);
int update = update_partial_safe || update_partial_unsafe;
@@ -819,6 +1174,19 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, activate_ARG))
cmd->include_active_foreign_vgs = 1;
- return process_each_vg(cmd, argc, argv, update ? READ_FOR_UPDATE : 0,
- NULL, &vgchange_single);
+ if (!lockd_vgchange(cmd, argc, argv))
+ return_ECMD_FAILED;
+
+ ret = process_each_vg(cmd, argc, argv, update ? READ_FOR_UPDATE : 0,
+ NULL, &vgchange_single);
+
+ /* Wait for lock-start ops that were initiated in vgchange_lockstart. */
+
+ if (arg_is_set(cmd, lockstart_ARG) && arg_is_set(cmd, lockopt_ARG)) {
+ const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL);
+ if (!strcmp(start_opt, "wait") || !strcmp(start_opt, "autowait"))
+ lockd_start_wait(cmd);
+ }
+
+ return ret;
}
diff --git a/tools/vgcreate.c b/tools/vgcreate.c
index 0a6ad6f32..5fe9687aa 100644
--- a/tools/vgcreate.c
+++ b/tools/vgcreate.c
@@ -50,6 +50,9 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
if (!vgcreate_params_validate(cmd, &vp_new))
return EINVALID_CMD_LINE;
+ if (!lockd_gl_create(cmd, "ex", vp_new.lock_type))
+ return ECMD_FAILED;
+
lvmcache_seed_infos_from_lvmetad(cmd);
/* Create the new VG */
@@ -71,6 +74,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
!vg_set_max_pv(vg, vp_new.max_pv) ||
!vg_set_alloc_policy(vg, vp_new.alloc) ||
!vg_set_clustered(vg, vp_new.clustered) ||
+ !vg_set_lock_type(vg, vp_new.lock_type) ||
!vg_set_system_id(vg, vp_new.system_id) ||
!vg_set_mda_copies(vg, vp_new.vgmetadatacopies))
goto bad_orphan;
@@ -119,6 +123,14 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
if (!vg_write(vg) || !vg_commit(vg))
goto_bad;
+ if (!lockd_init_vg(cmd, vg)) {
+ log_error("Failed to initialize lock args for lock type %s",
+ vp_new.lock_type);
+ vg_remove_pvs(vg);
+ vg_remove_direct(vg);
+ goto_bad;
+ }
+
unlock_vg(cmd, VG_ORPHANS);
unlock_vg(cmd, vp_new.vg_name);
@@ -128,6 +140,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;
diff --git a/tools/vgextend.c b/tools/vgextend.c
index de6d862e8..c7da8bc6c 100644
--- a/tools/vgextend.c
+++ b/tools/vgextend.c
@@ -165,6 +165,9 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
*/
cmd->handles_missing_pvs = 1;
+ if (!lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+
ret = process_each_vg(cmd, argc, argv,
READ_FOR_UPDATE | ONE_VGNAME_ARG, handle,
restoremissing ? &_vgextend_restoremissing : &_vgextend_single);
diff --git a/tools/vgmerge.c b/tools/vgmerge.c
index a17a636c5..e6e20278c 100644
--- a/tools/vgmerge.c
+++ b/tools/vgmerge.c
@@ -20,11 +20,18 @@ static struct volume_group *_vgmerge_vg_read(struct cmd_context *cmd,
{
struct volume_group *vg;
log_verbose("Checking for volume group \"%s\"", vg_name);
- vg = vg_read_for_update(cmd, vg_name, NULL, 0);
+ vg = vg_read_for_update(cmd, vg_name, NULL, 0, 0);
if (vg_read_error(vg)) {
release_vg(vg);
return NULL;
}
+
+ if (is_lockd_type(vg->lock_type)) {
+ log_error("vgmerge not allowed for lock_type %s", vg->lock_type);
+ unlock_and_release_vg(cmd, vg, vg_name);
+ return NULL;
+ }
+
return vg;
}
@@ -194,6 +201,9 @@ int vgmerge(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES))
+ return ECMD_FAILED;
+
vg_name_to = skip_dev_dir(cmd, argv[0], NULL);
argc--;
argv++;
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index 0adf1bb85..7ab2dca93 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -141,6 +141,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
{
struct volume_group *vg;
const char *vg_name;
+ uint32_t lockd_state;
int ret = ECMD_FAILED;
int fixed = 1;
int repairing = arg_count(cmd, removemissing_ARG);
@@ -195,7 +196,13 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
init_ignore_suspended_devices(1);
cmd->handles_missing_pvs = 1;
- vg = vg_read_for_update(cmd, vg_name, NULL, READ_ALLOW_EXPORTED);
+ if (!lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+
+ if (!lockd_vg(cmd, vg_name, "ex", 0, &lockd_state))
+ return_ECMD_FAILED;
+
+ vg = vg_read_for_update(cmd, vg_name, NULL, READ_ALLOW_EXPORTED, lockd_state);
if (vg_read_error(vg) == FAILED_ALLOCATION ||
vg_read_error(vg) == FAILED_NOTFOUND)
goto_out;
@@ -218,7 +225,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
log_verbose("Trying to open VG %s for recovery...", vg_name);
vg = vg_read_for_update(cmd, vg_name, NULL,
- READ_ALLOW_INCONSISTENT | READ_ALLOW_EXPORTED);
+ READ_ALLOW_INCONSISTENT | READ_ALLOW_EXPORTED, lockd_state);
locked |= !vg_read_error(vg);
diff --git a/tools/vgremove.c b/tools/vgremove.c
index fd9735604..e6df559a0 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -68,6 +68,9 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
}
}
+ if (!lockd_free_vg_before(cmd, vg))
+ return_ECMD_FAILED;
+
if (!force && !vg_remove_check(vg))
return_ECMD_FAILED;
@@ -76,6 +79,8 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
if (!vg_remove(vg))
return_ECMD_FAILED;
+ lockd_free_vg_final(cmd, vg);
+
return ECMD_PROCESSED;
}
@@ -89,6 +94,9 @@ int vgremove(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES))
+ return ECMD_FAILED;
+
cmd->handles_missing_pvs = 1;
ret = process_each_vg(cmd, argc, argv,
READ_FOR_UPDATE,
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 860ccf196..2cef1fc72 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -17,13 +17,14 @@
static struct volume_group *_get_old_vg_for_rename(struct cmd_context *cmd,
const char *vg_name_old,
- const char *vgid)
+ const char *vgid,
+ uint32_t lockd_state)
{
struct volume_group *vg;
/* FIXME we used to print an error about EXPORTED, but proceeded
nevertheless. */
- vg = vg_read_for_update(cmd, vg_name_old, vgid, READ_ALLOW_EXPORTED);
+ vg = vg_read_for_update(cmd, vg_name_old, vgid, READ_ALLOW_EXPORTED, lockd_state);
if (vg_read_error(vg)) {
release_vg(vg);
return_NULL;
@@ -67,6 +68,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
const char *vgid = NULL, *vg_name, *vg_name_old;
char old_path[NAME_LEN], new_path[NAME_LEN];
struct volume_group *vg = NULL;
+ uint32_t lockd_state;
int lock_vg_old_first = 1;
vg_name_old = skip_dev_dir(cmd, old_vg_path, NULL);
@@ -114,11 +116,14 @@ 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, &lockd_state))
+ return_0;
+
if (strcmp(vg_name_new, vg_name_old) < 0)
lock_vg_old_first = 0;
if (lock_vg_old_first) {
- vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid);
+ vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid, lockd_state);
if (!vg)
return_0;
@@ -130,7 +135,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
if (!_lock_new_vg_for_rename(cmd, vg_name_new))
return_0;
- vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid);
+ vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid, lockd_state);
if (!vg) {
unlock_vg(cmd, vg_name_new);
return_0;
@@ -144,6 +149,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);
@@ -171,6 +179,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))
@@ -190,6 +200,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);
@@ -207,6 +219,9 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES))
+ return_ECMD_FAILED;
+
if (!vg_rename_path(cmd, argv[0], argv[1]))
return_ECMD_FAILED;
diff --git a/tools/vgscan.c b/tools/vgscan.c
index 7328a096d..c70a3f07e 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -42,6 +42,9 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
+ if (!lockd_gl(cmd, "sh", 0))
+ return_ECMD_FAILED;
+
if (cmd->filter->wipe)
cmd->filter->wipe(cmd->filter);
lvmcache_destroy(cmd, 1, 0);
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index 53f3975c3..e04bf232b 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -422,7 +422,7 @@ static struct volume_group *_vgsplit_to(struct cmd_context *cmd,
if (vg_read_error(vg_to) == FAILED_EXIST) {
*existing_vg = 1;
release_vg(vg_to);
- vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0);
+ vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0, 0);
if (vg_read_error(vg_to)) {
release_vg(vg_to);
@@ -448,11 +448,18 @@ static struct volume_group *_vgsplit_from(struct cmd_context *cmd,
log_verbose("Checking for volume group \"%s\"", vg_name_from);
- vg_from = vg_read_for_update(cmd, vg_name_from, NULL, 0);
+ vg_from = vg_read_for_update(cmd, vg_name_from, NULL, 0, 0);
if (vg_read_error(vg_from)) {
release_vg(vg_from);
return NULL;
}
+
+ if (is_lockd_type(vg_from->lock_type)) {
+ log_error("vgsplit not allowed for lock_type %s", vg_from->lock_type);
+ unlock_and_release_vg(cmd, vg_from, vg_name_from);
+ return NULL;
+ }
+
return vg_from;
}
@@ -492,6 +499,9 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
+ if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES))
+ return_ECMD_FAILED;
+
if (arg_count(cmd, name_ARG))
lv_name = arg_value(cmd, name_ARG);
else
@@ -662,7 +672,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
if (!test_mode()) {
release_vg(vg_to);
vg_to = vg_read_for_update(cmd, vg_name_to, NULL,
- READ_ALLOW_EXPORTED);
+ READ_ALLOW_EXPORTED, 0);
if (vg_read_error(vg_to)) {
log_error("Volume group \"%s\" became inconsistent: "
"please fix manually", vg_name_to);