]> sourceware.org Git - lvm2.git/commitdiff
scan: work around udev problems by avoiding open RDWR
authorDavid Teigland <teigland@redhat.com>
Wed, 20 Jun 2018 16:32:45 +0000 (11:32 -0500)
committerDavid Teigland <teigland@redhat.com>
Wed, 20 Jun 2018 19:08:12 +0000 (14:08 -0500)
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
lib/label/label.c

index 00e398add2132f5eba2542a84b39d315a7f2b331..e879dbb2ecf8f1d2fd5e9de08c7590de56485fb8 100644 (file)
@@ -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.
index 065c01f38645cb5f51990301e7cf0bc9553c9159..d2c868564d57f5ea2a2e0a90d0cabb83469bc788 100644 (file)
@@ -467,12 +467,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:
 
@@ -1124,7 +1136,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);
 }
 
@@ -1166,8 +1185,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);
@@ -1201,8 +1231,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);
@@ -1236,8 +1277,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);
This page took 0.04451 seconds and 5 git commands to generate.