X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=blockd.c;h=8bb5005a7f3d575ab4e351ba66315720de8b6b64;hb=e1b68111e1661c92a773cc5131b55f98d943888f;hp=1e11c886797299a9a6474b236ec1f67a1fc59168;hpb=cc63933faedd8d4fcdabb872cf4661ac04fe4ba2;p=project%2Ffstools.git diff --git a/blockd.c b/blockd.c index 1e11c88..8bb5005 100644 --- a/blockd.c +++ b/blockd.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -93,10 +94,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 +108,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 +119,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; } @@ -127,7 +135,7 @@ block(char *cmd, char *action, char *device) } static int send_block_notification(struct ubus_context *ctx, const char *action, - const char *devname); + const char *devname, const char *target); static int hotplug_call_mount(struct ubus_context *ctx, const char *action, const char *devname, uloop_process_handler cb, void *priv) { @@ -145,6 +153,9 @@ static int hotplug_call_mount(struct ubus_context *ctx, const char *action, pid = fork(); switch (pid) { case -1: + if (c) + free(c); + err = -errno; ULOG_ERR("fork() failed\n"); return err; @@ -167,8 +178,6 @@ static int hotplug_call_mount(struct ubus_context *ctx, const char *action, break; } - send_block_notification(ctx, action, devname); - return 0; } @@ -183,7 +192,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); } @@ -193,8 +202,12 @@ static void device_mount_remove_hotplug_cb(struct uloop_process *p, int stat) static void device_mount_remove(struct ubus_context *ctx, struct device *device) { - hotplug_call_mount(ctx, "remove", device->name, + static const char *action = "remove"; + + hotplug_call_mount(ctx, action, device->name, device_mount_remove_hotplug_cb, device); + + send_block_notification(ctx, action, device->name, device->target); } static void device_mount_add(struct ubus_context *ctx, struct device *device) @@ -219,11 +232,13 @@ static void device_mount_add(struct ubus_context *ctx, struct device *device) *tmp = '/'; } - if (symlink(path, device->target)) + if (symlink(path, device->target)) { ULOG_ERR("failed to symlink %s->%s (%d) - %m\n", device->target, path, errno); - else - hotplug_call_mount(ctx, "add", device->name, NULL, NULL); - + } else { + static const char *action = "add"; + hotplug_call_mount(ctx, action, device->name, NULL, NULL); + send_block_notification(ctx, action, device->name, device->target); + } free(path); } @@ -339,7 +354,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); @@ -353,6 +368,7 @@ static int blockd_mount(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { + static const char *action = "add"; struct blob_attr *data[__MOUNT_MAX]; struct device *device; char *devname; @@ -368,7 +384,8 @@ static int blockd_mount(struct ubus_context *ctx, struct ubus_object *obj, if (!device) return UBUS_STATUS_UNKNOWN_ERROR; - hotplug_call_mount(ctx, "add", device->name, NULL, NULL); + hotplug_call_mount(ctx, action, device->name, NULL, NULL); + send_block_notification(ctx, action, device->name, device->target); return 0; } @@ -395,7 +412,10 @@ static int blockd_umount(struct ubus_context *ctx, struct ubus_object *obj, { struct blob_attr *data[__MOUNT_MAX]; struct blockd_umount_context *c; + static const char *action = "remove"; char *devname; + static char oldtarget[PATH_MAX]; + struct device *device; int err; blobmsg_parse(mount_policy, __MOUNT_MAX, data, blob_data(msg), blob_len(msg)); @@ -404,6 +424,11 @@ static int blockd_umount(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_INVALID_ARGUMENT; devname = blobmsg_get_string(data[MOUNT_DEVICE]); + device = vlist_find(&devices, devname, device, node); + if (device) { + strncpy(oldtarget, device->target, sizeof(oldtarget)-1); + oldtarget[PATH_MAX - 1] = '\0'; + } c = calloc(1, sizeof(*c)); if (!c) @@ -412,12 +437,14 @@ static int blockd_umount(struct ubus_context *ctx, struct ubus_object *obj, c->ctx = ctx; ubus_defer_request(ctx, req, &c->req); - err = hotplug_call_mount(ctx, "remove", devname, blockd_umount_hotplug_cb, c); + err = hotplug_call_mount(ctx, action, devname, blockd_umount_hotplug_cb, c); if (err) { free(c); return UBUS_STATUS_UNKNOWN_ERROR; } + send_block_notification(ctx, action, devname, oldtarget); + return 0; } @@ -495,7 +522,7 @@ static struct ubus_object block_object = { /* send ubus event for successful mounts, useful for procd triggers */ static int send_block_notification(struct ubus_context *ctx, const char *action, - const char *devname) + const char *devname, const char *target) { struct blob_buf buf = { 0 }; char evname[16] = "mount."; @@ -509,7 +536,10 @@ static int send_block_notification(struct ubus_context *ctx, const char *action, blob_buf_init(&buf, 0); if (devname) - blobmsg_add_string(&buf, "devname", devname); + blobmsg_add_string(&buf, "device", devname); + + if (target) + blobmsg_add_string(&buf, "target", target); err = ubus_notify(ctx, &block_object, evname, buf.head, -1); @@ -553,7 +583,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 +595,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,10 +655,18 @@ static int autofs_mount(void) return 0; } +static void blockd_startup_cb(struct uloop_process *p, int stat) +{ + send_block_notification(&conn.ctx, "ready", NULL, NULL); +} + +static struct uloop_process startup_process = { + .cb = blockd_startup_cb, +}; + static void blockd_startup(struct uloop_timeout *t) { - block("autofs", "start", NULL); - send_block_notification(&conn.ctx, "ready", NULL); + block("autofs", "start", NULL, 0, &startup_process); } struct uloop_timeout startup = {