diff options
author | Kay Sievers <kay@vrfy.org> | 2014-06-04 12:16:28 +0200 |
---|---|---|
committer | Kay Sievers <kay@vrfy.org> | 2014-06-04 12:21:44 +0200 |
commit | f3a740a5dae792fb6b2d411022ce8c29ced1c3f1 (patch) | |
tree | 1decdd0ff053382ea0122a036e96280c6cae7c92 /src/udev/udevd.c | |
parent | 323a2f0b4b3db8f34c382e66f1940c1216bdfc9d (diff) |
udev: synthesize "change' events for partitions when tools change the disk
This should make sure that fdisk-like programs will automatically
cause an update of all partitions, just like mkfs-like programs cause
an update of the partition.
Diffstat (limited to 'src/udev/udevd.c')
-rw-r--r-- | src/udev/udevd.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 59b5568fb6..6100d7d57a 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -46,6 +46,7 @@ #include <sys/utsname.h> #include "udev.h" +#include "udev-util.h" #include "sd-daemon.h" #include "cgroup-util.h" #include "dev-setup.h" @@ -733,15 +734,54 @@ out: return udev_ctrl_connection_unref(ctrl_conn); } -static void synthesize_change(struct udev_device *dev) { +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))) { + struct udev *udev = udev_device_get_udev(dev); + _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; + struct udev_list_entry *item; + + e = udev_enumerate_new(udev); + if (!e) + return -ENOMEM; + + r = udev_enumerate_add_match_parent(e, dev); + if (r < 0) + return r; + + r = udev_enumerate_add_match_subsystem(e, "block"); + if (r < 0) + return r; + + r = udev_enumerate_scan_devices(e); + udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) { + _cleanup_udev_device_unref_ struct udev_device *d = NULL; + + d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); + if (!d) + continue; + + if (!streq_ptr("partition", udev_device_get_devtype(d))) + continue; + + log_debug("device %s closed, synthesising partition '%s' 'change'", + udev_device_get_devnode(dev), udev_device_get_devnode(d)); + strscpyl(filename, sizeof(filename), udev_device_get_syspath(d), "/uevent", NULL); + write_string_file(filename, "change"); + } + } + + return 0; } -/* read inotify messages */ static int handle_inotify(struct udev *udev) { int nbytes, pos; |