[lvm-devel] 2018-06-01-stable - scan: work around udev problems by avoiding open RDWR

David Teigland teigland at sourceware.org
Wed Jun 20 17:05:50 UTC 2018


Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=a30e6222799409ab6e6151683c95eb13f4abaefb
Commit:        a30e6222799409ab6e6151683c95eb13f4abaefb
Parent:        76075ff55d7d23731b91929ef992fe6bdd32a964
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Wed Jun 20 11:32:45 2018 -0500
Committer:     David Teigland <teigland at redhat.com>
CommitterDate: Wed Jun 20 12:05:04 2018 -0500

scan: work around udev problems by avoiding open RDWR

udev creates a train wreck of events if we open devices
with RDWR.  Until we can fix/disable/scrap udev, work around
this by opening RDONLY and then closing/reopening RDWR when
a write is needed.  This invalidates the bcache blocks for
the device before writing so it can trigger unnecessary
rereading.
---
 lib/device/device.h |    1 +
 lib/label/label.c   |   56 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/lib/device/device.h b/lib/device/device.h
index c8ccd73..bbd965a 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -35,6 +35,7 @@
 #define DEV_BCACHE_EXCL		0x00001000      /* bcache_fd should be open EXCL */
 #define DEV_FILTER_AFTER_SCAN	0x00002000	/* apply filter after bcache has data */
 #define DEV_FILTER_OUT_SCAN	0x00004000	/* filtered out during label scan */
+#define DEV_BCACHE_WRITE	0x00008000      /* bcache_fd is open with RDWR */
 
 /*
  * Support for external device info.
diff --git a/lib/label/label.c b/lib/label/label.c
index d7d3f9e..ca465dd 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -464,12 +464,24 @@ static int _scan_dev_open(struct device *dev)
 	name_sl = dm_list_item(name_list, struct dm_str_list);
 	name = name_sl->str;
 
-	flags |= O_RDWR;
 	flags |= O_DIRECT;
 	flags |= O_NOATIME;
 
-	if (dev->flags & DEV_BCACHE_EXCL)
+	/*
+	 * FIXME: udev is a train wreck when we open RDWR and close, so we
+	 * need to only use RDWR when we actually need to write, and use
+	 * RDONLY otherwise.  Fix, disable or scrap udev nonsense so we can
+	 * just open with RDWR by default.
+	 */
+
+	if (dev->flags & DEV_BCACHE_EXCL) {
 		flags |= O_EXCL;
+		flags |= O_RDWR;
+	} else if (dev->flags & DEV_BCACHE_WRITE) {
+		flags |= O_RDWR;
+	} else {
+		flags |= O_RDONLY;
+	}
 
 retry_open:
 
@@ -1107,7 +1119,14 @@ int label_scan_open(struct device *dev)
 
 int label_scan_open_excl(struct device *dev)
 {
+	if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_EXCL)) {
+		/* FIXME: avoid tossing out bcache blocks just to replace fd. */
+		log_debug("Close and reopen excl %s", dev_name(dev));
+		bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+		_scan_dev_close(dev);
+	}
 	dev->flags |= DEV_BCACHE_EXCL;
+	dev->flags |= DEV_BCACHE_WRITE;
 	return label_scan_open(dev);
 }
 
@@ -1149,8 +1168,19 @@ bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data)
 		return false;
 	}
 
+	if (!(dev->flags & DEV_BCACHE_WRITE)) {
+		/* FIXME: avoid tossing out bcache blocks just to replace fd. */
+		log_debug("Close and reopen to write %s", dev_name(dev));
+		bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+		_scan_dev_close(dev);
+
+		dev->flags |= DEV_BCACHE_WRITE;
+		label_scan_open(dev);
+	}
+
 	if (dev->bcache_fd <= 0) {
 		/* This is not often needed, perhaps only with lvmetad. */
+		dev->flags |= DEV_BCACHE_WRITE;
 		if (!label_scan_open(dev)) {
 			log_error("Error opening device %s for writing at %llu length %u.",
 				  dev_name(dev), (unsigned long long)start, (uint32_t)len);
@@ -1184,8 +1214,19 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len)
 		return false;
 	}
 
+	if (!(dev->flags & DEV_BCACHE_WRITE)) {
+		/* FIXME: avoid tossing out bcache blocks just to replace fd. */
+		log_debug("Close and reopen to write %s", dev_name(dev));
+		bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+		_scan_dev_close(dev);
+
+		dev->flags |= DEV_BCACHE_WRITE;
+		label_scan_open(dev);
+	}
+
 	if (dev->bcache_fd <= 0) {
 		/* This is not often needed, perhaps only with lvmetad. */
+		dev->flags |= DEV_BCACHE_WRITE;
 		if (!label_scan_open(dev)) {
 			log_error("Error opening device %s for writing at %llu length %u.",
 				  dev_name(dev), (unsigned long long)start, (uint32_t)len);
@@ -1219,8 +1260,19 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val)
 		return false;
 	}
 
+	if (!(dev->flags & DEV_BCACHE_WRITE)) {
+		/* FIXME: avoid tossing out bcache blocks just to replace fd. */
+		log_debug("Close and reopen to write %s", dev_name(dev));
+		bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+		_scan_dev_close(dev);
+
+		dev->flags |= DEV_BCACHE_WRITE;
+		label_scan_open(dev);
+	}
+
 	if (dev->bcache_fd <= 0) {
 		/* This is not often needed, perhaps only with lvmetad. */
+		dev->flags |= DEV_BCACHE_WRITE;
 		if (!label_scan_open(dev)) {
 			log_error("Error opening device %s for writing at %llu length %u.",
 				  dev_name(dev), (unsigned long long)start, (uint32_t)len);




More information about the lvm-devel mailing list