diff options
-rw-r--r-- | lib/locking/lvmlockd.c | 30 | ||||
-rw-r--r-- | lib/locking/lvmlockd.h | 5 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 4 | ||||
-rw-r--r-- | tools/args.h | 1 | ||||
-rw-r--r-- | tools/dlock.c | 245 | ||||
-rw-r--r-- | tools/dlock.h | 11 | ||||
-rw-r--r-- | tools/lvconvert.c | 3 | ||||
-rw-r--r-- | tools/lvcreate.c | 3 | ||||
-rw-r--r-- | tools/lvmcmdline.c | 2 | ||||
-rw-r--r-- | tools/lvrename.c | 5 | ||||
-rw-r--r-- | tools/lvresize.c | 3 | ||||
-rw-r--r-- | tools/toollib.c | 17 | ||||
-rw-r--r-- | tools/tools.h | 2 | ||||
-rw-r--r-- | tools/vgchange.c | 37 | ||||
-rw-r--r-- | tools/vgmerge.c | 7 | ||||
-rw-r--r-- | tools/vgreduce.c | 2 | ||||
-rw-r--r-- | tools/vgremove.c | 7 | ||||
-rw-r--r-- | tools/vgrename.c | 6 | ||||
-rw-r--r-- | tools/vgsplit.c | 7 |
19 files changed, 391 insertions, 6 deletions
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c index ec8f1c40e..b9b684d4d 100644 --- a/lib/locking/lvmlockd.c +++ b/lib/locking/lvmlockd.c @@ -881,3 +881,33 @@ out: return ret; } +int lvmlockd_vg_update(struct volume_group *vg) +{ + daemon_reply reply; + int result; + int ret; + + if (!is_dlock_type(vg->lock_type)) + return 1; + + if (!_lvmlockd_active) + return 1; + if (!lvmlockd_connected()) + return 0; + + reply = _lvmlockd_send("vg_update", + "pid = %d", getpid(), + "vg_name = %s", vg->name, + "version = %d", (int64_t)vg->seqno, + NULL); + + if (!_lvmlockd_result(reply, &result, NULL)) { + ret = 0; + } else { + ret = (result < 0) ? 0 : 1; + } + + daemon_reply_destroy(reply); + return ret; +} + diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h index 87b49ccfe..9ee8f9acb 100644 --- a/lib/locking/lvmlockd.h +++ b/lib/locking/lvmlockd.h @@ -104,6 +104,9 @@ void lvmlockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg); int lvmlockd_start_vg(struct cmd_context *cmd, struct volume_group *vg); int lvmlockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg); +/* notify lvmlockd of a new VG seqno */ + +int lvmlockd_vg_update(struct volume_group *vg); #else /* LVMLOCKD_SUPPORT */ @@ -123,6 +126,8 @@ int lvmlockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg); #define lvmlockd_start_vg(cmd, vg) (1) #define lvmlockd_stop_vg(cmd, vg) (1) +#define lvmlockd_vg_update(vg) (1) + #endif /* LVMLOCKD_SUPPORT */ #endif diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 9e1bb9e5f..220de162f 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -605,6 +605,8 @@ int vg_remove(struct volume_group *vg) if (!lvmetad_vg_remove(vg)) stack; + lvmlockd_vg_update(vg); + if (!backup_remove(vg->cmd, vg->name)) stack; @@ -2903,6 +2905,8 @@ int vg_commit(struct volume_group *vg) if ((vg->fid->fmt->features & FMT_PRECOMMIT) && !lvmetad_vg_update(vg)) return_0; + lvmlockd_vg_update(vg); + cache_updated = _vg_commit_mdas(vg); if (cache_updated) { diff --git a/tools/args.h b/tools/args.h index 72f592dd5..12c9ce934 100644 --- a/tools/args.h +++ b/tools/args.h @@ -48,6 +48,7 @@ arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", NULL, 0) arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", NULL, 0) arg(labelsector_ARG, '\0', "labelsector", int_arg, 0) arg(lockgl_ARG, '\0', "lock-gl", string_arg, 0) +arg(lockvg_ARG, '\0', "lock-vg", string_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) diff --git a/tools/dlock.c b/tools/dlock.c index cefa54d7c..ab2a47291 100644 --- a/tools/dlock.c +++ b/tools/dlock.c @@ -135,11 +135,12 @@ int dlock_gl_create(struct cmd_context *cmd, const char *def_mode, uint32_t flag /* * result and result_flags were returned from lvmlockd. * In lvmlockd, result 0 is success, and error is < 0. + * + * ENOLS: no lockspace was found with a global lock. + * It may not exist (perhaps this command is creating the first), + * or it may not be visible or started on the system yet. */ - /* - * No lockspace was found with a global lock. - */ if (result == -ENOLS) { /* * It's not a problem if an unlock happens after the @@ -319,7 +320,14 @@ int dlock_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags) /* * result and result_flags were returned from lvmlockd. - * in lvmlockd, result 0 is success, and error is < 0. + * In lvmlockd, result 0 is success, and error is < 0. + * + * ENOLS: no lockspace was found with a global lock. + * The VG with the global lock may not be visible or started yet, + * this should be a temporary condition. + * + * ESTARTING: the lockspace with the gl is starting. + * The VG with the global lock is starting and should finish shortly. */ if (result == -ENOLS || result == -ESTARTING) { @@ -378,3 +386,232 @@ int dlock_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags) return 1; } +int dlock_vg(struct cmd_context *cmd, const char *vg_name, + const char *def_mode, uint32_t flags) +{ + const char *mode = NULL; + const char *opts = NULL; + uint32_t result_flags; + int result; + int ret; + + /* + * Only real vgs have locks; orphans are covered by global lock. + */ + if (!is_real_vg(vg_name)) + return 1; + + /* + * DLOCK_VG_NA is used in special cases to disable the vg lock. + */ + if (cmd->command->flags & DLOCK_VG_NA) + return 1; + + /* + * DL_VG_MODE_NOARG disables getting the mode from --lock-vg arg. + */ + if (!(flags & DL_VG_MODE_NOARG)) { + mode = arg_str_value(cmd, lockvg_ARG, NULL); + if (mode && def_mode && + (_mode_compare(mode, def_mode) < 0) && + !find_config_tree_bool(cmd, global_allow_override_lock_modes_CFG, NULL)) { + log_error("Disallowed lock-vg mode \"%s\"", mode); + return 0; + } + } + + if (!mode) + mode = def_mode; + + if (!mode) { + /* + * Default mode is needed, but was not provided + * in the function args. This happens when dlock_vg + * is called from a process_each function that handles + * different commands. Commands that only + * read/check/report/display the vg have DLOCK_VG_SH + * set in commands.h. All other commands modify the vg. + */ + if (cmd->command->flags & DLOCK_VG_SH) + mode = "sh"; + else + mode = "ex"; + } + + if (!strcmp(mode, "ex") && find_config_tree_bool(cmd, global_read_only_lock_modes_CFG, NULL)) { + log_error("Disallow lock-vg ex with read_only_lock_modes"); + return 0; + } + + ret = lvmlockd_send(cmd, command_name(cmd), "lock_vg", + vg_name, NULL, NULL, NULL, NULL, mode, opts, + &result, &result_flags); + if (!ret) { + /* No result from lvmlockd, it is probably not running. */ + + /* See comment in dlock_gl() about this case. */ + + if (arg_count(cmd, sysinit_ARG) || arg_count(cmd, ignorelockingfailure_ARG)) { + log_debug("Ignore failed locking for VG %s: option %s", vg_name, + arg_count(cmd, sysinit_ARG) ? "sysinit" : "ignorelockingfailure"); + return 1; + } + + /* See comment in dlock_gl() about these cases. */ + + if (!strcmp(mode, "un")) + return 1; + + if (!strcmp(mode, "sh")) { + log_warn("Reading VG %s without shared lock.", vg_name); + return 1; + } + + log_error("Locking failed for VG %s", vg_name); + return 0; + } + + /* + * result and result_flags were returned from lvmlockd. + * In lvmlockd, result 0 is success, and error is < 0. + * + * ELOCALVG: the VG is local and does not need a dlock. + * + * EOTHERVG: the VG is local and belongs to another system_id. + * + * ENOLS: no lockspace for the VG was found, the VG may not + * be started yet. The VG should be started manually or by system, + * e.g. vgchange --lock-start + * + * ESTARTING: the lockspace for the VG is starting and should + * finish shortly. + */ + + if (result == -ELOCALVG) + return 1; + + if (result == -EOTHERVG) { + /* + * The VG is local and owned by another system_id. + * lvmlockd knows this because it caches the identity of + * local VGs (for the ELOCALVG case above). + * + * . By returning 0 (failure) here we can skip this VG + * before vg_read() is even called. + * + * . By returning 1 (success) here we will continue through + * vg_read(), after which we will see the foreign + * system_id in the metadata, and return FAILED_SYSTEMID. + * This VG would then be skipped by ignore_vg() instead + * of being skipped here. + * + * Skipping the foreign VG here is more efficient, but not + * consistent with the way foreign VGs are ignored when + * lvmlockd is not used, so we return success instead. + * If we decide to skip the VG here (return 0), then we + * would need to override this when cmd->include_foreign_vgs + * is set (the command wants to read/report foreign VGs.) + */ + log_debug("local VG %s owned by other system_id", vg_name); + return 0; + } + + if (result == -ENOLS || result == -ESTARTING) { + + /* It doesn't matter if an unlock operation fails. */ + if (!strcmp(mode, "un")) + return 1; + + if (strcmp(mode, "sh")) { + /* + * An ex lock request always fails here. Based on the + * result number and result flags we can often print a + * reason for the failure. + * + * (In the future we might want to continue through + * vg_read with the lock and fail after the vg_read. + * Doing the vg_read may provide more information about + * the failure here.) + */ + if ((result == -ENOLS) && (result_flags & LD_RF_INACTIVE_LS)) { + if (result_flags & LD_RF_ADD_LS_ERROR) + log_error("VG %s lock failed: lock start error", vg_name); + else + log_error("VG %s lock failed: locking stopped", vg_name); + + } else if (result == -ENOLS) { + log_error("VG %s lock failed: lock start required", vg_name); + + } else if (result == -ESTARTING) { + log_error("VG %s lock failed: lock start in progress", vg_name); + + } else { + log_error("VG %s lock failed: %d", vg_name, result); + } + return 0; + } + + /* + * When a sh lock failed we will allow the command to proceed + * because there's little harm that it could do. See the + * reasoning above for proceeding after a failed gl sh lock. + * Do we want to invalidate the cached VG in these cases to + * force rereading from disk? + */ + + if (result == -ESTARTING) { + log_warn("Skipping lock for VG %s: lock start in progress", vg_name); + return 1; + } + + if ((result == -ENOLS) && (result_flags & LD_RF_ADD_LS_ERROR)) { + log_warn("Skipping lock for VG %s: lock start error", vg_name); + return 1; + } + + if ((result == -ENOLS) && (result_flags & LD_RF_INACTIVE_LS)) { + log_warn("Skipping lock for VG %s: locking stopped", vg_name); + return 1; + } + + if (result == -ENOLS) { + log_warn("Skipping lock for VG %s: lock start required", vg_name); + return 1; + } + + log_error("VG %s shared lock error %d", vg_name, result); + return 0; + } + + /* + * A notice from lvmlockd that duplicate gl locks have been found. + * It would be good for the user to disable one of them. + */ + if ((result_flags & LD_RF_DUP_GL_LS) && strcmp(mode, "un")) + log_warn("Duplicate sanlock global lock in VG %s", vg_name); + + if (result < 0) { + log_error("VG %s lock error: %d", vg_name, result); + return 0; + } + + return 1; +} + +/* A shortcut for back to back dlock_gl() + dlock_vg() */ + +int dlock_gl_vg(struct cmd_context *cmd, const char *vg_name, + const char *def_gl_mode, const char *def_vg_mode, + uint32_t flags) +{ + if (!dlock_gl(cmd, def_gl_mode, flags)) + return 0; + + if (!dlock_vg(cmd, vg_name, def_vg_mode, flags)) { + dlock_gl(cmd, "un", DL_GL_MODE_NOARG); + return 0; + } + + return 1; +} + diff --git a/tools/dlock.h b/tools/dlock.h index 255c90080..2a6ebe183 100644 --- a/tools/dlock.h +++ b/tools/dlock.h @@ -15,16 +15,27 @@ #define DL_GL_SKIP_CACHE_VALIDATE 0x00000002 #define DL_GL_UPDATE_NAMES 0x00000004 +#define DL_VG_MODE_NOARG 0x00000001 + #ifdef LVMLOCKD_SUPPORT int dlock_gl_create(struct cmd_context *cmd, const char *def_mode, uint32_t flags, const char *vg_lock_type); int dlock_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags); +int dlock_vg(struct cmd_context *cmd, const char *vg_name, + const char *def_mode, uint32_t flags); + +int dlock_gl_vg(struct cmd_context *cmd, const char *vg_name, + const char *def_gl_mode, const char *def_vg_mode, + uint32_t flags); + #else /* LVMLOCKD_SUPPORT */ #define dlock_gl_create(cmd, def_mode, flags, vg_lock_type) (1) #define dlock_gl(cmd, def_mode, flags) (1) +#define dlock_vg(cmd, vg_name, def_mode, flags) (1) +#define dlock_gl_vg(cmd, vg_name, def_gl_mode, def_vg_mode, flags) (1) #endif /* LVMLOCKD_SUPPORT */ diff --git a/tools/lvconvert.c b/tools/lvconvert.c index fcec8e176..b95e20b82 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -3418,6 +3418,9 @@ static int lvconvert_single(struct cmd_context *cmd, struct lvconvert_params *lp cmd->handles_missing_pvs = 1; } + if (!dlock_vg(cmd, lp->vg_name, "ex", 0)) + goto_out; + if (!(lv = get_vg_lock_and_logical_volume(cmd, lp->vg_name, lp->lv_name))) goto_out; diff --git a/tools/lvcreate.c b/tools/lvcreate.c index cf2a07cb8..333b9c113 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -1424,6 +1424,9 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv) return EINVALID_CMD_LINE; } + if (!dlock_vg(cmd, lp.vg_name, "ex", 0)) + return_ECMD_FAILED; + log_verbose("Finding volume group \"%s\"", lp.vg_name); vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0); if (vg_read_error(vg)) { diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 07427f941..337dc4416 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -761,7 +761,7 @@ void lvm_register_commands(void) yes_ARG, \ quiet_ARG, config_ARG, \ commandprofile_ARG, \ - lockgl_ARG, \ + lockgl_ARG, lockvg_ARG, \ profile_ARG, -1); #include "commands.h" #undef xx diff --git a/tools/lvrename.c b/tools/lvrename.c index eeff76da2..2f34f1dd2 100644 --- a/tools/lvrename.c +++ b/tools/lvrename.c @@ -124,6 +124,11 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv) goto bad; } + if (is_dlock_type(vg->lock_type)) { + log_error("Cannot rename LV with lock_type %s", vg->lock_type); + goto bad; + } + if (!lv_rename(cmd, lvl->lv, lv_name_new)) goto_bad; diff --git a/tools/lvresize.c b/tools/lvresize.c index 08248bbec..f747d4ccf 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -174,6 +174,9 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv) if (!_lvresize_params(cmd, argc, argv, &lp)) return EINVALID_CMD_LINE; + if (!dlock_vg(cmd, lp.vg_name, "ex", 0)) + return_ECMD_FAILED; + log_verbose("Finding volume group %s", lp.vg_name); vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0); if (vg_read_error(vg)) { diff --git a/tools/toollib.c b/tools/toollib.c index 8a7c6cc3e..6b6c0db9b 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -1695,12 +1695,16 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags, vg_uuid = vgnl->vgid; ret = 0; + if (!dlock_vg(cmd, vg_name, NULL, 0)) + continue; + vg = vg_read(cmd, vg_name, vg_uuid, flags); if (ignore_vg(cmd, vg, vg_name, arg_vgnames, flags & READ_ALLOW_INCONSISTENT, &ret)) { if (ret > ret_max) ret_max = ret; release_vg(vg); + dlock_vg(cmd, vg_name, "un", 0); stack; continue; } @@ -1716,6 +1720,8 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags, else unlock_and_release_vg(cmd, vg, vg_name); + dlock_vg(cmd, vg_name, "un", 0); + if (ret > ret_max) ret_max = ret; if (sigint_caught()) @@ -2070,11 +2076,15 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags, } } + if (!dlock_vg(cmd, vg_name, NULL, 0)) + continue; + vg = vg_read(cmd, vg_name, vg_uuid, flags); if (ignore_vg(cmd, vg, vg_name, arg_vgnames, flags & READ_ALLOW_INCONSISTENT, &ret)) { if (ret > ret_max) ret_max = ret; release_vg(vg); + dlock_vg(cmd, vg_name, "un", 0); stack; continue; } @@ -2083,6 +2093,8 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags, handle, process_single_lv); unlock_and_release_vg(cmd, vg, vg_name); + dlock_vg(cmd, vg_name, "un", 0); + if (ret > ret_max) ret_max = ret; @@ -2386,6 +2398,9 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags, ret = 0; skip = 0; + if (!dlock_vg(cmd, vg_name, NULL, 0)) + continue; + vg = vg_read(cmd, vg_name, vg_uuid, flags | READ_WARN_INCONSISTENT); if (ignore_vg(cmd, vg, vg_name, NULL, flags & READ_ALLOW_INCONSISTENT, &ret)) { if (ret > ret_max) @@ -2404,6 +2419,8 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags, else unlock_and_release_vg(cmd, vg, vg->name); + dlock_vg(cmd, vg_name, "un", 0); + if (sigint_caught()) return_ECMD_FAILED; diff --git a/tools/tools.h b/tools/tools.h index 0f0495e0c..af554cc0b 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -110,6 +110,8 @@ struct arg_value_group_list { #define ENABLE_ALL_DEVS 0x00000008 /* Use only the first free arg as the vg name. */ #define ONLY_FIRST_NAME 0x00000010 +#define DLOCK_VG_SH 0x00000020 /* cmd never modifies a vg */ +#define DLOCK_VG_NA 0x00000040 /* vg lock does not apply to cmd */ /* a register of the lvm commands */ struct command { diff --git a/tools/vgchange.c b/tools/vgchange.c index 80d91c647..67f9d43d0 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -665,8 +665,45 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name, return ret; } +/* + * vgchange can do a 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 dlock_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->command->flags |= DLOCK_VG_SH; + + /* Starting a vg lockspace means there are no locks available yet. */ + + if (arg_is_set(cmd, lockstart_ARG)) + cmd->command->flags |= DLOCK_VG_NA; + + /* + * In most cases, dlock_vg does not apply when changing lock type. + * (We don't generally allow changing *from* dlock type yet.) + * dlock_vg could be called within _vgchange_locktype as needed. + */ + + if (arg_is_set(cmd, locktype_ARG)) + cmd->command->flags |= DLOCK_VG_NA; + + /* + * 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 diff --git a/tools/vgmerge.c b/tools/vgmerge.c index 41658af9a..92b49ad30 100644 --- a/tools/vgmerge.c +++ b/tools/vgmerge.c @@ -25,6 +25,13 @@ static struct volume_group *_vgmerge_vg_read(struct cmd_context *cmd, release_vg(vg); return NULL; } + + if (is_dlock_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; } diff --git a/tools/vgreduce.c b/tools/vgreduce.c index 95d0cca50..fb11a0c08 100644 --- a/tools/vgreduce.c +++ b/tools/vgreduce.c @@ -195,7 +195,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv) init_ignore_suspended_devices(1); cmd->handles_missing_pvs = 1; - if (!dlock_gl(cmd, "ex", 0)) + if (!dlock_gl_vg(cmd, vg_name, "ex", "ex", 0)) return_ECMD_FAILED; vg = vg_read_for_update(cmd, vg_name, NULL, READ_ALLOW_EXPORTED); diff --git a/tools/vgremove.c b/tools/vgremove.c index 6c31c9a3e..9941d04b1 100644 --- a/tools/vgremove.c +++ b/tools/vgremove.c @@ -67,6 +67,13 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name, lvmlockd_free_vg_final(cmd, vg); + /* + * The vg lock no longer exists, so don't bother unlocking it. + * (This would be nice to do in lvmlockd_free_vg_final(), but + * cmd->command is not accessible lib.) + */ + cmd->command->flags |= DLOCK_VG_NA; + return ECMD_PROCESSED; } diff --git a/tools/vgrename.c b/tools/vgrename.c index 8dc413920..a287a21f9 100644 --- a/tools/vgrename.c +++ b/tools/vgrename.c @@ -29,6 +29,12 @@ static struct volume_group *_get_old_vg_for_rename(struct cmd_context *cmd, return_NULL; } + if (is_dlock_type(vg->lock_type)) { + log_error("vgrename not allowed for lock_type %s", vg->lock_type); + unlock_and_release_vg(cmd, vg, vg_name_old); + return NULL; + } + return vg; } diff --git a/tools/vgsplit.c b/tools/vgsplit.c index 339bb52aa..40b6e67a6 100644 --- a/tools/vgsplit.c +++ b/tools/vgsplit.c @@ -453,6 +453,13 @@ static struct volume_group *_vgsplit_from(struct cmd_context *cmd, release_vg(vg_from); return NULL; } + + if (is_dlock_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; } |