diff options
author | David Teigland <teigland@redhat.com> | 2021-09-02 16:55:04 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2021-10-07 12:45:22 -0500 |
commit | 64dd17e53904b8a77e8cdf25d5338bec40d8fef4 (patch) | |
tree | ce6e9a2eeb97a697fbf1783aae655ae1ff788a90 | |
parent | 240db28214a3ebb8e22b7d42904775333e6b96c1 (diff) | |
download | lvm2-64dd17e53904b8a77e8cdf25d5338bec40d8fef4.tar.gz |
pvscan, vgchange: add eventactivation option
A new file /run/lvm/event-activation-on is used to transition
from a fixed point in time activation (vgchange -aay) run by
a startup service, to event based activation
(pvscan --cache -aay) run by uevents.
vgchange -aay --vgonline --eventactivation enable
. creates /run/lvm/event-activation-on
. creates /run/lvm/pvs_online/ files for existing PVs
. looks for complete VGs
. creates vg online file
. activates complete VGs
pvscan --cache --eventactivation check ...
. checks if /run/lvm/event-activation-on exists
. if not, does nothing and quits
. if so, does traditional pvscan
If lvm.conf has event_activation=0, then do not create the
event-activation-on file to enable event activation from
vgchange -aay --eventactivation enable.
-rw-r--r-- | tools/args.h | 4 | ||||
-rw-r--r-- | tools/command-lines.in | 8 | ||||
-rw-r--r-- | tools/pvscan.c | 48 | ||||
-rw-r--r-- | tools/tools.h | 3 | ||||
-rw-r--r-- | tools/vgchange.c | 79 |
5 files changed, 130 insertions, 12 deletions
diff --git a/tools/args.h b/tools/args.h index 774ce33f4..491bd0417 100644 --- a/tools/args.h +++ b/tools/args.h @@ -278,6 +278,10 @@ arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0, "(Also see dm-thin-pool kernel module option no_space_timeout.)\n" "See \\fBlvmthin\\fP(7) for more information.\n") +arg(eventactivation_ARG, '\0', "eventactivation", string_VAL, 0, 0, + "Use a run file to coordinate the transition to event\n" + "activation.\n") + arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0, "Force metadata restore even with thin pool LVs.\n" "Use with extreme caution. Most changes to thin metadata\n" diff --git a/tools/command-lines.in b/tools/command-lines.in index 23ea33e6d..6e00f22b4 100644 --- a/tools/command-lines.in +++ b/tools/command-lines.in @@ -1642,14 +1642,15 @@ DESC: Record that a PV is online or offline. pvscan --cache_long --activate ay OO: --ignorelockingfailure, --reportformat ReportFmt, ---major Number, --minor Number, --noudevsync +--major Number, --minor Number, --noudevsync, --eventactivation String OP: PV|String ... IO: --background ID: pvscan_cache DESC: Record that a PV is online and autoactivate the VG if complete. pvscan --cache_long --listvg PV -OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput +OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput, +--eventactivation String ID: pvscan_cache DESC: Record that a PV is online and list the VG using the PV. @@ -1747,7 +1748,8 @@ DESC: Start or stop processing LV conversions. vgchange --activate Active OO: --activationmode ActivationMode, --ignoreactivationskip, --partial, --sysinit, ---readonly, --ignorelockingfailure, --monitor Bool, --poll Bool, --vgonline, OO_VGCHANGE +--readonly, --ignorelockingfailure, --monitor Bool, --poll Bool, +--vgonline, --eventactivation String, OO_VGCHANGE OP: VG|Tag|Select ... IO: --ignoreskippedcluster ID: vgchange_activate diff --git a/tools/pvscan.c b/tools/pvscan.c index ada1f07fe..5955b4079 100644 --- a/tools/pvscan.c +++ b/tools/pvscan.c @@ -20,6 +20,7 @@ #include "lib/label/hints.h" #include <dirent.h> +#include <time.h> struct pvscan_params { int new_pvs_found; @@ -46,6 +47,8 @@ static const char *_pvs_online_dir = DEFAULT_RUN_DIR "/pvs_online"; static const char *_vgs_online_dir = DEFAULT_RUN_DIR "/vgs_online"; static const char *_pvs_lookup_dir = DEFAULT_RUN_DIR "/pvs_lookup"; +static const char *_event_activation_file = DEFAULT_RUN_DIR "/event-activation-on"; + static int _pvscan_display_pv(struct cmd_context *cmd, struct physical_volume *pv, struct pvscan_params *params) @@ -179,6 +182,30 @@ out: return ret; } +int event_activation_enable(struct cmd_context *cmd) +{ + FILE *fp; + + if (!(fp = fopen(_event_activation_file, "w"))) + return_0; + if (fclose(fp)) + stack; + return 1; +} + +int event_activation_is_on(struct cmd_context *cmd) +{ + struct stat buf; + + if (!stat(_event_activation_file, &buf)) + return 1; + + if (errno != ENOENT) + log_debug("event_activation_is_on errno %d", errno); + + return 0; +} + /* * Avoid a duplicate pvscan[%d] prefix when logging to the journal. * FIXME: this should probably replace if (udevoutput) with @@ -367,7 +394,7 @@ static void _online_files_remove(const char *dirpath) log_sys_debug("closedir", dirpath); } -static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname) +int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname, int ignore_existing, int *exists) { char path[PATH_MAX]; char buf[MAX_PVID_FILE_SIZE] = { 0 }; @@ -407,8 +434,13 @@ static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev, fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); if (fd < 0) { - if (errno == EEXIST) + if (errno == EEXIST) { + if (exists) + *exists = 1; + if (ignore_existing) + return 1; goto check_duplicate; + } log_error_pvscan(cmd, "Failed to create online file for %s path %s error %d", dev_name(dev), path, errno); return 0; } @@ -427,7 +459,6 @@ static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev, } /* We don't care about syncing, these files are not even persistent. */ - if (close(fd)) log_sys_debug("close", path); @@ -1412,7 +1443,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs * Create file named for pvid to record this PV is online. * The command creates/checks online files only when --cache is used. */ - if (do_cache && !_online_pvid_file_create(cmd, dev, vg ? vg->name : NULL)) { + if (do_cache && !online_pvid_file_create(cmd, dev, vg ? vg->name : NULL, 0, NULL)) { log_error_pvscan(cmd, "PV %s failed to create online file.", dev_name(dev)); release_vg(vg); ret = 0; @@ -1857,6 +1888,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) { struct pvscan_aa_params pp = { 0 }; struct dm_list complete_vgnames; + const char *ea; int do_activate = arg_is_set(cmd, activate_ARG); int event_activation; int devno_args = 0; @@ -1930,6 +1962,14 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) log_verbose("Ignoring pvscan --cache because event_activation is disabled."); return ECMD_PROCESSED; } + + if ((ea = arg_str_value(cmd, eventactivation_ARG, NULL)) && + !strcmp(ea, "check") && + !event_activation_is_on(cmd)) { + log_verbose("Ignoring pvscan --cache because event_activation is not started."); + return ECMD_PROCESSED; + } + if (!_pvscan_cache_args(cmd, argc, argv, &complete_vgnames)) return ECMD_FAILED; } diff --git a/tools/tools.h b/tools/tools.h index e2661f272..37b7d5a7e 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -295,8 +295,11 @@ int lvconvert_cachevol_attach_single(struct cmd_context *cmd, struct logical_volume *lv, struct processing_handle *handle); +int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname, int ignore_existing, int *exists); void online_vg_file_remove(const char *vgname); int online_vg_file_create(struct cmd_context *cmd, const char *vgname); void online_dir_setup(struct cmd_context *cmd); +int event_activation_enable(struct cmd_context *cmd); +int event_activation_is_on(struct cmd_context *cmd); #endif diff --git a/tools/vgchange.c b/tools/vgchange.c index 985907a02..d9779a8a0 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -194,6 +194,41 @@ int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg return 1; } +static int _online_pvid_file_create_all(struct cmd_context *cmd) +{ + struct lvmcache_info *info; + struct dev_iter *iter; + struct device *dev; + const char *vgname; + int exists; + int exist_count = 0; + int create_count = 0; + + if (!(iter = dev_iter_create(NULL, 0))) + return 0; + while ((dev = dev_iter_get(cmd, iter))) { + if (dev->pvid[0] && + (info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) { + vgname = lvmcache_vgname_from_info(info); + if (vgname && !is_orphan_vg(vgname)) { + /* + * Ignore exsting pvid file because a pvscan may be creating + * the same file as the same time we are, which is expected. + */ + exists = 0; + online_pvid_file_create(cmd, dev, vgname, 1, &exists); + if (exists) + exist_count++; + else + create_count++; + } + } + } + dev_iter_destroy(iter); + log_debug("PV online files created %d exist %d", create_count, exist_count); + return 1; +} + int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg, activation_change_t activate) { @@ -219,6 +254,11 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg, return 1; } + if (arg_is_set(cmd, vgonline_ARG) && !online_vg_file_create(cmd, vg->name)) { + log_print("VG %s already online", vg->name); + return 1; + } + /* * Safe, since we never write out new metadata here. Required for * partial activation to work. @@ -262,11 +302,6 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg, } } - if (arg_is_set(cmd, vgonline_ARG) && !online_vg_file_create(cmd, vg->name)) { - log_print("VG %s finished", vg->name); - return 1; - } - if (!_activate_lvs_in_vg(cmd, vg, activate)) { stack; r = 0; @@ -733,6 +768,7 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name, int vgchange(struct cmd_context *cmd, int argc, char **argv) { struct processing_handle *handle; + const char *ea; uint32_t flags = 0; int ret; @@ -845,6 +881,39 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv) cmd->lockd_vg_enforce_sh = 1; } + /* + * When enabling event-based activation for pvscan, we first created + * the /run/lvm/event-activation-on file to tell pvscans to begin + * processing new PVs and doing activation for newly completed VGs. We + * also need to create online files for existing PVs because some VGs + * may be incomplete at this point, and future pvscan commands need to + * find online files for PVs that have already appeared. The label + * scan gives us the info to know which PVs are present and should have + * pvid online files created. + * + * process_each_vg() usually begins with lock_global() and + * lvmcache_label_scan(), and then processes each VG. In this case, + * lock_global/lvmcache_label_scan are done before calling + * process_each_vg. This allows a special step to be inserted between + * the label scan and processing vgs. That step creates the pvid online + * files, which requires label scan info. The lock_global and + * lvmcache_label_scan will be skipped by process_each_vg since they + * are already done here. + */ + if ((ea = arg_str_value(cmd, eventactivation_ARG, NULL)) && !strcmp(ea, "enable")) { + if (!find_config_tree_bool(cmd, global_event_activation_CFG, NULL)) { + log_print("Skip event activation enable for lvm.conf event_activation 0."); + } else { + if (!event_activation_enable(cmd)) + log_warn("WARNING: failed to enable event activation"); + } + if (!lock_global(cmd, "sh")) + return ECMD_FAILED; + lvmcache_label_scan(cmd); + _online_pvid_file_create_all(cmd); + flags |= PROCESS_SKIP_SCAN; + } + if (update) flags |= READ_FOR_UPDATE; else if (arg_is_set(cmd, activate_ARG)) |