block: generate hotplug.d mount events
authorRafał Miłecki <rafal@milecki.pl>
Sun, 9 Dec 2018 14:52:32 +0000 (15:52 +0100)
committerRafał Miłecki <rafal@milecki.pl>
Sun, 9 Dec 2018 14:52:32 +0000 (15:52 +0100)
With this change block generates 2 "mount" hotplug.d subsystem events:
1) "add" when block device gets mounted
2) "remove" when block device gets unmounted

This allows e.g. controlling USB storage dependant software using
hotplug.d listeners.

A very similar solution was implemented in mountd which was replaced by
blockd.

Right now this is implemented using a call to the /sbin/hotplug-call.
A possible improvement is to rewrite above shell script into a C lib
function. For now let's just assume that script exists.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
block.c

diff --git a/block.c b/block.c
index a0bbf47..cfd95b4 100644 (file)
--- a/block.c
+++ b/block.c
@@ -880,6 +880,35 @@ static int exec_mount(const char *source, const char *target,
        return err;
 }
 
+static int hotplug_call_mount(const char *action, const char *device)
+{
+       pid_t pid;
+       int err = 0;
+
+       pid = fork();
+       if (!pid) {
+               char * const argv[] = { "hotplug-call", "mount", NULL };
+
+               setenv("ACTION", action, 1);
+               setenv("DEVICE", device, 1);
+
+               execv("/sbin/hotplug-call", argv);
+               exit(-1);
+       } else if (pid > 0) {
+               int status;
+
+               pid = waitpid(pid, &status, 0);
+               if (pid <= 0 || !WIFEXITED(status) || WEXITSTATUS(status)) {
+                       err = -ENOEXEC;
+                       ULOG_ERR("hotplug-call call failed\n");
+               }
+       } else {
+               err = -errno;
+       }
+
+       return err;
+}
+
 static int handle_mount(const char *source, const char *target,
                         const char *fstype, struct mount *m)
 {
@@ -1079,6 +1108,8 @@ static int mount_device(struct probe_info *pr, int type)
 
        handle_swapfiles(true);
 
+       hotplug_call_mount("add", device);
+
        return 0;
 }
 
@@ -1091,6 +1122,8 @@ static int umount_device(char *path)
        if (!mp)
                return -1;
 
+       hotplug_call_mount("remove", basename(path));
+
        err = umount2(mp, MNT_DETACH);
        if (err)
                ULOG_ERR("unmounting %s (%s) failed (%d) - %m\n", path, mp,