mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +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:
parent
240db28214
commit
64dd17e539
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user