diff options
author | Daniel Golle <daniel@makrotopia.org> | 2021-07-30 01:01:25 +0100 |
---|---|---|
committer | Daniel Golle <daniel@makrotopia.org> | 2021-07-30 02:05:01 +0100 |
commit | b7bf18563769e26d24cdace973d09f9c438bbd34 (patch) | |
tree | f34b3eab06bb11efd49a1014ba4d8e793307b920 | |
parent | cc63933faedd8d4fcdabb872cf4661ac04fe4ba2 (diff) | |
download | fstools-b7bf18563769e26d24cdace973d09f9c438bbd34.tar.gz |
blockd: make most calls to 'block' asynchronous
Don't wait for calls to 'block' to complete unless it's for an
autofs event (which cannot be handled async).
Use uloop for 'mount.ready' notificaion when startup has completed
to avoid blocking in waitpid() while the 'block' process is calling
back via ubus.
This greatly reduces the amount of time blockd needs on boot.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
-rw-r--r-- | blockd.c | 39 |
1 files changed, 27 insertions, 12 deletions
@@ -93,10 +93,10 @@ _find_mount_point(char *device) } static int -block(char *cmd, char *action, char *device) +block(char *cmd, char *action, char *device, int sync, struct uloop_process *process) { pid_t pid = fork(); - int ret = -1; + int ret = sync; int status; char *argv[5] = { 0 }; int a = 0; @@ -107,6 +107,8 @@ block(char *cmd, char *action, char *device) break; case 0: + uloop_end(); + argv[a++] = "/sbin/block"; argv[a++] = cmd; argv[a++] = action; @@ -116,10 +118,15 @@ block(char *cmd, char *action, char *device) exit(EXIT_FAILURE); default: - waitpid(pid, &status, 0); - ret = WEXITSTATUS(status); - if (ret) - ULOG_ERR("failed to run block. %s/%s\n", action, device); + if (!sync && process) { + process->pid = pid; + uloop_process_add(process); + } else if (sync) { + waitpid(pid, &status, 0); + ret = WEXITSTATUS(status); + if (ret) + ULOG_ERR("failed to run block. %s/%s\n", action, device); + } break; } @@ -183,7 +190,7 @@ static void device_mount_remove_hotplug_cb(struct uloop_process *p, int stat) mp = _find_mount_point(device->name); if (mp) { - block("autofs", "remove", device->name); + block("autofs", "remove", device->name, 0, NULL); free(mp); } @@ -339,7 +346,7 @@ block_hotplug(struct ubus_context *ctx, struct ubus_object *obj, device_mount_remove(ctx, old); device_mount_add(ctx, device); } else { - block("mount", NULL, NULL); + block("mount", NULL, NULL, 0, NULL); } } else if (device->autofs) { device_mount_add(ctx, device); @@ -553,7 +560,7 @@ static void autofs_read_handler(struct uloop_fd *u, unsigned int events) pkt = &pktu.missing_indirect; ULOG_ERR("kernel is requesting a mount -> %s\n", pkt->name); if (lstat(pkt->name, &st) == -1) - if (block("autofs", "add", (char *)pkt->name)) + if (block("autofs", "add", (char *)pkt->name, 1, NULL)) cmd = AUTOFS_IOC_FAIL; if (ioctl(fd_autofs_write, cmd, pkt->wait_queue_token) < 0) @@ -565,7 +572,7 @@ static void autofs_expire(struct uloop_timeout *t) struct autofs_packet_expire pkt; while (ioctl(fd_autofs_write, AUTOFS_IOC_EXPIRE, &pkt) == 0) - block("autofs", "remove", pkt.name); + block("autofs", "remove", pkt.name, 1, NULL); uloop_timeout_set(t, AUTOFS_EXPIRE_TIMER); } @@ -625,12 +632,20 @@ static int autofs_mount(void) return 0; } -static void blockd_startup(struct uloop_timeout *t) +static void blockd_startup_cb(struct uloop_process *p, int stat) { - block("autofs", "start", NULL); send_block_notification(&conn.ctx, "ready", NULL); } +static struct uloop_process startup_process = { + .cb = blockd_startup_cb, +}; + +static void blockd_startup(struct uloop_timeout *t) +{ + block("autofs", "start", NULL, 0, &startup_process); +} + struct uloop_timeout startup = { .cb = blockd_startup, }; |