1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-10 16:58:47 +03:00

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.
This commit is contained in:
David Teigland 2021-09-02 16:55:04 -05:00
parent 240db28214
commit 64dd17e539
5 changed files with 130 additions and 12 deletions

View File

@ -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" "(Also see dm-thin-pool kernel module option no_space_timeout.)\n"
"See \\fBlvmthin\\fP(7) for more information.\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, arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0,
"Force metadata restore even with thin pool LVs.\n" "Force metadata restore even with thin pool LVs.\n"
"Use with extreme caution. Most changes to thin metadata\n" "Use with extreme caution. Most changes to thin metadata\n"

View File

@ -1642,14 +1642,15 @@ DESC: Record that a PV is online or offline.
pvscan --cache_long --activate ay pvscan --cache_long --activate ay
OO: --ignorelockingfailure, --reportformat ReportFmt, OO: --ignorelockingfailure, --reportformat ReportFmt,
--major Number, --minor Number, --noudevsync --major Number, --minor Number, --noudevsync, --eventactivation String
OP: PV|String ... OP: PV|String ...
IO: --background IO: --background
ID: pvscan_cache ID: pvscan_cache
DESC: Record that a PV is online and autoactivate the VG if complete. DESC: Record that a PV is online and autoactivate the VG if complete.
pvscan --cache_long --listvg PV pvscan --cache_long --listvg PV
OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput,
--eventactivation String
ID: pvscan_cache ID: pvscan_cache
DESC: Record that a PV is online and list the VG using the PV. 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 vgchange --activate Active
OO: --activationmode ActivationMode, --ignoreactivationskip, --partial, --sysinit, 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 ... OP: VG|Tag|Select ...
IO: --ignoreskippedcluster IO: --ignoreskippedcluster
ID: vgchange_activate ID: vgchange_activate

View File

@ -20,6 +20,7 @@
#include "lib/label/hints.h" #include "lib/label/hints.h"
#include <dirent.h> #include <dirent.h>
#include <time.h>
struct pvscan_params { struct pvscan_params {
int new_pvs_found; 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 *_vgs_online_dir = DEFAULT_RUN_DIR "/vgs_online";
static const char *_pvs_lookup_dir = DEFAULT_RUN_DIR "/pvs_lookup"; 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, static int _pvscan_display_pv(struct cmd_context *cmd,
struct physical_volume *pv, struct physical_volume *pv,
struct pvscan_params *params) struct pvscan_params *params)
@ -179,6 +182,30 @@ out:
return ret; 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. * Avoid a duplicate pvscan[%d] prefix when logging to the journal.
* FIXME: this should probably replace if (udevoutput) with * 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); 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 path[PATH_MAX];
char buf[MAX_PVID_FILE_SIZE] = { 0 }; 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); fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) { if (fd < 0) {
if (errno == EEXIST) if (errno == EEXIST) {
if (exists)
*exists = 1;
if (ignore_existing)
return 1;
goto check_duplicate; goto check_duplicate;
}
log_error_pvscan(cmd, "Failed to create online file for %s path %s error %d", dev_name(dev), path, errno); log_error_pvscan(cmd, "Failed to create online file for %s path %s error %d", dev_name(dev), path, errno);
return 0; 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. */ /* We don't care about syncing, these files are not even persistent. */
if (close(fd)) if (close(fd))
log_sys_debug("close", path); 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. * Create file named for pvid to record this PV is online.
* The command creates/checks online files only when --cache is used. * 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)); log_error_pvscan(cmd, "PV %s failed to create online file.", dev_name(dev));
release_vg(vg); release_vg(vg);
ret = 0; 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 pvscan_aa_params pp = { 0 };
struct dm_list complete_vgnames; struct dm_list complete_vgnames;
const char *ea;
int do_activate = arg_is_set(cmd, activate_ARG); int do_activate = arg_is_set(cmd, activate_ARG);
int event_activation; int event_activation;
int devno_args = 0; 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."); log_verbose("Ignoring pvscan --cache because event_activation is disabled.");
return ECMD_PROCESSED; 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)) if (!_pvscan_cache_args(cmd, argc, argv, &complete_vgnames))
return ECMD_FAILED; return ECMD_FAILED;
} }

View File

@ -295,8 +295,11 @@ int lvconvert_cachevol_attach_single(struct cmd_context *cmd,
struct logical_volume *lv, struct logical_volume *lv,
struct processing_handle *handle); 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); void online_vg_file_remove(const char *vgname);
int online_vg_file_create(struct cmd_context *cmd, const char *vgname); int online_vg_file_create(struct cmd_context *cmd, const char *vgname);
void online_dir_setup(struct cmd_context *cmd); 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 #endif

View File

@ -194,6 +194,41 @@ int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg
return 1; 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, int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
activation_change_t activate) activation_change_t activate)
{ {
@ -219,6 +254,11 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
return 1; 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 * Safe, since we never write out new metadata here. Required for
* partial activation to work. * 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)) { if (!_activate_lvs_in_vg(cmd, vg, activate)) {
stack; stack;
r = 0; 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) int vgchange(struct cmd_context *cmd, int argc, char **argv)
{ {
struct processing_handle *handle; struct processing_handle *handle;
const char *ea;
uint32_t flags = 0; uint32_t flags = 0;
int ret; int ret;
@ -845,6 +881,39 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
cmd->lockd_vg_enforce_sh = 1; 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) if (update)
flags |= READ_FOR_UPDATE; flags |= READ_FOR_UPDATE;
else if (arg_is_set(cmd, activate_ARG)) else if (arg_is_set(cmd, activate_ARG))