]> sourceware.org Git - lvm2.git/commitdiff
lvmdevices: new output and options for check and update 1059238271
authorDavid Teigland <teigland@redhat.com>
Fri, 27 Oct 2023 22:39:32 +0000 (17:39 -0500)
committerDavid Teigland <teigland@redhat.com>
Thu, 2 Nov 2023 16:46:31 +0000 (11:46 -0500)
- add new comparison between old and new entries, and use this
  as the basis for new dedicated output for check and update
- add new --refresh option to search for missing PVIDs on all
  devices, and possibly update the device ID
- internally, only use the term "refresh" for cases where a
  new device ID may be found and assigned for a missing PVID

lib/cache/lvmcache.c
lib/device/device_id.c
lib/device/device_id.h
test/shell/devicesfile-misc.sh
test/shell/devicesfile-realdevs.sh
tools/args.h
tools/command-lines.in
tools/lvmdevices.c

index abdfd136ac6f16c49625b0f30ac8251a3bed8db0..0cbe146c1556fa752a0e13264c33faa0e98ff8e0 100644 (file)
@@ -1643,7 +1643,7 @@ int lvmcache_label_scan(struct cmd_context *cmd)
         * need to be scanned to find the new device for the PVIDs.
         * device_ids_validate() will update the devices file to correct
         * some info, but to locate new devices for PVIDs, it defers
-        * to device_ids_refresh() which involves label scanning.
+        * to device_ids_search() which involves label scanning.
         *
         * device_ids_refresh_trigger is set by device_ids_read() when
         * it sees that the local machine doesn't match the machine
@@ -1652,17 +1652,17 @@ int lvmcache_label_scan(struct cmd_context *cmd)
         * This also means that all devs on the system need to be
         * scanned to find the new devices for the PVIDs.
         *
-        * When device_ids_refresh() locates the correct devices
+        * When device_ids_search() locates the correct devices
         * for the PVs in the devices file, it returns those new
         * devices in the refresh_devs list.  Those devs need to
         * be passed to label_scan to populate lvmcache info.
         */
        if (cmd->device_ids_invalid || cmd->device_ids_refresh_trigger) {
-               struct dm_list refresh_devs;
-               dm_list_init(&refresh_devs);
-               device_ids_refresh(cmd, &refresh_devs, NULL, 0, NULL);
-               if (!dm_list_empty(&refresh_devs))
-                       label_scan_devs(cmd, cmd->filter, &refresh_devs);
+               struct dm_list new_devs;
+               dm_list_init(&new_devs);
+               device_ids_search(cmd, &new_devs, 0, 0, NULL);
+               if (!dm_list_empty(&new_devs))
+                       label_scan_devs(cmd, cmd->filter, &new_devs);
        }
 
        /*
index 63c177a154417783524c8ec84263a85886926bb6..497aeb8f4b0349bad644b452c17a2b27ea4b1f58 100644 (file)
@@ -2277,7 +2277,7 @@ void device_ids_match(struct cmd_context *cmd)
        /*
         * Next match entries with IDTYPE=devname, which is only
         * based on matching devname, so somewhat likely to be wrong
-        * and need correcting in device_ids_validate/device_ids_refresh.
+        * and need correcting in device_ids_validate/device_ids_search.
         */
 
        dm_list_iterate_items(du, &cmd->use_devices) {
@@ -2386,7 +2386,7 @@ static void _get_devs_with_serial_numbers(struct cmd_context *cmd, struct dm_lis
                        }
                }
 
-               /* just copying the no-data filters in similar device_ids_refresh */
+               /* just copying the no-data filters in similar device_ids_search */
                if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "sysfs"))
                        continue;
                if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "type"))
@@ -2705,7 +2705,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
 
        /*
         * Each remaining du that's not matched to a dev (no du->dev set) is
-        * subject to device_ids_refresh which will look for unmatched pvids on
+        * subject to device_ids_search which will look for unmatched pvids on
         * devs that have not been scanned yet.
         */
        dm_list_iterate_items(du, &cmd->use_devices) {
@@ -2818,7 +2818,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
         * Set invalid if an entry using IDNAME=devname has not
         * been matched to a device.  It's possible that the device
         * with the PVID has a new name, different from the IDNAME
-        * value.  device_ids_refresh needs to search system devs
+        * value.  device_ids_search needs to search system devs
         * for the PVID.  The same applies when the IDNAME field
         * has no value.
         */
@@ -2851,7 +2851,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
        if (update_file && update_needed)
                *update_needed = 1;
 
-       /* FIXME: for wrong devname cases, wait to write new until device_ids_refresh? */
+       /* FIXME: for wrong devname cases, wait to write new until device_ids_search? */
 
        /*
         * try lock and device_ids_write(), the update is not required and will
@@ -3180,8 +3180,8 @@ void device_ids_check_serial(struct cmd_context *cmd, struct dm_list *scan_devs,
  * is using a non-system devices file?
  */
 
-void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
-                       int *search_count, int noupdate, int *update_needed)
+void device_ids_search(struct cmd_context *cmd, struct dm_list *new_devs,
+                      int all_ids, int noupdate, int *update_needed)
 {
        struct device *dev;
        struct dev_use *du;
@@ -3193,9 +3193,6 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
        struct dm_list search_list_devs ;        /* list of device_list */
        const char *devname;
        int update_file = 0;
-       int other_idtype = 0;
-       int other_pvid = 0;
-       int no_pvid = 0;
        int found = 0;
        int not_found = 0;
        int search_mode_none;
@@ -3208,7 +3205,24 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
        if (!cmd->enable_devices_file)
                return;
 
-       if (cmd->device_ids_refresh_trigger) {
+       /*
+        * When the product_uuid/hostname change (refresh_trigger is set), or
+        * when --refresh is included with lvmdevices --check|--update (all_ids
+        * is set), this function expands from correcting renamed IDTYPE=devname
+        * entries to looking for missing PVIDs with any IDTYPE, and assigning new
+        * IDTYPE/IDNAME values for a PVID entry if it's found elsewhere.
+        * (e.g. a PVID that has moved to a device with a new wwid.)  We require
+        * the --refresh option with update|check because otherwise a PVID may
+        * be picked up from an old cloned/snapshotted device, and lvm would
+        * begin using that old clone rather than the actual PV.
+        *
+        * Note: refresh_trigger=1 means that product_uuid/hostname has changed,
+        * which means that the devices file should be updated with that new
+        * value, even if no device ids need updates themselves.
+        * With --refresh (all_ids=1), an update may not be needed at all.
+        */
+
+       if (cmd->device_ids_refresh_trigger || all_ids) {
                search_mode_all = 1;
                search_mode_none = 0;
                search_mode_auto = 0;
@@ -3229,21 +3243,18 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
                        continue;
 
                /*
-                * When device_ids_refresh_trigger is set, it means
-                * that a PVID may be shifted to a new device even when
-                * the entry uses a stable id type, like wwid.
-                * Otherwise, we assume that only entries using the
-                * devname id type can move to new devices.
+                * When device_ids_refresh_trigger/all_ids is set, it means
+                * that a PVID may be relocated to a new device, even when the
+                * entry and/or device have a stable id type, like wwid.
+                * Ordinarily, we assume that only entries using the devname
+                * id type will need to be located on new devices.
                 */
-               if (!cmd->device_ids_refresh_trigger &&
+               if (!cmd->device_ids_refresh_trigger && !all_ids &&
                    (du->idtype != DEV_ID_TYPE_DEVNAME))
                        continue;
 
                log_debug("Search for PVID %s.", du->pvid);
 
-               if (search_count)
-                       (*search_count)++;
-
                if (search_mode_none)
                        continue;
 
@@ -3257,8 +3268,8 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
        if (dm_list_empty(&search_list_pvids) && !cmd->device_ids_refresh_trigger)
                return;
 
-       log_debug("device ids refresh search_pvids %d trigger %d search all %d auto %d none %d",
-                 dm_list_size(&search_list_pvids), cmd->device_ids_refresh_trigger,
+       log_debug("Search for PVIDs %d trigger %d all_ids %d search all %d auto %d none %d",
+                 dm_list_size(&search_list_pvids), cmd->device_ids_refresh_trigger, all_ids,
                  search_mode_all, search_mode_auto, search_mode_none);
 
        if (dm_list_empty(&search_list_pvids) && cmd->device_ids_refresh_trigger) {
@@ -3281,7 +3292,7 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
         * If hints are enabled, the hints invalidation could also remove the
         * searched file.
         */
-       if (!cmd->device_ids_refresh_trigger && _searched_devnames_exists(cmd)) {
+       if (!cmd->device_ids_refresh_trigger && !all_ids && _searched_devnames_exists(cmd)) {
                log_debug("Search for PVIDs skipped for %s", _searched_file);
                return;
        }
@@ -3333,12 +3344,12 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
                dev = devl->dev;
 
                /*
-                * We only need to check devs that would use ID_TYPE_DEVNAME
-                * themselves as alternatives to the missing ID_TYPE_DEVNAME
-                * entry. i.e. a ID_TYPE_DEVNAME entry would not appear on a
-                * device that has a wwid and would use ID_TYPE_SYS_WWID.  So,
-                * if a dev in the search_list_devs list has a proper/stable device
-                * id (e.g. wwid, serial, loop, mpath), then we don't need to
+                * As an optimization for locating new devs for IDTYPE=devname
+                * entries, we can just check devs that would also use
+                * ID_TYPE_DEVNAME themselves.  i.e. a ID_TYPE_DEVNAME entry
+                * would not appear on a device that has a wwid.  So, if a
+                * dev in search_list_devs has a proper/stable device id
+                * (e.g. wwid, serial, loop, mpath), then we don't need to
                 * read it to check for missing PVIDs.
                 * 
                 * search_for_devnames="all" means we should search every
@@ -3355,7 +3366,6 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
                 */
                if (search_mode_auto && _dev_has_stable_id(cmd, dev)) {
                        log_debug("Search for PVIDs skip %s (stable id)", dev_name(dev));
-                       other_idtype++;
                        continue;
                }
 
@@ -3368,15 +3378,11 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
                 * Sets has_pvid=1 if the dev has an lvm PVID.
                 * This loop may look at and skip many non-LVM devices.
                 */
-               if (!label_read_pvid(dev, &has_pvid)) {
-                       no_pvid++;
+               if (!label_read_pvid(dev, &has_pvid))
                        continue;
-               }
 
-               if (!has_pvid) {
-                       no_pvid++;
+               if (!has_pvid)
                        continue;
-               }
 
                /*
                 * These filters will use the block of data from bcache that
@@ -3407,19 +3413,15 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
                                        log_warn("WARNING: use lvmdevices to select a device for PVID %s.", dil->pvid);
                                        dm_list_del(&dil->list);
                                } else {
-                                       log_debug("Devices file PVID %s found on %s.", dil->pvid, dev_name(dev));
+                                       log_debug("Search for PVID %s found on %s.", dil->pvid, dev_name(dev));
                                        dil->dev = dev;
                                }
-                       } else {
-                               other_pvid++;
                        }
                }
          next:
                label_scan_invalidate(dev);
        }
 
-       log_debug("Search for PVIDs other_pvid %d no_pvid %d other_idtype %d.", other_pvid, no_pvid, other_idtype);
-
        /*
         * The use_devices entries (repesenting the devices file) are
         * updated for the new devices on which the PVs reside.  The new
@@ -3453,7 +3455,7 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
                new_idname2 = NULL;
                new_devname = NULL;
 
-               if (cmd->device_ids_refresh_trigger) {
+               if (cmd->device_ids_refresh_trigger || all_ids) {
                        if (!device_id_system_read_preferred(cmd, dev, &new_idtype, (const char **)&new_idname))
                                continue;
                        new_idname2 = strdup(new_idname);
@@ -3548,7 +3550,7 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
                if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
                        continue;
                devl->dev = dev;
-               dm_list_add(refresh_devs, &devl->list);
+               dm_list_add(new_devs, &devl->list);
        }
 
        /*
@@ -3556,7 +3558,7 @@ void device_ids_refresh(struct cmd_context *cmd, struct dm_list *refresh_devs,
         * pvids not found were from devices that are permanently detached.
         * If a new PV appears, pvscan will run and do unlink_searched_file.
         */
-       if (!cmd->device_ids_refresh_trigger && not_found && !found)
+       if (!cmd->device_ids_refresh_trigger && !all_ids && not_found && !found)
                _touch_searched_devnames(cmd);
 }
 
index 2dc7373cb967330cfd1880ae5368565f9883802c..2603ba0f01ca8d70937ff1d2c8003ed48dfb2a30 100644 (file)
@@ -37,8 +37,8 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
                        int noupdate, int *update_needed);
 void device_ids_check_serial(struct cmd_context *cmd, struct dm_list *scan_devs,
                        int noupdate, int *update_needed);
-void device_ids_refresh(struct cmd_context *cmd, struct dm_list *dev_list, int *search_count,
-                       int noupdate, int *update_needed);
+void device_ids_search(struct cmd_context *cmd, struct dm_list *new_devs,
+                      int all_ids, int noupdate, int *update_needed);
 const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype);
 void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg, struct id *old_vg_id);
 int device_ids_version_unchanged(struct cmd_context *cmd);
index 3116fb90d6cc2e50549425003528abe416ec5862..109209f13d5b9816d2daf9ab9cb719775fa54813 100644 (file)
@@ -222,6 +222,227 @@ not grep "$WWID1" out
 grep "IDNAME=$dev3" out
 grep "DEVNAME=$dev3" out
 
+#
+# lvmdevices --check|--update
+#
+
+DEVNAME_NONE=/dev/sdxyz
+PVID_NONE=aaaaaa
+WWID_NONE=naa.56789
+
+rm $DF
+lvmdevices --adddev "$dev1"
+lvmdevices --adddev "$dev2"
+lvmdevices --adddev "$dev3"
+lvmdevices --adddev "$dev4"
+cat $DF
+cp "$DF" orig
+
+# 1. lvmdevices --check|--update : devs with wwid
+# 1.a change pvid and devname
+sed -e "s|DEVNAME=$dev1|DEVNAME=$DEVNAME_NONE|" orig > tmp1
+sed -e "s|PVID=$PVID1|PVID=$PVID_NONE|" tmp1 > "$DF"
+cat "$DF"
+not lvmdevices --check |tee out
+grep PVID=$PVID1 out
+grep DEVNAME=$dev1 out
+grep "old $DEVNAME_NONE" out
+grep "old $PVID_NONE" out
+lvmdevices --update
+grep PVID=$PVID1 "$DF" |tee out
+grep DEVNAME=$dev1 out
+lvmdevices --check
+
+# 1.b change devname
+sed -e "s|DEVNAME=$dev1|DEVNAME=$DEVNAME_NONE|" orig > "$DF"
+cat "$DF"
+not lvmdevices --check |tee out
+grep PVID=$PVID1 out
+grep DEVNAME=$dev1 out
+grep "old $DEVNAME_NONE" out
+lvmdevices --update
+grep PVID=$PVID1 "$DF" |tee out
+grep DEVNAME=$dev1 out
+lvmdevices --check
+
+# 1.c change pvid
+sed -e "s|PVID=$PVID1|PVID=$PVID_NONE|" orig > "$DF"
+cat "$DF"
+not lvmdevices --check |tee out
+grep PVID=$PVID1 out
+grep DEVNAME=$dev1 out
+grep "old $PVID_NONE" out
+lvmdevices --update
+grep PVID=$PVID1 "$DF" |tee out
+grep DEVNAME=$dev1 out
+lvmdevices --check
+
+# 2. lvmdevices --check|--update : devs with only devname
+# 2.a change idname and devname
+sed -e "s|IDNAME=$dev3|IDNAME=$DEVNAME_NONE|" orig > tmp1
+sed -e "s|DEVNAME=$dev3|DEVNAME=$DEVNAME_NONE|" tmp1 > "$DF"
+cat "$DF"
+not lvmdevices --check |tee out
+grep PVID=$PVID3 out |tee out1
+grep IDNAME=$dev3 out1
+grep DEVNAME=$dev3 out1
+grep "old $DEVNAME_NONE" out1
+lvmdevices --update
+grep PVID=$PVID3 "$DF" |tee out
+grep IDNAME=$dev3 out
+grep DEVNAME=$dev3 out
+lvmdevices --check
+
+# 2.b change devname
+sed -e "s|DEVNAME=$dev3|DEVNAME=$DEVNAME_NONE|" orig > "$DF"
+cat "$DF"
+not lvmdevices --check |tee out
+grep PVID=$PVID3 out |tee out1
+grep IDNAME=$dev3 out1
+grep DEVNAME=$dev3 out1
+grep "old $DEVNAME_NONE" out1
+lvmdevices --update
+grep PVID=$PVID3 "$DF" |tee out
+grep IDNAME=$dev3 out
+grep DEVNAME=$dev3 out
+lvmdevices --check
+
+# 2.c change idname
+sed -e "s|IDNAME=$dev3|IDNAME=$DEVNAME_NONE|" orig > "$DF"
+cat "$DF"
+not lvmdevices --check |tee out
+grep PVID=$PVID3 out |tee out1
+grep IDNAME=$dev3 out1
+grep DEVNAME=$dev3 out1
+grep "old $DEVNAME_NONE" out1
+lvmdevices --update
+grep PVID=$PVID3 "$DF" |tee out
+grep IDNAME=$dev3 out
+grep DEVNAME=$dev3 out
+lvmdevices --check
+
+# 3. lvmdevices --check|--update --refresh devs with IDTYPE=sys_wwid
+# 3.a.i change idtype and idname and devname (wwid to serial)
+sed -e "s|DEVNAME=$dev1|DEVNAME=$DEVNAME_NONE|" orig > tmp1
+sed -e "s|IDTYPE=sys_wwid IDNAME=$WWID1|IDTYPE=sys_serial IDNAME=S123|" tmp1 > "$DF"
+cat "$DF"
+# this command succeeds since no update is detected, the dev is simply not found
+lvmdevices --check |tee out
+grep 'device not found' out
+not lvmdevices --check --refresh |tee out
+grep PVID=$PVID1 out |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+grep "old sys_serial" out1
+grep "old S123" out1
+lvmdevices --update --refresh
+grep PVID=$PVID1 "$DF" |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+lvmdevices --check
+
+# 3.a.ii change idtype and idname and devname (wwid to devname)
+sed -e "s|DEVNAME=$dev1|DEVNAME=$DEVNAME_NONE|" orig > tmp1
+sed -e "s|IDTYPE=sys_wwid IDNAME=$WWID1|IDTYPE=devname IDNAME=$DEVNAME_NONE|" tmp1 > "$DF"
+cat "$DF"
+# the command without --refresh thinks the update should be just to the devname
+not lvmdevices --check |tee out
+grep PVID=$PVID1 out | tee out1
+grep DEVNAME=$dev1 out1
+grep IDNAME=$dev1 out1
+grep IDTYPE=devname out1
+# the command with --refresh sees the update should use sys_wwid
+not lvmdevices --check --refresh |tee out
+grep PVID=$PVID1 out | tee out1
+grep DEVNAME=$dev1 out1
+grep IDNAME=$WWID1 out1
+grep IDTYPE=sys_wwid out1
+lvmdevices --update --refresh
+grep PVID=$PVID1 "$DF" |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+lvmdevices --check
+
+# 3.b change idtype and idname
+sed -e "s|IDTYPE=sys_wwid IDNAME=$WWID1|IDTYPE=sys_serial IDNAME=S123|" orig > "$DF"
+cat "$DF"
+# this command succeeds since no update is detected, the dev is simply not found
+lvmdevices --check |tee out
+grep 'device not found' out
+not lvmdevices --check --refresh |tee out
+grep PVID=$PVID1 out |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+grep "old sys_serial" out1
+grep "old S123" out1
+lvmdevices --update --refresh
+grep PVID=$PVID1 "$DF" |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+lvmdevices --check
+
+# 3.c change idname and devname
+sed -e "s|DEVNAME=$dev1|DEVNAME=$DEVNAME_NONE|" orig > tmp1
+sed -e "s|IDNAME=$WWID1|IDNAME=$WWID_NONE|" tmp1 > "$DF"
+cat "$DF"
+# this command succeeds since no update is detected, the dev is simply not found
+lvmdevices --check |tee out
+grep 'device not found' out
+not lvmdevices --check --refresh |tee out
+grep PVID=$PVID1 out |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+grep "old $WWID_NONE" out1
+lvmdevices --update --refresh
+grep PVID=$PVID1 "$DF" |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+lvmdevices --check
+
+# 3.d change idname
+sed -e "s|IDNAME=$WWID1|IDNAME=$WWID_NONE|" orig > "$DF"
+cat "$DF"
+# this command succeeds since no update is detected, the dev is simply not found
+lvmdevices --check |tee out
+grep 'device not found' out
+not lvmdevices --check --refresh |tee out
+grep PVID=$PVID1 out |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+grep "old $WWID_NONE" out1
+lvmdevices --update --refresh
+grep PVID=$PVID1 "$DF" |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+lvmdevices --check
+
+# 3.e change devname
+sed -e "s|DEVNAME=$dev1|DEVNAME=$DEVNAME_NONE|" orig > "$DF"
+cat "$DF"
+not lvmdevices --check |tee out
+grep PVID=$PVID1 out |tee out1
+grep DEVNAME=$dev1 out1
+grep "old $DEVNAME_NONE" out1
+not lvmdevices --check --refresh |tee out
+grep PVID=$PVID1 out |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+lvmdevices --update --refresh
+grep PVID=$PVID1 "$DF" |tee out1
+grep DEVNAME=$dev1 out1
+grep IDTYPE=sys_wwid out1
+grep IDNAME=$WWID1 out1
+lvmdevices --check
 
 vgchange -an $vg1
 lvremove -y $vg1
index 7874a6d0c078edbe09df22a3ae2d8a0bac5e00af..c7403a3545afa654e92fd910a0b74f02bebfbf27 100644 (file)
@@ -466,11 +466,10 @@ grep $did1 $DF
 rm $DF
 sed "s/$did1/baddid/" "$DF.orig" |tee $DF
 
-# FIXME: lvmdevices --check needs fixed output
-#lvmdevices --check 2>&1|tee out
-#grep $dev1 out
-#grep baddid out
-#not grep $dev2 out
+lvmdevices --check 2>&1|tee out
+grep $dev1 out
+grep baddid out
+not grep $dev2 out
 
 lvmdevices 2>&1|tee out
 grep $pvid1 out
@@ -499,8 +498,7 @@ d1=$(basename $dev1)
 d3=$(basename $dev3)
 sed "s/$d1/$d3/" "$DF.orig" |tee $DF
 not lvmdevices --check 2>&1 |tee out
-# FIXME: define fixed check output
-#grep $dev1 out
+grep $dev1 out
 
 lvmdevices --update
 
@@ -522,9 +520,8 @@ sed "s/$d2/$d1/" "${DF}_1" |tee ${DF}_2
 sed "s/tmp/$d2/" "${DF}_2" |tee $DF
 rm ${DF}_1 ${DF}_2
 not lvmdevices --check 2>&1 |tee out
-# FIXME: define fixed check output
-#grep $dev1 out
-#grep $dev2 out
+grep $dev1 out
+grep $dev2 out
 
 lvmdevices --update
 
@@ -544,8 +541,7 @@ d1=$(basename $dev1)
 d3=$(basename $dev3)
 sed "s/$d1/$d3/" "$DF.orig" |tee $DF
 not lvmdevices --check 2>&1 |tee out
-# FIXME: define fixed check output
-#grep $dev1 out
+grep $dev1 out
 
 pvs -o+uuid,deviceid | grep $vg |tee out
 grep $dev1 out |tee out1
index bbb1f4744e87bb1c4f2c555165e73245f2473054..35dfcfd3b890faedc6695ea524b21906f190d413 100644 (file)
@@ -668,6 +668,19 @@ arg(readonly_ARG, '\0', "readonly", 0, 0, 0,
     "or not LVs are actually in use.\n")
 
 arg(refresh_ARG, '\0', "refresh", 0, 0, 0,
+    "#lvmdevices\n"
+    "Search for missing PVs on new devices, and update the devices file\n"
+    "with new device IDs for the PVs if they are found on new devices.\n"
+    "This is useful if PVs have been moved to new devices with new WWIDs,\n"
+    "for example. The device ID type and name may both change for a PV.\n"
+    "WARNING: if a PV is detached from the system, but a device containing a\n"
+    "clone or snapshot of that PV is present, then refresh would replace the\n"
+    "correct device ID with the clone/snapshot device ID, and lvm would begin\n"
+    "using the wrong device for the PV. Use deldev/adddev to safely change\n"
+    "a PV device ID in this scenario.\n"
+    "#vgchange\n"
+    "#lvchange\n"
+    "#vgmknodes\n"
     "If the LV is active, reload its metadata.\n"
     "This is not necessary in normal operation, but may be useful\n"
     "if something has gone wrong, or if some form of manual LV\n"
index f093b895e8740485da4804ece653a501c31f1995..633ea2090f22958061ce64398b2946eaf43c0ba1 100644 (file)
@@ -1448,10 +1448,11 @@ DESC: Print devices in the devices file.
 
 lvmdevices --check
 ID: lvmdevices_check
+OO: --refresh
 DESC: Check the devices file and report incorrect values.
 
 lvmdevices --update
-OO: --delnotfound
+OO: --delnotfound, --refresh
 ID: lvmdevices_update
 DESC: Update the devices file to fix incorrect values.
 
index c3380c78c9657db34378ee7a442cf706280c6afc..7a1ccac3dd6f595129bf31808397f5994e462d85 100644 (file)
@@ -120,6 +120,361 @@ static void _search_devs_for_pvids(struct cmd_context *cmd, struct dm_list *sear
        }
 }
 
+static char *_part_str(struct dev_use *du)
+{
+       static char _part_str_buf[64];
+
+       if (du->part)
+               snprintf(_part_str_buf, 63, " PART=%d", du->part);
+       else
+               _part_str_buf[0] = '\0';
+
+       return _part_str_buf;
+}
+
+static void _print_check(struct cmd_context *cmd)
+{
+       struct dm_list use_old;
+       struct dm_list use_new;
+       struct dm_list done_old;
+       struct dm_list done_new;
+       struct dev_use *du_old, *du_new;
+       int pvid_same;
+       int idname_same;
+       int idtype_same;
+       int devname_same;
+       char *part;
+
+       dm_list_init(&use_old);
+       dm_list_init(&use_new);
+       dm_list_init(&done_old);
+       dm_list_init(&done_new);
+
+       dm_list_splice(&use_new, &cmd->use_devices);
+       device_ids_read(cmd);
+       dm_list_splice(&use_old, &cmd->use_devices);
+       dm_list_init(&cmd->use_devices);
+
+       /*
+        * Check entries with proper id types.
+        */
+restart1:
+       dm_list_iterate_items(du_old, &use_old) {
+               if (du_old->idtype == DEV_ID_TYPE_DEVNAME)
+                       continue;
+               dm_list_iterate_items(du_new, &use_new) {
+                       if (du_new->idtype == DEV_ID_TYPE_DEVNAME)
+                               continue;
+
+                       if (du_old->idtype != du_new->idtype)
+                               continue;
+
+                       if (!du_old->idname || !du_new->idname)
+                               continue;
+
+                       if (du_old->part != du_new->part)
+                               continue;
+
+                       if (!strcmp(du_old->idname, du_new->idname)) {
+                               part = _part_str(du_old);
+
+                               /*
+                                * Old and new entries match based on device id.
+                                * Possible differences between old and new:
+                                * DEVNAME mismatch can be common.
+                                * PVID mismatch is not common, but can
+                                * happen from something like dd of one
+                                * PV to another.
+                                */
+
+                               if (!du_new->dev) {
+                                       /* We can't know the new pvid and devname without a device. */
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: device not found",
+                                               idtype_to_str(du_old->idtype),
+                                               du_old->idname,
+                                               du_old->devname ?: "none",
+                                               du_old->pvid ?: "none",
+                                               part);
+                                       goto next1;
+                               }
+
+                               pvid_same = (du_old->pvid && du_new->pvid && !strcmp(du_old->pvid, du_new->pvid));
+                               devname_same = (du_old->devname && du_new->devname && !strcmp(du_old->devname, du_new->devname));
+
+                               if (pvid_same && devname_same) {
+                                       log_verbose("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: no change",
+                                                   idtype_to_str(du_new->idtype),
+                                                   du_new->idname,
+                                                   du_new->devname ?: "none",
+                                                   du_new->pvid ?: "none",
+                                                   part);
+
+                               } else if (!pvid_same && !devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s (old %s) PVID=%s (old %s)%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               du_new->idname,
+                                               du_new->devname ?: "none",
+                                               du_old->devname ?: "none",
+                                               du_new->pvid ?: "none",
+                                               du_old->pvid ?: "none",
+                                               part);
+
+                               } else if (pvid_same && !devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s (old %s) PVID=%s%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               du_new->idname,
+                                               du_new->devname ?: "none",
+                                               du_old->devname ?: "none",
+                                               du_new->pvid ?: "none",
+                                               part);
+
+                               } else if (!pvid_same && devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s (old %s)%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               du_new->idname,
+                                               du_new->devname ?: "none",
+                                               du_new->pvid ?: "none",
+                                               du_old->pvid ?: "none",
+                                               part);
+                               }
+                       next1:
+                               dm_list_del(&du_old->list);
+                               dm_list_del(&du_new->list);
+                               dm_list_add(&done_old, &du_old->list);
+                               dm_list_add(&done_new, &du_new->list);
+                               goto restart1;
+                       }
+               }
+       }
+
+       /*
+        * Check entries with devname id type.
+        */
+restart2:
+       dm_list_iterate_items(du_old, &use_old) {
+               if (du_old->idtype != DEV_ID_TYPE_DEVNAME)
+                       continue;
+               dm_list_iterate_items(du_new, &use_new) {
+                       if (du_new->idtype != DEV_ID_TYPE_DEVNAME)
+                               continue;
+
+                       if (!du_old->pvid || !du_new->pvid)
+                               continue;
+
+                       if (du_old->part != du_new->part)
+                               continue;
+
+                       if (!memcmp(du_old->pvid, du_new->pvid, strlen(du_old->pvid))) {
+                               part = _part_str(du_old);
+
+                               /*
+                                * Old and new entries match based on PVID.
+                                * IDNAME and DEVNAME might not match.
+                                */
+
+                               if (!du_new->dev) {
+                                       /* We can't know the new idname and devname without a device. */
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: device not found",
+                                               idtype_to_str(du_old->idtype),
+                                               du_old->idname ?: "none",
+                                               du_old->devname ?: "none",
+                                               du_old->pvid,
+                                               part);
+                                       goto next2;
+                               }
+
+                               idname_same = (du_old->idname && du_new->idname && !strcmp(du_old->idname, du_new->idname));
+                               devname_same = (du_old->devname && du_new->devname && !strcmp(du_old->devname, du_new->devname));
+
+                               if (idname_same && devname_same) {
+                                       log_verbose("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: no change",
+                                                   idtype_to_str(du_new->idtype),
+                                                   du_new->idname ?: "none",
+                                                   du_new->devname ?: "none",
+                                                   du_new->pvid,
+                                                   part);
+
+                               } else if (!idname_same && !devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s (old %s) DEVNAME=%s (old %s) PVID=%s%s: update",
+                                                   idtype_to_str(du_new->idtype),
+                                                   du_new->idname ?: "none",
+                                                   du_old->idname ?: "none",
+                                                   du_new->devname ?: "none",
+                                                   du_old->devname ?: "none",
+                                                   du_new->pvid,
+                                                   part);
+
+                               } else if (idname_same && !devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s (old %s) PVID=%s%s: update",
+                                                   idtype_to_str(du_new->idtype),
+                                                   du_new->idname ?: "none",
+                                                   du_new->devname ?: "none",
+                                                   du_old->devname ?: "none",
+                                                   du_new->pvid,
+                                                   part);
+
+                               } else if (!idname_same && devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s (old %s) DEVNAME=%s PVID=%s%s: update",
+                                                   idtype_to_str(du_new->idtype),
+                                                   du_new->idname ?: "none",
+                                                   du_old->idname ?: "none",
+                                                   du_new->devname ?: "none",
+                                                   du_new->pvid,
+                                                   part);
+                               }
+                       next2:
+                               dm_list_del(&du_old->list);
+                               dm_list_del(&du_new->list);
+                               dm_list_add(&done_old, &du_old->list);
+                               dm_list_add(&done_new, &du_new->list);
+                               goto restart2;
+                       }
+               }
+       }
+
+       /*
+        * Check entries with new IDTYPE (refresh can do this)
+        * Compare PVIDs.
+        */
+restart3:
+       dm_list_iterate_items(du_old, &use_old) {
+               dm_list_iterate_items(du_new, &use_new) {
+
+                       if (!du_old->pvid || !du_new->pvid)
+                               continue;
+
+                       if (du_old->part != du_new->part)
+                               continue;
+
+                       if (!memcmp(du_old->pvid, du_new->pvid, strlen(du_old->pvid))) {
+                               part = _part_str(du_old);
+
+                               /*
+                                * Old and new entries match based on PVID.
+                                * IDTYPE, IDNAME, DEVNAME might not match.
+                                */
+
+                               if (!du_new->dev) {
+                                       /* could this happen? */
+                                       log_print_unless_silent("IDTYPE=%s (%s) IDNAME=%s (%s) DEVNAME=%s (%s) PVID=%s%s: device not found",
+                                               idtype_to_str(du_new->idtype),
+                                               idtype_to_str(du_old->idtype),
+                                               du_new->idname ?: "none",
+                                               du_old->idname ?: "none",
+                                               du_new->devname ?: "none",
+                                               du_old->devname ?: "none",
+                                               du_new->pvid,
+                                               part);
+                                       goto next3;
+                               }
+
+                               idtype_same = (du_old->idtype == du_new->idtype);
+                               idname_same = (du_old->idname && du_new->idname && !strcmp(du_old->idname, du_new->idname));
+                               devname_same = (du_old->devname && du_new->devname && !strcmp(du_old->devname, du_new->devname));
+
+                               if (idtype_same && idname_same && devname_same) {
+                                       /* this case will probably be caught earlier */
+                                       log_verbose("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: no change",
+                                                   idtype_to_str(du_new->idtype),
+                                                   du_new->idname ?: "none",
+                                                   du_new->devname ?: "none",
+                                                   du_new->pvid,
+                                                   part);
+
+                               } else if (!idtype_same && !idname_same && !devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s (old %s) IDNAME=%s (old %s) DEVNAME=%s (old %s) PVID=%s%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               idtype_to_str(du_old->idtype),
+                                               du_new->idname ?: "none",
+                                               du_old->idname ?: "none",
+                                               du_new->devname ?: "none",
+                                               du_old->devname ?: "none",
+                                               du_new->pvid,
+                                               part);
+
+                               } else if (!idtype_same && !idname_same && devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s (old %s) IDNAME=%s (old %s) DEVNAME=%s PVID=%s%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               idtype_to_str(du_old->idtype),
+                                               du_new->idname ?: "none",
+                                               du_old->idname ?: "none",
+                                               du_new->devname ?: "none",
+                                               du_new->pvid,
+                                               part);
+
+                               } else if (idtype_same && !idname_same && !devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s (old %s) DEVNAME=%s (old %s) PVID=%s%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               du_new->idname ?: "none",
+                                               du_old->idname ?: "none",
+                                               du_new->devname ?: "none",
+                                               du_old->devname ?: "none",
+                                               du_new->pvid,
+                                               part);
+
+                               } else if (idtype_same && !idname_same && devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s (old %s) DEVNAME=%s PVID=%s%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               du_new->idname ?: "none",
+                                               du_old->idname ?: "none",
+                                               du_new->devname ?: "none",
+                                               du_new->pvid,
+                                               part);
+
+                               } else if (idtype_same && idname_same && !devname_same) {
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s (old %s) PVID=%s%s: update",
+                                               idtype_to_str(du_new->idtype),
+                                               du_new->idname ?: "none",
+                                               du_new->devname ?: "none",
+                                               du_old->devname ?: "none",
+                                               du_new->pvid,
+                                               part);
+                               }
+                       next3:
+                               dm_list_del(&du_old->list);
+                               dm_list_del(&du_new->list);
+                               dm_list_add(&done_old, &du_old->list);
+                               dm_list_add(&done_new, &du_new->list);
+                               goto restart3;
+                       }
+               }
+       }
+
+       /*
+        * Entries remaining on old/new lists can't be directly
+        * correlated by loops above, to print field-specific
+        * changes.  So, just print remaining old entries as
+        * being removed and remaing new entries as being added.
+        */
+
+       dm_list_iterate_items(du_old, &use_old) {
+               part = _part_str(du_old);
+
+               log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: old entry",
+                       idtype_to_str(du_old->idtype),
+                       du_old->idname ?: "none",
+                       du_old->devname ?: "none",
+                       du_old->pvid,
+                       part);
+       }
+
+       dm_list_iterate_items(du_new, &use_new) {
+               part = _part_str(du_new);
+
+               log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: new entry",
+                       idtype_to_str(du_new->idtype),
+                       du_new->idname ?: "none",
+                       du_new->devname ?: "none",
+                       du_new->pvid,
+                       part);
+       }
+
+       /* Restore cmd->use_devices list */
+
+       dm_list_splice(&cmd->use_devices, &use_new);
+       dm_list_splice(&cmd->use_devices, &done_new);
+}
+
 int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
 {
        struct dm_list search_pvids;
@@ -186,7 +541,6 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
 
        if (arg_is_set(cmd, check_ARG) || arg_is_set(cmd, update_ARG)) {
                int update_set = arg_is_set(cmd, update_ARG);
-               int search_count = 0;
                int update_needed = 0;
 
                unlink_searched_devnames(cmd);
@@ -248,11 +602,17 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
                        if (!dev_is_mpath_component(cmd, dev, &mpath_devno))
                                continue;
 
+                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: remove multipath component",
+                                       idtype_to_str(du->idtype),
+                                       du->idname ?: "none",
+                                       du->devname ?: "none",
+                                       du->pvid ?: "none",
+                                       _part_str(du));
+
                        update_needed = 1;
-                       if (update_set) {
-                               log_print("Removing multipath component %s.", dev_name(du->dev));
+
+                       if (update_set)
                                dm_list_del(&du->list);
-                       }
 
                        if (!(mpath_dev = dev_cache_get_by_devt(cmd, mpath_devno)))
                                continue;
@@ -264,8 +624,8 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
                                        if (!device_id_add(cmd, mpath_dev, dev->pvid, NULL, NULL, 0))
                                                stack;
                                } else {
-                                       log_print("Missing multipath device %s for multipath component %s.",
-                                                 dev_name(mpath_dev), dev_name(du->dev));
+                                       log_print_unless_silent("Missing multipath device %s for multipath component %s.",
+                                               dev_name(mpath_dev), dev_name(du->dev));
                                }
                        }
                }
@@ -276,10 +636,15 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
                }
 
                /*
-                * Find and fix any devname entries that have moved to a
-                * renamed device.
+                * Find devname entries that have moved to a renamed device.
+                * If --refresh is set, then also look for missing PVIDs on
+                * devices with new device ids of any type, e.g. a PVID that's
+                * moved to a new WWID.
                 */
-               device_ids_refresh(cmd, &found_devs, &search_count, 1, &update_needed);
+               cmd->search_for_devnames = "all";
+               device_ids_search(cmd, &found_devs, arg_is_set(cmd, refresh_ARG), 1, &update_needed);
+
+               _print_check(cmd);
 
                dm_list_iterate_items(du, &cmd->use_devices) {
                        if (du->dev)
@@ -289,11 +654,15 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
                if (arg_is_set(cmd, delnotfound_ARG)) {
                        dm_list_iterate_items_safe(du, du2, &cmd->use_devices) {
                                if (!du->dev) {
-                                       log_print("Deleting IDTYPE=%s IDNAME=%s PVID=%s",
-                                                 idtype_to_str(du->idtype), du->idname ?: ".", du->pvid ?: ".");
+                                       log_print_unless_silent("IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s: delete",
+                                               idtype_to_str(du->idtype),
+                                               du->idname ?: "none",
+                                               du->devname ?: "none",
+                                               du->pvid ?: "none",
+                                               _part_str(du));
                                        dm_list_del(&du->list);
                                        free_du(du);
-                                       update_needed++;
+                                       update_needed = 1;
                                }
                        }
                }
@@ -553,18 +922,13 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
        /* If no options, print use_devices list */
 
        dm_list_iterate_items(du, &cmd->use_devices) {
-               char part_buf[64] = { 0 };
-
-               if (du->part)
-                       snprintf(part_buf, 63, " PART=%d", du->part);
-
                log_print("Device %s IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s",
                          du->dev ? dev_name(du->dev) : "none",
                          du->idtype ? idtype_to_str(du->idtype) : "none",
                          du->idname ? du->idname : "none",
                          du->devname ? du->devname : "none",
                          du->pvid ? (char *)du->pvid : "none",
-                         part_buf);
+                         _part_str(du));
        }
 
 out:
This page took 0.070298 seconds and 5 git commands to generate.