From: Kay Sievers Date: Wed, 4 Jun 2014 11:30:24 +0000 (+0200) Subject: udev: try first re-reading the partition table X-Git-Tag: v214~91 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=ede344452a54e1c53f541cad12a06269a4fe96a9;hp=bd1fe7c79de3d81325afecb7ded46c1627f6c1df 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) --- diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 6100d7d57..763062f21 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -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; }