Blame SOURCES/0032-devices-file-do-not-clear-PVID-of-unread-devices.patch

4d51e5
From 08a5619a1d7a5a8dd6e0df6e4dedec47ce2533b7 Mon Sep 17 00:00:00 2001
4d51e5
From: David Teigland <teigland@redhat.com>
4d51e5
Date: Thu, 10 Feb 2022 14:00:25 -0600
4d51e5
Subject: [PATCH 32/54] devices file: do not clear PVID of unread devices
4d51e5
4d51e5
In a certain disconnected state, a block device is present on
4d51e5
the system, can be opened, reports a valid size, reports the
4d51e5
correct device id (wwid), and matches a devices file entry.
4d51e5
But, reading the device can still fail.  In this case,
4d51e5
device_ids_validate() was misinterpreting the read error as
4d51e5
the device having no data/label on it (and no PVID).
4d51e5
The validate function would then clear the PVID from the
4d51e5
devices file entry for the device, thinking that it was
4d51e5
fixing the devices file (making it consistent with the on disk
4d51e5
state.)  Fix this by not attempting to check and correct a
4d51e5
devices file entry that cannot be read.  Also make this case
4d51e5
explicit in the hints validation code (which was doing the
4d51e5
right thing but indirectly.)
4d51e5
---
4d51e5
 lib/device/device.h    |  1 +
4d51e5
 lib/device/device_id.c | 14 ++++++++++++++
4d51e5
 lib/label/hints.c      | 14 ++++++++++++++
4d51e5
 lib/label/label.c      |  8 ++++++++
4d51e5
 4 files changed, 37 insertions(+)
4d51e5
4d51e5
diff --git a/lib/device/device.h b/lib/device/device.h
4d51e5
index 9e471a9b5..8c3a8c30e 100644
4d51e5
--- a/lib/device/device.h
4d51e5
+++ b/lib/device/device.h
4d51e5
@@ -40,6 +40,7 @@
4d51e5
 #define DEV_IS_NVME		0x00040000	/* set if dev is nvme */
4d51e5
 #define DEV_MATCHED_USE_ID	0x00080000	/* matched an entry from cmd->use_devices */
4d51e5
 #define DEV_SCAN_FOUND_NOLABEL	0x00100000	/* label_scan read, passed filters, but no lvm label */
4d51e5
+#define DEV_SCAN_NOT_READ	0x00200000	/* label_scan not able to read dev */
4d51e5
 
4d51e5
 /*
4d51e5
  * Support for external device info.
4d51e5
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
4d51e5
index aeaa1ffc6..7fe581571 100644
4d51e5
--- a/lib/device/device_id.c
4d51e5
+++ b/lib/device/device_id.c
4d51e5
@@ -1724,6 +1724,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
4d51e5
 		if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
4d51e5
 			continue;
4d51e5
 
4d51e5
+		/*
4d51e5
+		 * The matched device could not be read so we do not have
4d51e5
+		 * the PVID from disk and cannot verify the devices file entry.
4d51e5
+		 */
4d51e5
+		if (dev->flags & DEV_SCAN_NOT_READ)
4d51e5
+			continue;
4d51e5
+
4d51e5
 		/*
4d51e5
 		 * du and dev may have been matched, but the dev could still
4d51e5
 		 * have been excluded by other filters during label scan.
4d51e5
@@ -1806,6 +1813,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
4d51e5
 		if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
4d51e5
 			continue;
4d51e5
 
4d51e5
+		/*
4d51e5
+		 * The matched device could not be read so we do not have
4d51e5
+		 * the PVID from disk and cannot verify the devices file entry.
4d51e5
+		 */
4d51e5
+		if (dev->flags & DEV_SCAN_NOT_READ)
4d51e5
+			continue;
4d51e5
+
4d51e5
 		if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
4d51e5
 			log_warn("Devices file %s is excluded by filter: %s.",
4d51e5
 				 dev_name(dev), dev_filtered_reason(dev));
4d51e5
diff --git a/lib/label/hints.c b/lib/label/hints.c
4d51e5
index 3ce9634f2..95d5d77b8 100644
4d51e5
--- a/lib/label/hints.c
4d51e5
+++ b/lib/label/hints.c
4d51e5
@@ -234,6 +234,7 @@ static int _touch_newhints(void)
4d51e5
 		return_0;
4d51e5
 	if (fclose(fp))
4d51e5
 		stack;
4d51e5
+	log_debug("newhints created");
4d51e5
 	return 1;
4d51e5
 }
4d51e5
 
4d51e5
@@ -504,6 +505,19 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints)
4d51e5
 		if (!hint->chosen)
4d51e5
 			continue;
4d51e5
 
4d51e5
+		/* 
4d51e5
+		 * label_scan was unable to read the dev so we don't know its pvid.
4d51e5
+		 * Since we are unable to verify the hint is correct, it's possible
4d51e5
+		 * that the PVID is actually found on a different device, so don't
4d51e5
+		 * depend on hints. (This would also fail the following pvid check.)
4d51e5
+		 */
4d51e5
+		if (dev->flags & DEV_SCAN_NOT_READ) {
4d51e5
+			log_debug("Uncertain hint for unread device %d:%d %s",
4d51e5
+				  major(hint->devt), minor(hint->devt), dev_name(dev));
4d51e5
+			ret = 0;
4d51e5
+			continue;
4d51e5
+		}
4d51e5
+
4d51e5
 		if (strcmp(dev->pvid, hint->pvid)) {
4d51e5
 			log_debug("Invalid hint device %d:%d %s pvid %s had hint pvid %s",
4d51e5
 				  major(hint->devt), minor(hint->devt), dev_name(dev),
4d51e5
diff --git a/lib/label/label.c b/lib/label/label.c
4d51e5
index 9fac3e464..354ab35e2 100644
4d51e5
--- a/lib/label/label.c
4d51e5
+++ b/lib/label/label.c
4d51e5
@@ -686,6 +686,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
4d51e5
 
4d51e5
 	dm_list_iterate_items_safe(devl, devl2, devs) {
4d51e5
 
4d51e5
+		devl->dev->flags &= ~DEV_SCAN_NOT_READ;
4d51e5
+
4d51e5
 		/*
4d51e5
 		 * If we prefetch more devs than blocks in the cache, then the
4d51e5
 		 * cache will wait for earlier reads to complete, toss the
4d51e5
@@ -701,6 +703,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
4d51e5
 				log_debug_devs("Scan failed to open %s.", dev_name(devl->dev));
4d51e5
 				dm_list_del(&devl->list);
4d51e5
 				dm_list_add(&reopen_devs, &devl->list);
4d51e5
+				devl->dev->flags |= DEV_SCAN_NOT_READ;
4d51e5
 				continue;
4d51e5
 			}
4d51e5
 		}
4d51e5
@@ -724,6 +727,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
4d51e5
 			log_debug_devs("Scan failed to read %s.", dev_name(devl->dev));
4d51e5
 			scan_read_errors++;
4d51e5
 			scan_failed_count++;
4d51e5
+			devl->dev->flags |= DEV_SCAN_NOT_READ;
4d51e5
 			lvmcache_del_dev(devl->dev);
4d51e5
 			if (bb)
4d51e5
 				bcache_put(bb);
4d51e5
@@ -1113,6 +1117,10 @@ int label_scan(struct cmd_context *cmd)
4d51e5
 	 * filter", and this result needs to be cleared (wiped) so that the
4d51e5
 	 * complete set of filters (including those that require data) can be
4d51e5
 	 * checked in _process_block, where headers have been read.
4d51e5
+	 *
4d51e5
+	 * FIXME: devs that are filtered with data in _process_block
4d51e5
+	 * are not moved to the filtered_devs list like devs filtered
4d51e5
+	 * here without data.  Does that have any effect?
4d51e5
 	 */
4d51e5
 	log_debug_devs("Filtering devices to scan (nodata)");
4d51e5
 
4d51e5
-- 
4d51e5
2.34.3
4d51e5