mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
vgchange -aay: improve unexpected command variations
For completeness and consistency, adjust the behavior for some variations of: vgchange -aay --autoactivation event [vgname] The current standard use is with a VG name arg, and the command is only called when all pvs_online files exist. This is the optimal case, in which only pvs_online devs are read. This remains the same. Clean up behaviors for some other unexpected uses of the command: . With no VG name arg, the command activates any VGs that are complete according to pvs_online. If no pvs_online files exist, it does nothing. . If a VG name is used but no PVs online files exist for the VG, or the PVs online files are incomplete, then consider there could be a problem with the pvs_online files, and fall back to a full label scan prior to attempting the activation.
This commit is contained in:
parent
14b68ea313
commit
024ce50f06
@ -2164,7 +2164,7 @@ static char *_get_devname_from_devno(struct cmd_context *cmd, dev_t devno)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (devname[0]) {
|
if (devname[0]) {
|
||||||
log_debug("Found %s for %d:%d from sys", devname, major, minor);
|
log_debug("Found %s for %d:%d from sys dm", devname, major, minor);
|
||||||
return _strdup(devname);
|
return _strdup(devname);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -134,8 +134,12 @@ int get_pvs_online(struct dm_list *pvs_online, const char *vgname)
|
|||||||
|
|
||||||
dm_list_add(pvs_online, &po->list);
|
dm_list_add(pvs_online, &po->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closedir(dir))
|
if (closedir(dir))
|
||||||
log_sys_debug("closedir", PVS_ONLINE_DIR);
|
log_sys_debug("closedir", PVS_ONLINE_DIR);
|
||||||
|
|
||||||
|
log_debug("PVs online found %d for %s", dm_list_size(pvs_online), vgname ?: "all");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,6 +359,8 @@ int get_pvs_lookup(struct dm_list *pvs_online, const char *vgname)
|
|||||||
dm_list_add(pvs_online, &po->list);
|
dm_list_add(pvs_online, &po->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_debug("PVs online lookup found %d for %s", dm_list_size(pvs_online), vgname);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -1023,13 +1023,13 @@ int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Use files under /run/lvm/, created by pvscan --cache autoactivation,
|
* Use files under /run/lvm/, created by pvscan --cache autoactivation,
|
||||||
* to optimize device setup/scanning for a command that is run for a
|
* to optimize device setup/scanning. autoactivation happens during
|
||||||
* specific vg name. autoactivation happens during system startup
|
* system startup when the hints file is not useful, but he pvs_online
|
||||||
* when the hints file is not useful, so this uses the online files as
|
* files can provide a similar optimization to the hints file.
|
||||||
* an alternative.
|
*/
|
||||||
*/
|
|
||||||
|
int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
|
||||||
int label_scan_vg_online(struct cmd_context *cmd, const char *vgname)
|
int *found_none, int *found_all, int *found_incomplete)
|
||||||
{
|
{
|
||||||
struct dm_list pvs_online;
|
struct dm_list pvs_online;
|
||||||
struct dm_list devs;
|
struct dm_list devs;
|
||||||
@ -1042,6 +1042,8 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname)
|
|||||||
dm_list_init(&pvs_online);
|
dm_list_init(&pvs_online);
|
||||||
dm_list_init(&devs);
|
dm_list_init(&devs);
|
||||||
|
|
||||||
|
log_debug_devs("Finding online devices to scan");
|
||||||
|
|
||||||
/* reads devices file, does not populate dev-cache */
|
/* reads devices file, does not populate dev-cache */
|
||||||
if (!setup_devices_for_online_autoactivation(cmd))
|
if (!setup_devices_for_online_autoactivation(cmd))
|
||||||
return 0;
|
return 0;
|
||||||
@ -1055,11 +1057,21 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname)
|
|||||||
* info from the online files tell us which devices those PVs are
|
* info from the online files tell us which devices those PVs are
|
||||||
* located on.
|
* located on.
|
||||||
*/
|
*/
|
||||||
if (!get_pvs_lookup(&pvs_online, vgname)) {
|
if (vgname) {
|
||||||
if (!get_pvs_online(&pvs_online, vgname))
|
if (!get_pvs_lookup(&pvs_online, vgname)) {
|
||||||
|
if (!get_pvs_online(&pvs_online, vgname))
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!get_pvs_online(&pvs_online, NULL))
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dm_list_empty(&pvs_online)) {
|
||||||
|
*found_none = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each po devno add a struct dev to dev-cache. This is a faster
|
* For each po devno add a struct dev to dev-cache. This is a faster
|
||||||
* alternative to the usual dev_cache_scan() which looks at all
|
* alternative to the usual dev_cache_scan() which looks at all
|
||||||
@ -1201,8 +1213,10 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname)
|
|||||||
|
|
||||||
free_po_list(&pvs_online);
|
free_po_list(&pvs_online);
|
||||||
|
|
||||||
if (dm_list_empty(&devs))
|
if (dm_list_empty(&devs)) {
|
||||||
|
*found_none = 1;
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan devs to populate lvmcache info, which includes the mda info that's
|
* Scan devs to populate lvmcache info, which includes the mda info that's
|
||||||
@ -1220,13 +1234,17 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname)
|
|||||||
* be able to fall back to a standard label scan if the online hints
|
* be able to fall back to a standard label scan if the online hints
|
||||||
* gave fewer PVs than listed in VG metadata.
|
* gave fewer PVs than listed in VG metadata.
|
||||||
*/
|
*/
|
||||||
metadata_pv_count = lvmcache_pvsummary_count(vgname);
|
if (vgname) {
|
||||||
if (metadata_pv_count != dm_list_size(&devs)) {
|
metadata_pv_count = lvmcache_pvsummary_count(vgname);
|
||||||
log_debug("Incorrect PV list from online files %d metadata %d.",
|
if (metadata_pv_count > dm_list_size(&devs)) {
|
||||||
dm_list_size(&devs), metadata_pv_count);
|
log_debug("Incomplete PV list from online files %d metadata %d.",
|
||||||
return 0;
|
dm_list_size(&devs), metadata_pv_count);
|
||||||
|
*found_incomplete = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*found_all = 1;
|
||||||
return 1;
|
return 1;
|
||||||
bad:
|
bad:
|
||||||
free_po_list(&pvs_online);
|
free_po_list(&pvs_online);
|
||||||
|
@ -118,7 +118,9 @@ int label_scan_open_excl(struct device *dev);
|
|||||||
int label_scan_open_rw(struct device *dev);
|
int label_scan_open_rw(struct device *dev);
|
||||||
int label_scan_reopen_rw(struct device *dev);
|
int label_scan_reopen_rw(struct device *dev);
|
||||||
int label_read_pvid(struct device *dev, int *has_pvid);
|
int label_read_pvid(struct device *dev, int *has_pvid);
|
||||||
int label_scan_vg_online(struct cmd_context *cmd, const char *vgname);
|
int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
|
||||||
|
int *found_none, int *found_all, int *found_incomplete);
|
||||||
|
|
||||||
|
|
||||||
int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev_out);
|
int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev_out);
|
||||||
|
|
||||||
|
@ -19,62 +19,136 @@ _clear_online_files() {
|
|||||||
|
|
||||||
aux prepare_devs 4
|
aux prepare_devs 4
|
||||||
|
|
||||||
|
# Because mapping devno to devname gets dm name from sysfs
|
||||||
|
aux lvmconf 'devices/scan = "/dev"'
|
||||||
|
base1=$(basename $dev1)
|
||||||
|
base2=$(basename $dev2)
|
||||||
|
base3=$(basename $dev3)
|
||||||
|
base4=$(basename $dev4)
|
||||||
|
aux extend_filter "a|/dev/mapper/$base1|"
|
||||||
|
aux extend_filter "a|/dev/mapper/$base2|"
|
||||||
|
aux extend_filter "a|/dev/mapper/$base3|"
|
||||||
|
aux extend_filter "a|/dev/mapper/$base4|"
|
||||||
|
|
||||||
vgcreate $vg1 "$dev1" "$dev2"
|
vgcreate $vg1 "$dev1" "$dev2"
|
||||||
vgcreate $vg2 "$dev3"
|
vgcreate $vg2 "$dev3"
|
||||||
pvcreate "$dev4"
|
pvcreate "$dev4"
|
||||||
|
|
||||||
lvcreate -l1 -n $lv1 -an $vg1
|
lvcreate -l1 -n $lv1 -an $vg1
|
||||||
|
lvcreate -l1 -n $lv2 -an $vg1
|
||||||
lvcreate -l1 -n $lv1 -an $vg2
|
lvcreate -l1 -n $lv1 -an $vg2
|
||||||
|
|
||||||
# With no pv online files, vgchange that uses online files
|
# Expected use, with vg name and all online files exist for vgchange.
|
||||||
# will find no PVs to activate from.
|
|
||||||
|
|
||||||
_clear_online_files
|
_clear_online_files
|
||||||
|
|
||||||
not vgchange -aay --autoactivation event $vg1
|
|
||||||
not vgchange -aay --autoactivation event $vg2
|
|
||||||
vgchange -aay --autoactivation event
|
|
||||||
|
|
||||||
check lv_field $vg1/$lv1 lv_active ""
|
|
||||||
check lv_field $vg2/$lv1 lv_active ""
|
|
||||||
|
|
||||||
# incomplete vg will not be activated
|
|
||||||
|
|
||||||
pvscan --cache "$dev1"
|
pvscan --cache "$dev1"
|
||||||
|
pvscan --cache "$dev2"
|
||||||
vgchange -aay --autoactivation event $vg1
|
vgchange -aay --autoactivation event $vg1
|
||||||
# VG foo is incomplete
|
check lv_field $vg1/$lv1 lv_active "active"
|
||||||
check lv_field $vg1/$lv1 lv_active ""
|
check lv_field $vg1/$lv2 lv_active "active"
|
||||||
|
check lv_field $vg2/$lv1 lv_active ""
|
||||||
# complete vg is activated
|
|
||||||
|
|
||||||
pvscan --cache "$dev3"
|
pvscan --cache "$dev3"
|
||||||
vgchange -aay --autoactivation event $vg2
|
vgchange -aay --autoactivation event $vg2
|
||||||
check lv_field $vg2/$lv1 lv_active "active"
|
check lv_field $vg2/$lv1 lv_active "active"
|
||||||
|
|
||||||
pvscan --cache "$dev2"
|
# Count io to check the pvs_online optimization
|
||||||
vgchange -aay --autoactivation event $vg1
|
# is working to limit scanning.
|
||||||
check lv_field $vg1/$lv1 lv_active "active"
|
|
||||||
|
|
||||||
vgchange -an $vg1
|
|
||||||
vgchange -an $vg2
|
|
||||||
|
|
||||||
# the same tests but using command options matching udev rule
|
|
||||||
|
|
||||||
|
vgchange -an
|
||||||
_clear_online_files
|
_clear_online_files
|
||||||
|
|
||||||
pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$dev1"
|
pvscan --cache "$dev1"
|
||||||
vgchange -aay --autoactivation event $vg1
|
pvscan --cache "$dev2"
|
||||||
# VG foo is incomplete
|
strace -e io_submit vgchange -aay --autoactivation event $vg1 2>&1|tee trace.out
|
||||||
|
test "$(grep io_submit trace.out | wc -l)" -eq 4
|
||||||
|
rm trace.out
|
||||||
|
|
||||||
|
strace -e io_submit pvscan --cache "$dev3" 2>&1|tee trace.out
|
||||||
|
test "$(grep io_submit trace.out | wc -l)" -eq 1
|
||||||
|
rm trace.out
|
||||||
|
|
||||||
|
strace -e io_submit vgchange -aay --autoactivation event $vg2 2>&1|tee trace.out
|
||||||
|
test "$(grep io_submit trace.out | wc -l)" -eq 2
|
||||||
|
rm trace.out
|
||||||
|
|
||||||
|
# non-standard usage: no VG name arg, vgchange will only used pvs_online files
|
||||||
|
|
||||||
|
vgchange -an
|
||||||
|
_clear_online_files
|
||||||
|
|
||||||
|
vgchange -aay --autoactivation event
|
||||||
check lv_field $vg1/$lv1 lv_active ""
|
check lv_field $vg1/$lv1 lv_active ""
|
||||||
|
check lv_field $vg1/$lv2 lv_active ""
|
||||||
|
check lv_field $vg2/$lv1 lv_active ""
|
||||||
|
|
||||||
|
pvscan --cache "$dev1"
|
||||||
|
vgchange -aay --autoactivation event
|
||||||
|
check lv_field $vg1/$lv1 lv_active ""
|
||||||
|
check lv_field $vg1/$lv2 lv_active ""
|
||||||
|
check lv_field $vg2/$lv1 lv_active ""
|
||||||
|
|
||||||
|
pvscan --cache "$dev2"
|
||||||
|
vgchange -aay --autoactivation event
|
||||||
|
check lv_field $vg1/$lv1 lv_active "active"
|
||||||
|
check lv_field $vg1/$lv2 lv_active "active"
|
||||||
|
check lv_field $vg2/$lv1 lv_active ""
|
||||||
|
|
||||||
|
pvscan --cache "$dev3"
|
||||||
|
vgchange -aay --autoactivation event
|
||||||
|
check lv_field $vg2/$lv1 lv_active "active"
|
||||||
|
|
||||||
|
# non-standard usage: include VG name arg, but missing or incomplete pvs_online files
|
||||||
|
|
||||||
|
vgchange -an
|
||||||
|
_clear_online_files
|
||||||
|
|
||||||
|
# all missing pvs_online, vgchange falls back to full label scan
|
||||||
|
vgchange -aay --autoactivation event $vg1
|
||||||
|
check lv_field $vg1/$lv1 lv_active "active"
|
||||||
|
check lv_field $vg1/$lv2 lv_active "active"
|
||||||
|
|
||||||
|
vgchange -an
|
||||||
|
_clear_online_files
|
||||||
|
|
||||||
|
# incomplete pvs_online, vgchange falls back to full label scan
|
||||||
|
pvscan --cache "$dev1"
|
||||||
|
vgchange -aay --autoactivation event $vg1
|
||||||
|
check lv_field $vg1/$lv1 lv_active "active"
|
||||||
|
check lv_field $vg1/$lv2 lv_active "active"
|
||||||
|
|
||||||
|
vgchange -an
|
||||||
|
_clear_online_files
|
||||||
|
|
||||||
|
# incomplete pvs_online, pvs_online from different vg,
|
||||||
|
# no pvs_online found for vg arg so vgchange falls back to full label scan
|
||||||
|
|
||||||
|
pvscan --cache "$dev3"
|
||||||
|
vgchange -aay --autoactivation event $vg1
|
||||||
|
check lv_field $vg1/$lv1 lv_active "active"
|
||||||
|
check lv_field $vg1/$lv2 lv_active "active"
|
||||||
|
check lv_field $vg2/$lv1 lv_active ""
|
||||||
|
|
||||||
|
vgchange -aay --autoactivation event $vg2
|
||||||
|
check lv_field $vg2/$lv1 lv_active "active"
|
||||||
|
|
||||||
|
vgchange -an
|
||||||
|
_clear_online_files
|
||||||
|
|
||||||
|
# same tests but using command options matching udev rule
|
||||||
|
|
||||||
|
pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$dev1"
|
||||||
|
pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$dev2"
|
||||||
|
vgchange -aay --autoactivation event $vg1
|
||||||
|
check lv_field $vg1/$lv1 lv_active "active"
|
||||||
|
check lv_field $vg1/$lv2 lv_active "active"
|
||||||
|
check lv_field $vg2/$lv1 lv_active ""
|
||||||
|
|
||||||
pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$dev3"
|
pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$dev3"
|
||||||
vgchange -aay --autoactivation event $vg2
|
vgchange -aay --autoactivation event $vg2
|
||||||
check lv_field $vg2/$lv1 lv_active "active"
|
check lv_field $vg2/$lv1 lv_active "active"
|
||||||
|
|
||||||
pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$dev2"
|
|
||||||
vgchange -aay --autoactivation event $vg1
|
|
||||||
check lv_field $vg1/$lv1 lv_active "active"
|
|
||||||
|
|
||||||
vgchange -an $vg1
|
vgchange -an $vg1
|
||||||
vgchange -an $vg2
|
vgchange -an $vg2
|
||||||
|
|
||||||
|
@ -879,7 +879,9 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arg_is_set(cmd, autoactivation_ARG)) {
|
if (arg_is_set(cmd, autoactivation_ARG)) {
|
||||||
|
int found_none = 0, found_all = 0, found_incomplete = 0;
|
||||||
int skip_command = 0;
|
int skip_command = 0;
|
||||||
|
|
||||||
if (!_check_autoactivation(cmd, &vp, &skip_command))
|
if (!_check_autoactivation(cmd, &vp, &skip_command))
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
if (skip_command)
|
if (skip_command)
|
||||||
@ -889,14 +891,49 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
* Special label scan optimized for autoactivation
|
* Special label scan optimized for autoactivation
|
||||||
* that is based on info read from /run/lvm/ files
|
* that is based on info read from /run/lvm/ files
|
||||||
* created by pvscan --cache during autoactivation.
|
* created by pvscan --cache during autoactivation.
|
||||||
* (Add an option to disable this optimization?)
|
* Add an option to disable this optimization? e.g.
|
||||||
|
* "online_skip" in --autoactivation / auto_activation_settings
|
||||||
|
*
|
||||||
|
* In some cases it might be useful to strictly follow
|
||||||
|
* the online files, and not fall back to a standard
|
||||||
|
* label scan when no pvs or incomplete pvs are found
|
||||||
|
* from the online files. Add option for that? e.g.
|
||||||
|
* "online_only" in --autoactivation / auto_activation_settings
|
||||||
|
*
|
||||||
|
* Generally the way that vgchange -aay --autoactivation event
|
||||||
|
* is currently used, it will not be called until pvscan --cache
|
||||||
|
* has found the VG is complete, so it will not generally be
|
||||||
|
* following the paths that fall back to standard label_scan.
|
||||||
|
*
|
||||||
|
* TODO: Like pvscan_aa_quick, this could do lock_vol(vgname)
|
||||||
|
* before label_scan_vg_online, then set cmd->can_use_one_scan=1
|
||||||
|
* to avoid rescanning in _vg_read called by process_each_vg.
|
||||||
*/
|
*/
|
||||||
get_single_vgname_cmd_arg(cmd, NULL, &vgname);
|
get_single_vgname_cmd_arg(cmd, NULL, &vgname);
|
||||||
if (vgname) {
|
if (!label_scan_vg_online(cmd, vgname, &found_none, &found_all, &found_incomplete)) {
|
||||||
if (!label_scan_vg_online(cmd, vgname))
|
log_print("PVs online error%s%s, using all devices.", vgname ? " for VG " : "", vgname ?: "");
|
||||||
log_debug("Standard label_scan required in place of online scan.");
|
} else {
|
||||||
else
|
if (!vgname) {
|
||||||
|
/* Not expected usage, activate any VGs that are complete based on pvs_online. */
|
||||||
flags |= PROCESS_SKIP_SCAN;
|
flags |= PROCESS_SKIP_SCAN;
|
||||||
|
} else if (found_all) {
|
||||||
|
/* The expected and optimal usage, only online PVs are read. */
|
||||||
|
flags |= PROCESS_SKIP_SCAN;
|
||||||
|
/*
|
||||||
|
} else if (online_only) {
|
||||||
|
log_print("PVs online %s.", found_none ? "not found" : "incomplete");
|
||||||
|
return vgname ? ECMD_FAILED : ECMD_PROCESSED;
|
||||||
|
*/
|
||||||
|
} else if (found_none) {
|
||||||
|
/* Not expected usage, use full label_scan in process_each */
|
||||||
|
log_print("PVs online not found for VG %s, using all devices.", vgname);
|
||||||
|
} else if (found_incomplete) {
|
||||||
|
/* Not expected usage, use full label_scan in process_each */
|
||||||
|
log_print("PVs online incomplete for VG %s, using all devicess.", vgname);
|
||||||
|
} else {
|
||||||
|
/* Shouldn't happen */
|
||||||
|
log_print("PVs online unknown for VG %s, using all devices.", vgname);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user