]> sourceware.org Git - lvm2.git/commitdiff
vgchange -aay: improve unexpected command variations
authorDavid Teigland <teigland@redhat.com>
Mon, 8 Nov 2021 17:30:25 +0000 (11:30 -0600)
committerDavid Teigland <teigland@redhat.com>
Mon, 8 Nov 2021 21:19:25 +0000 (15:19 -0600)
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.

lib/device/dev-cache.c
lib/device/online.c
lib/label/label.c
lib/label/label.h
test/shell/vgchange-pvs-online.sh
tools/vgchange.c

index e71cef38dd4fed958ecbb15d8fa7714f08665a40..525dae31e2dbced6dfc398a05a0e1375d3943937 100644 (file)
@@ -2164,7 +2164,7 @@ static char *_get_devname_from_devno(struct cmd_context *cmd, dev_t devno)
                }
 
                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 NULL;
index cd89d72e3d8f58342257ff994b8f416ccd584c40..58696871e4f97b38038b44409180bd8f074126f0 100644 (file)
@@ -134,8 +134,12 @@ int get_pvs_online(struct dm_list *pvs_online, const char *vgname)
 
                dm_list_add(pvs_online, &po->list);
        }
+
        if (closedir(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;
 }
 
@@ -355,6 +359,8 @@ int get_pvs_lookup(struct dm_list *pvs_online, const char *vgname)
                dm_list_add(pvs_online, &po->list);
        }
 
+       log_debug("PVs online lookup found %d for %s", dm_list_size(pvs_online), vgname);
+
        fclose(fp);
        return 1;
 
index 2f9b5c3712b17148ea3202dce70d24abbd9abd2c..9875b5f021c7bac5030dd6ccdb59aadf903790d3 100644 (file)
@@ -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,
- * to optimize device setup/scanning for a command that is run for a
- * specific vg name.  autoactivation happens during system startup
- * when the hints file is not useful, so this uses the online files as
- * an alternative.
- */ 
-
-int label_scan_vg_online(struct cmd_context *cmd, const char *vgname)
+ * to optimize device setup/scanning.  autoactivation happens during
+ * system startup when the hints file is not useful, but he pvs_online
+ * files can provide a similar optimization to the hints file.
+ */
+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 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(&devs);
 
+       log_debug_devs("Finding online devices to scan");
+
        /* reads devices file, does not populate dev-cache */
        if (!setup_devices_for_online_autoactivation(cmd))
                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
         * located on.
         */
-       if (!get_pvs_lookup(&pvs_online, vgname)) {
-               if (!get_pvs_online(&pvs_online, vgname))
+       if (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;
        }
 
+       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
         * 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);
 
-       if (dm_list_empty(&devs))
+       if (dm_list_empty(&devs)) {
+               *found_none = 1;
                return 1;
+       }
 
        /*
         * 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
         * gave fewer PVs than listed in VG metadata.
         */
-       metadata_pv_count = lvmcache_pvsummary_count(vgname);
-       if (metadata_pv_count != dm_list_size(&devs)) {
-               log_debug("Incorrect PV list from online files %d metadata %d.",
-                          dm_list_size(&devs), metadata_pv_count);
-               return 0;
+       if (vgname) {
+               metadata_pv_count = lvmcache_pvsummary_count(vgname);
+               if (metadata_pv_count > dm_list_size(&devs)) {
+                       log_debug("Incomplete PV list from online files %d metadata %d.",
+                                 dm_list_size(&devs), metadata_pv_count);
+                       *found_incomplete = 1;
+                       return 1;
+               }
        }
 
+       *found_all = 1;
        return 1;
 bad:
        free_po_list(&pvs_online);
index 55ebfde45eac29563595ff9d5622727b0728dc36..3cda1818cc027aba1f295a7a9b4d32d2fbc1b1a7 100644 (file)
@@ -118,7 +118,9 @@ int label_scan_open_excl(struct device *dev);
 int label_scan_open_rw(struct device *dev);
 int label_scan_reopen_rw(struct device *dev);
 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);
 
index bdc481ced2117d91973b36e27ee7a0a24a36f450..c2ebe73276f9c28bdf5964e1f4d88f40bb7ffbf3 100644 (file)
@@ -19,61 +19,135 @@ _clear_online_files() {
 
 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 $vg2 "$dev3"
 pvcreate "$dev4"
 
 lvcreate -l1 -n $lv1 -an $vg1
+lvcreate -l1 -n $lv2 -an $vg1
 lvcreate -l1 -n $lv1 -an $vg2
 
-# With no pv online files, vgchange that uses online files
-# will find no PVs to activate from.
+# Expected use, with vg name and all online files exist for vgchange.
 
 _clear_online_files
 
-not vgchange -aay --autoactivation event $vg1
-not vgchange -aay --autoactivation event $vg2
-vgchange -aay --autoactivation event
+pvscan --cache "$dev1"
+pvscan --cache "$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 "$dev3"
+vgchange -aay --autoactivation event $vg2
+check lv_field $vg2/$lv1 lv_active "active"
+
+# Count io to check the pvs_online optimization 
+# is working to limit scanning.
+
+vgchange -an
+_clear_online_files
+
+pvscan --cache "$dev1"
+pvscan --cache "$dev2"
+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/$lv2 lv_active ""
 check lv_field $vg2/$lv1 lv_active ""
 
-# incomplete vg will not be activated
-
 pvscan --cache "$dev1"
-vgchange -aay --autoactivation event $vg1
-# VG foo is incomplete
+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 ""
 
-# complete vg is activated
+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 $vg2
+vgchange -aay --autoactivation event
 check lv_field $vg2/$lv1 lv_active "active"
 
-pvscan --cache "$dev2"
+# 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 $vg1
-vgchange -an $vg2
+vgchange -an
+_clear_online_files
 
-# the same tests but using command options matching udev rule
+# 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
 
-pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$dev1"
+# 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
-# VG foo is incomplete
-check lv_field $vg1/$lv1 lv_active ""
+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"
 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"
+vgchange -aay --autoactivation event $vg2
+check lv_field $vg2/$lv1 lv_active "active"
 
 vgchange -an $vg1
 vgchange -an $vg2
index e20026e4df1d3cd365ca6ea10c7bea54c6fe7809..acdde97a8429c363e50cc69063fc93773a1742ed 100644 (file)
@@ -879,7 +879,9 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
        }
 
        if (arg_is_set(cmd, autoactivation_ARG)) {
+               int found_none = 0, found_all = 0, found_incomplete = 0;
                int skip_command = 0;
+
                if (!_check_autoactivation(cmd, &vp, &skip_command))
                        return ECMD_FAILED;
                if (skip_command)
@@ -889,14 +891,49 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
                 * Special label scan optimized for autoactivation
                 * that is based on info read from /run/lvm/ files
                 * 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);
-               if (vgname) {
-                       if (!label_scan_vg_online(cmd, vgname))
-                               log_debug("Standard label_scan required in place of online scan.");
-                       else
+               if (!label_scan_vg_online(cmd, vgname, &found_none, &found_all, &found_incomplete)) {
+                       log_print("PVs online error%s%s, using all devices.", vgname ? " for VG " : "", vgname ?: "");
+               } else {
+                       if (!vgname) {
+                               /* Not expected usage, activate any VGs that are complete based on pvs_online. */
+                               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);
+                       }
                }
        }
 
This page took 0.055376 seconds and 5 git commands to generate.