diff mbox series

device-mapper: fix race with async mmc initialization

Message ID 20220524122346.126308-1-tomas.melin@vaisala.com (mailing list archive)
State New, archived
Headers show
Series device-mapper: fix race with async mmc initialization | expand

Commit Message

Tomas Melin May 24, 2022, 12:23 p.m. UTC
From: Tuomas Pennanen <tuomas.pennanen@vaisala.com>

Device mapper may fail to find mmc device during boot due to the probing
time needed to initialize certain emmc chips.

Probing of the emmc chip happens asynchronously related to
initialization of the device mapper targets, for example dm-verity, and
it may happen that device mapper may try to get the underlying device
before it's available.

Fix the race by introducing a wait loop to the device mapper, which is
similar to how rootfs mount is done, when "rootwait" kernel parameter is
being used.

Signed-off-by: Tuomas Pennanen <tuomas.pennanen@vaisala.com>
Tested-by: Tomas Melin <tomas.melin@vaisala.com>
---
 drivers/md/dm-table.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a37c7b763643..26c5f4d8a977 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -22,6 +22,7 @@ 
 #include <linux/blk-mq.h>
 #include <linux/mount.h>
 #include <linux/dax.h>
+#include <linux/async.h>
 
 #define DM_MSG_PREFIX "table"
 
@@ -349,6 +350,7 @@  int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 	int r;
 	dev_t dev;
 	unsigned int major, minor;
+	unsigned long timeout;
 	char dummy;
 	struct dm_dev_internal *dd;
 	struct dm_table *t = ti->table;
@@ -362,8 +364,16 @@  int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 			return -EOVERFLOW;
 	} else {
 		dev = dm_get_dev_t(path);
-		if (!dev)
-			return -ENODEV;
+		/* wait for any asynchronous scanning to complete */
+		if (!dev) {
+			DMINFO("Waiting for device %s...", path);
+			timeout = jiffies + (60 * HZ);
+			while (!dev && time_before(jiffies, timeout)) {
+				msleep(5);
+				dev = dm_get_dev_t(path);
+			}
+			async_synchronize_full();
+		}
 	}
 
 	dd = find_device(&t->devices, dev);