block(d): improve hotplug.d "mount" events for the autofs
authorRafał Miłecki <rafal@milecki.pl>
Wed, 12 Dec 2018 14:24:35 +0000 (15:24 +0100)
committerRafał Miłecki <rafal@milecki.pl>
Fri, 28 Dec 2018 22:10:32 +0000 (23:10 +0100)
So far - when using autofs - "add" and "remove" action events were
triggered on every (un)mount. It wasn't very helpful when using autofs
due to its nature.

The point of blockd & autofs is to have block devices mounted on an
access request. Its users should not care / know if it's currently
mounted or not. Mounting should be handled transparently.

To make that work it requires informing listeners whenever device:
1) Becomes *ready* for mounting (by triggering "add" action)
2) Becomes *unavailable* (by triggering "remove" action)

The current mounting state is something that autofs & blockd should
handle internally and should not notify listeners about.

This is implemented by:
1) block generating events for non-autofs cases only (when (un)mounting)
2) blockd informing block when autofs resource becomes (un)available

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

diff --git a/block.c b/block.c
index f7fdc274b2c2902f8e9ea917f12aba733d9803e2..cfc87273ee9969a153a4beededc61a5c6ba40a16 100644 (file)
--- a/block.c
+++ b/block.c
@@ -1113,12 +1113,13 @@ static int mount_device(struct probe_info *pr, int type)
 
        handle_swapfiles(true);
 
-       hotplug_call_mount("add", device);
+       if (type != TYPE_AUTOFS)
+               hotplug_call_mount("add", device);
 
        return 0;
 }
 
-static int umount_device(char *path)
+static int umount_device(char *path, int type)
 {
        char *mp;
        int err;
@@ -1127,7 +1128,8 @@ static int umount_device(char *path)
        if (!mp)
                return -1;
 
-       hotplug_call_mount("remove", basename(path));
+       if (type != TYPE_AUTOFS)
+               hotplug_call_mount("remove", basename(path));
 
        err = umount2(mp, MNT_DETACH);
        if (err) {
@@ -1154,7 +1156,7 @@ static int mount_action(char *action, char *device, int type)
                if (type == TYPE_HOTPLUG)
                        blockd_notify(device, NULL, NULL);
 
-               umount_device(path);
+               umount_device(path, type);
 
                return 0;
        } else if (strcmp(action, "add")) {
@@ -1177,6 +1179,8 @@ static int main_hotplug(int argc, char **argv)
 
 static int main_autofs(int argc, char **argv)
 {
+       int err = 0;
+
        if (argc < 3)
                return -1;
 
@@ -1199,13 +1203,22 @@ static int main_autofs(int argc, char **argv)
 
                        blockd_notify(pr->dev, m, pr);
                }
-               return 0;
+       } else if (!strcmp(argv[2], "available")) {
+               err = hotplug_call_mount("add", argv[3]);
+       } else if (!strcmp(argv[2], "unavailable")) {
+               err = hotplug_call_mount("remove", argv[3]);
+       } else {
+               if (argc < 4)
+                       return -EINVAL;
+
+               err = mount_action(argv[2], argv[3], TYPE_AUTOFS);
        }
 
-       if (argc < 4)
-               return -EINVAL;
+       if (err) {
+               ULOG_ERR("autofs: \"%s\" action has failed: %d\n", argv[2], err);
+       }
 
-       return mount_action(argv[2], argv[3], TYPE_AUTOFS);
+       return err;
 }
 
 static int find_block_mtd(char *name, char *part, int plen)
@@ -1612,7 +1625,7 @@ static int main_umount(int argc, char **argv)
                if (m && m->extroot)
                        continue;
 
-               umount_device(pr->dev);
+               umount_device(pr->dev, TYPE_DEV);
        }
 
        return 0;
index a00a5b328e7074d4f3bcc7fc1f3e35e2eec3d69d..88fe1682fa2cb9202236f9d187dbf9f200a0d9dc 100644 (file)
--- a/blockd.c
+++ b/blockd.c
@@ -116,6 +116,8 @@ device_free(struct device *device)
        if (!device->autofs)
                return;
 
+       block("autofs", "unavailable", device->name);
+
        if (device->target)
                unlink(device->target);
 
@@ -137,6 +139,8 @@ device_add(struct device *device)
        snprintf(path, sizeof(path), "/tmp/run/blockd/%s", device->name);
        if (symlink(path, device->target))
                ULOG_ERR("failed to symlink %s->%s\n", device->target, path);
+       else
+               block("autofs", "available", device->name);
 }
 
 static int