From f3a740a5dae792fb6b2d411022ce8c29ced1c3f1 Mon Sep 17 00:00:00 2001
From: Kay Sievers <kay@vrfy.org>
Date: Wed, 4 Jun 2014 12:16:28 +0200
Subject: [PATCH] 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.

Signed-off-by: Robert Milasan <rmilasan@suse.com>
---
 src/udev/udevd.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

Index: systemd-210/src/udev/udevd.c
===================================================================
--- systemd-210.orig/src/udev/udevd.c
+++ systemd-210/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"
@@ -736,15 +737,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;