diff options
author | Anthony G. Basile <blueness@gentoo.org> | 2014-06-07 08:41:42 -0400 |
---|---|---|
committer | Anthony G. Basile <blueness@gentoo.org> | 2014-06-07 08:41:42 -0400 |
commit | 8a892f61097f90cf06cc33ab0510cd4ecbf64e11 (patch) | |
tree | f85c2581930636b6b886f3a455d1b01111ba8e7f | |
parent | 50decc8ac8f7c9d91ec46a5a52ef0f161f752be0 (diff) |
[PATCH] 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)
Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
-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 b21c962272..d598ba39e3 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 <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; } |