summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Golle <daniel@makrotopia.org>2021-07-30 01:01:25 +0100
committerDaniel Golle <daniel@makrotopia.org>2021-07-30 02:05:01 +0100
commitb7bf18563769e26d24cdace973d09f9c438bbd34 (patch)
treef34b3eab06bb11efd49a1014ba4d8e793307b920
parentcc63933faedd8d4fcdabb872cf4661ac04fe4ba2 (diff)
downloadfstools-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.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/blockd.c b/blockd.c
index 1e11c88..94cb02e 100644
--- a/blockd.c
+++ b/blockd.c
@@ -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,
};