diff options
author | Kay Sievers <kay@vrfy.org> | 2014-06-04 13:30:24 +0200 |
---|---|---|
committer | Kay Sievers <kay@vrfy.org> | 2014-06-04 13:35:02 +0200 |
commit | ede344452a54e1c53f541cad12a06269a4fe96a9 (patch) | |
tree | 478aa88c80e4cd7bc889a4ed5f056a8c0e7816b1 | |
parent | bd1fe7c79de3d81325afecb7ded46c1627f6c1df (diff) |
udev: try first re-reading the partition table
mounted partitions:
# dd if=/dev/zero of=/dev/sda bs=1 count=1
UDEV [4157.369250] change .../0:0:0:0/block/sda (block)
UDEV [4157.375059] change .../0:0:0:0/block/sda/sda1 (block)
UDEV [4157.397088] change .../0:0:0:0/block/sda/sda2 (block)
UDEV [4157.404842] change .../0:0:0:0/block/sda/sda4 (block)
unmounted partitions:
# dd if=/dev/zero of=/dev/sdb bs=1 count=1
UDEV [4163.450217] remove .../target6:0:0/6:0:0:0/block/sdb/sdb1 (block)
UDEV [4163.593167] change .../target6:0:0/6:0:0:0/block/sdb (block)
UDEV [4163.713982] add .../target6:0:0/6:0:0:0/block/sdb/sdb1 (block)
-rw-r--r-- | src/udev/udevd.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 6100d7d57a..763062f219 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -38,6 +38,7 @@ #include <sys/un.h> #include <sys/signalfd.h> #include <sys/epoll.h> +#include <sys/mount.h> #include <sys/poll.h> #include <sys/wait.h> #include <sys/stat.h> @@ -738,17 +739,37 @@ static int synthesize_change(struct udev_device *dev) { char filename[UTIL_PATH_SIZE]; int r; - log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev)); - strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); - write_string_file(filename, "change"); - - /* for disks devices, re-trigger all partitions too */ if (streq_ptr("block", udev_device_get_subsystem(dev)) && - streq_ptr("disk", udev_device_get_devtype(dev))) { + streq_ptr("disk", udev_device_get_devtype(dev)) && + !startswith("dm-", udev_device_get_sysname(dev))) { + int fd; struct udev *udev = udev_device_get_udev(dev); _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item; + /* + * Try to re-read the partition table, this only succeeds if + * none of the devices is busy. + * + * The kernel will send out a change event for the disk, and + * "remove/add" for all partitions. + */ + fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); + if (fd >= 0) { + r = ioctl(fd, BLKRRPART, 0); + close(fd); + if (r >= 0) + return 0; + } + + /* + * Re-reading the partition table did not work, synthesize "change" + * events for the disk and all partitions. + */ + log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev)); + strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); + write_string_file(filename, "change"); + e = udev_enumerate_new(udev); if (!e) return -ENOMEM; @@ -777,8 +798,14 @@ static int synthesize_change(struct udev_device *dev) { strscpyl(filename, sizeof(filename), udev_device_get_syspath(d), "/uevent", NULL); write_string_file(filename, "change"); } + + return 0; } + log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev)); + strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); + write_string_file(filename, "change"); + return 0; } |