diff options
author | David Teigland <teigland@redhat.com> | 2015-05-13 15:03:21 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2015-05-28 16:34:36 -0500 |
commit | 0e76602814ec02c033a2705f625d4f4f0a679ad9 (patch) | |
tree | 0786ba34663cbc19805d3c5a2e4b5cfda18e2ed2 | |
parent | 3cda1ce866f30f870ca1b68de65f00a25aded62c (diff) | |
download | lvm2-0e76602814ec02c033a2705f625d4f4f0a679ad9.tar.gz |
tools: use locks from lvmlockd
-rw-r--r-- | tools/lvchange.c | 30 | ||||
-rw-r--r-- | tools/lvcreate.c | 9 | ||||
-rw-r--r-- | tools/lvrename.c | 6 | ||||
-rw-r--r-- | tools/lvresize.c | 6 | ||||
-rw-r--r-- | tools/lvscan.c | 3 | ||||
-rw-r--r-- | tools/pvchange.c | 7 | ||||
-rw-r--r-- | tools/pvcreate.c | 3 | ||||
-rw-r--r-- | tools/pvdisplay.c | 3 | ||||
-rw-r--r-- | tools/pvremove.c | 3 | ||||
-rw-r--r-- | tools/pvresize.c | 7 | ||||
-rw-r--r-- | tools/pvscan.c | 6 | ||||
-rw-r--r-- | tools/reporter.c | 3 | ||||
-rw-r--r-- | tools/toollib.c | 291 | ||||
-rw-r--r-- | tools/vgchange.c | 372 | ||||
-rw-r--r-- | tools/vgcreate.c | 16 | ||||
-rw-r--r-- | tools/vgextend.c | 3 | ||||
-rw-r--r-- | tools/vgmerge.c | 12 | ||||
-rw-r--r-- | tools/vgreduce.c | 11 | ||||
-rw-r--r-- | tools/vgremove.c | 8 | ||||
-rw-r--r-- | tools/vgrename.c | 23 | ||||
-rw-r--r-- | tools/vgscan.c | 3 | ||||
-rw-r--r-- | tools/vgsplit.c | 16 |
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 = ¶ms; + 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); |