From 943e97907956d73efcbf19a1662fb7bc09520f9c Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 18 Jun 2024 11:24:02 -0500 Subject: [PATCH] lvmlockd: parse lockopt string into flags --- lib/commands/toolcontext.h | 1 + lib/locking/lvmlockd.c | 65 ++++++++++++++++++++++++++++++-- lib/locking/lvmlockd.h | 16 +++++++- lib/metadata/metadata-exported.h | 1 - tools/lvmcmdline.c | 9 +++-- tools/lvresize.c | 1 - tools/vgchange.c | 21 ++++------- tools/vgcreate.c | 10 ++--- tools/vgremove.c | 2 +- 9 files changed, 94 insertions(+), 32 deletions(-) diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 8c1d81d6d..0f93813d7 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -286,6 +286,7 @@ struct cmd_context { struct dm_list pending_delete; /* list of LVs for removal */ struct dm_pool *pending_delete_mem; /* memory pool for pending deletes */ struct vdo_convert_params *lvcreate_vcp;/* params for LV to VDO conversion */ + uint32_t lockopt; /* LOCKOPT_* from --lockopt string */ }; /* diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c index 4d3f398c9..4b5f0278b 100644 --- a/lib/locking/lvmlockd.c +++ b/lib/locking/lvmlockd.c @@ -1223,11 +1223,11 @@ static int _lockd_all_lvs(struct cmd_context *cmd, struct volume_group *vg) /* vgremove before the vg is removed */ int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg, - int changing, const char *lockopt, int yes) + int changing, int yes) { int lock_type_num = get_lock_type_from_string(vg->lock_type); - if (lockopt && strstr(lockopt, "force")) { + if (cmd->lockopt & LOCKOPT_FORCE) { if (!yes && yes_no_prompt("Force unprotected removal of shared VG? [y/n]: ") == 'n') { log_error("VG not removed."); return 0; @@ -2782,8 +2782,8 @@ int lockd_lv_resize(struct cmd_context *cmd, struct logical_volume *lv, { char lv_uuid[64] __attribute__((aligned(8))); char path[PATH_MAX]; - int shupdate = (lp->lockopt && strstr(lp->lockopt, "shupdate")); - int norefresh = (lp->lockopt && strstr(lp->lockopt, "norefresh")); + int shupdate = cmd->lockopt & LOCKOPT_SHUPDATE; + int norefresh = cmd->lockopt & LOCKOPT_NOREFRESH; int rv; if (!vg_is_shared(lv->vg)) @@ -3453,3 +3453,60 @@ int lockd_lv_refresh(struct cmd_context *cmd, struct lvresize_params *lp) return 1; } +static void _split_line(char *buf, int *argc, char **argv, int max_args, char sep) +{ + char *p = buf; + int i; + + argv[0] = p; + + for (i = 1; i < max_args; i++) { + p = strchr(p, sep); + if (!p) + break; + *p++ = '\0'; + + argv[i] = p; + } + *argc = i; +} + +#define MAX_LOCKOPT 16 + +void lockd_lockopt_get_flags(const char *str, uint32_t *flags) +{ + char buf[PATH_MAX]; + char *argv[MAX_LOCKOPT]; + int argc; + int i; + + if (!str) + return; + + dm_strncpy(buf, str, sizeof(buf)); + + _split_line(buf, &argc, argv, MAX_LOCKOPT, ','); + + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "force")) + *flags |= LOCKOPT_FORCE; + else if (!strcmp(argv[i], "shupdate")) + *flags |= LOCKOPT_SHUPDATE; + else if (!strcmp(argv[i], "norefresh")) + *flags |= LOCKOPT_NOREFRESH; + else if (!strcmp(argv[i], "skipgl")) + *flags |= LOCKOPT_SKIPGL; + else if (!strcmp(argv[i], "skipvg")) + *flags |= LOCKOPT_SKIPVG; + else if (!strcmp(argv[i], "skiplv")) + *flags |= LOCKOPT_SKIPLV; + else if (!strcmp(argv[i], "auto")) + *flags |= LOCKOPT_AUTO; + else if (!strcmp(argv[i], "nowait")) + *flags |= LOCKOPT_NOWAIT; + else if (!strcmp(argv[i], "autonowait")) + *flags |= LOCKOPT_AUTONOWAIT; + else + log_warn("Ignoring unknown lockopt value: %s", argv[i]); + } +} diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h index 59be37609..eda6ed015 100644 --- a/lib/locking/lvmlockd.h +++ b/lib/locking/lvmlockd.h @@ -39,6 +39,19 @@ #define LDST_FAIL_OTHER 0x00000020 #define LDST_FAIL (LDST_FAIL_REQUEST | LDST_FAIL_NOLS | LDST_FAIL_STARTING | LDST_FAIL_OTHER) +/* --lockopt flags */ +#define LOCKOPT_FORCE 0x00000001 +#define LOCKOPT_SHUPDATE 0x00000002 +#define LOCKOPT_NOREFRESH 0x00000004 +#define LOCKOPT_SKIPGL 0x00000008 +#define LOCKOPT_SKIPVG 0x00000010 +#define LOCKOPT_SKIPLV 0x00000020 +#define LOCKOPT_AUTO 0x00000040 +#define LOCKOPT_NOWAIT 0x00000080 +#define LOCKOPT_AUTONOWAIT 0x00000100 + +void lockd_lockopt_get_flags(const char *str, uint32_t *flags); + #ifdef LVMLOCKD_SUPPORT struct lvresize_params; @@ -53,10 +66,11 @@ void lvmlockd_init(struct cmd_context *cmd); void lvmlockd_connect(void); void lvmlockd_disconnect(void); + /* vgcreate/vgremove use init/free */ int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg, const char *lock_type, int lv_lock_count); -int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg, int changing, const char *lockopt, int yes); +int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg, int changing, int yes); void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg); /* vgrename */ diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index 3d5e3ce72..e7cf8cc0d 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -699,7 +699,6 @@ struct lvresize_params { int extend_fs_error; /* FS extend error after LV extend success */ int vg_changed_error; /* VG metadata was modified during fs resize */ - const char *lockopt; char *lockd_lv_refresh_path; /* set during resize to use for refresh at the end */ char *lockd_lv_refresh_uuid; /* set during resize to use for refresh at the end */ diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 2ac0b9506..1b2f7f47c 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -2943,16 +2943,17 @@ static int _init_lvmlockd(struct cmd_context *cmd) } if (use_lvmlockd && arg_is_set(cmd, lockopt_ARG)) { - const char *opts = arg_str_value(cmd, lockopt_ARG, ""); - if (strstr(opts, "skiplv")) { + lockd_lockopt_get_flags(arg_str_value(cmd, lockopt_ARG, ""), &cmd->lockopt); + + if (cmd->lockopt & LOCKOPT_SKIPLV) { log_warn("WARNING: skipping LV lock in lvmlockd."); cmd->lockd_lv_disable = 1; } - if (strstr(opts, "skipvg")) { + if (cmd->lockopt & LOCKOPT_SKIPVG) { log_warn("WARNING: skipping VG lock in lvmlockd."); cmd->lockd_vg_disable = 1; } - if (strstr(opts, "skipgl")) { + if (cmd->lockopt & LOCKOPT_SKIPGL) { log_warn("WARNING: skipping global lock in lvmlockd."); cmd->lockd_gl_disable = 1; } diff --git a/tools/lvresize.c b/tools/lvresize.c index 0bcda3d3d..4431a886f 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -195,7 +195,6 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp) lp->yes = arg_is_set(cmd, yes_ARG); lp->force = arg_is_set(cmd, force_ARG), lp->nosync = arg_is_set(cmd, nosync_ARG); - lp->lockopt = arg_str_value(cmd, lockopt_ARG, NULL); if (type_str) { if (!strcmp(type_str, "linear")) { diff --git a/tools/vgchange.c b/tools/vgchange.c index 0fab16ccd..5eba2a1b3 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -647,7 +647,6 @@ static int _passes_lock_start_filter(struct cmd_context *cmd, static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg, struct vgchange_params *vp) { - const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL); int auto_opt = 0; int exists = 0; int r; @@ -659,10 +658,9 @@ static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg goto do_start; /* - * Recognize both "auto" and "autonowait" options. * Any waiting is done at the end of vgchange. */ - if (start_opt && !strncmp(start_opt, "auto", 4)) + if ((cmd->lockopt & LOCKOPT_AUTO) || (cmd->lockopt & LOCKOPT_AUTONOWAIT)) auto_opt = 1; if (!_passes_lock_start_filter(cmd, vg, activation_lock_start_list_CFG)) { @@ -1144,13 +1142,12 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv) static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg, int *no_change) { const char *lock_type = arg_str_value(cmd, locktype_ARG, NULL); - const char *lockopt = arg_str_value(cmd, lockopt_ARG, NULL); struct lv_list *lvl; struct logical_volume *lv; int lv_lock_count = 0; /* Special recovery case. */ - if (lock_type && lockopt && !strcmp(lock_type, "none") && !strcmp(lockopt, "force")) { + if (lock_type && !strcmp(lock_type, "none") && (cmd->lockopt & LOCKOPT_FORCE)) { vg->status &= ~CLUSTERED; vg->lock_type = "none"; vg->lock_args = NULL; @@ -1215,7 +1212,7 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg, * lockd type to ..., first undo lockd type */ if (is_lockd_type(vg->lock_type)) { - if (!lockd_free_vg_before(cmd, vg, 1, NULL, 0)) + if (!lockd_free_vg_before(cmd, vg, 1, 0)) return 0; lockd_free_vg_final(cmd, vg); @@ -1347,9 +1344,9 @@ int vgchange_locktype_cmd(struct cmd_context *cmd, int argc, char **argv) { struct processing_handle *handle; const char *lock_type = arg_str_value(cmd, locktype_ARG, NULL); - const char *lockopt = arg_str_value(cmd, lockopt_ARG, NULL); int ret; + /* * vgchange --locktype none --lockopt force VG * @@ -1372,7 +1369,7 @@ int vgchange_locktype_cmd(struct cmd_context *cmd, int argc, char **argv) * disable locking. lockd_gl(), lockd_vg() and lockd_lv() will * just return success when they see the disable flag set. */ - if (lockopt && !strcmp(lockopt, "force")) { + if (cmd->lockopt & LOCKOPT_FORCE) { if (!arg_is_set(cmd, yes_ARG) && yes_no_prompt("Forcibly change VG lock type to %s? [y/n]: ", lock_type) == 'n') { log_error("VG lock type not changed."); @@ -1480,19 +1477,17 @@ int vgchange_lock_start_stop_cmd(struct cmd_context *cmd, int argc, char **argv) /* Wait for lock-start ops that were initiated in vgchange_lockstart. */ if (arg_is_set(cmd, lockstart_ARG) && vp.lock_start_count) { - const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL); - if (!lockd_global(cmd, "un")) stack; - if (!start_opt || !strcmp(start_opt, "auto")) { + if ((cmd->lockopt & LOCKOPT_NOWAIT) || (cmd->lockopt & LOCKOPT_AUTONOWAIT)) { + log_print_unless_silent("Starting locking. VG can only be read until locks are ready."); + } else { if (vp.lock_start_sanlock) log_print_unless_silent("Starting locking. Waiting for sanlock may take a few seconds to 3 min..."); else log_print_unless_silent("Starting locking. Waiting until locks are ready..."); lockd_start_wait(cmd); - } else if (!strcmp(start_opt, "nowait") || !strcmp(start_opt, "autonowait")) { - log_print_unless_silent("Starting locking. VG can only be read until locks are ready."); } } diff --git a/tools/vgcreate.c b/tools/vgcreate.c index e65abb7cd..a82096e75 100644 --- a/tools/vgcreate.c +++ b/tools/vgcreate.c @@ -181,8 +181,6 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) * read without locks until the lockspace is done starting.) */ if (vg_is_shared(vg)) { - const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL); - if (!lockd_start_vg(cmd, vg, NULL)) { log_error("Failed to start locking"); goto out; @@ -190,15 +188,13 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) lock_global(cmd, "un"); - if (!start_opt || !strcmp(start_opt, "wait")) { + if (cmd->lockopt & LOCKOPT_NOWAIT) { + log_print_unless_silent("Starting locking. VG is read-only until locks are ready."); + } else { /* It is OK if the user does Ctrl-C to cancel the wait. */ log_print_unless_silent("Starting locking. Waiting until locks are ready..."); lockd_start_wait(cmd); - - } else if (!strcmp(start_opt, "nowait")) { - log_print_unless_silent("Starting locking. VG is read-only until locks are ready."); } - } out: release_vg(vg); diff --git a/tools/vgremove.c b/tools/vgremove.c index 94615aea3..3ccb63d53 100644 --- a/tools/vgremove.c +++ b/tools/vgremove.c @@ -70,7 +70,7 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name, !lvremove_single(cmd, vg->pool_metadata_spare_lv, &void_handle)) return_ECMD_FAILED; - if (!lockd_free_vg_before(cmd, vg, 0, arg_str_value(cmd, lockopt_ARG, NULL), arg_is_set(cmd, yes_ARG))) + if (!lockd_free_vg_before(cmd, vg, 0, arg_is_set(cmd, yes_ARG))) return_ECMD_FAILED; if (!force && !vg_remove_check(vg))