X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=block.c;h=cfc87273ee9969a153a4beededc61a5c6ba40a16;hb=af93f4b8dc32cf1320dfe8f4b93bb3a12606fc33;hp=a35631514ceba3c37c818d60c454874bbbbdbef3;hpb=a778468bca43a269d80b31b5d7b96bf745a00f38;p=oweals%2Ffstools.git diff --git a/block.c b/block.c index a356315..cfc8727 100644 --- 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) { @@ -931,13 +960,14 @@ static int handle_mount(const char *source, const char *target, return err; } -static void blockd_notify(char *device, struct mount *m, struct probe_info *pr) +static int blockd_notify(char *device, struct mount *m, struct probe_info *pr) { struct ubus_context *ctx = ubus_connect(NULL); uint32_t id; + int err; if (!ctx) - return; + return -ENXIO; if (!ubus_lookup_id(ctx, "block", &id)) { struct blob_buf buf = { 0 }; @@ -983,10 +1013,14 @@ static void blockd_notify(char *device, struct mount *m, struct probe_info *pr) blobmsg_add_u32(&buf, "remove", 1); } - ubus_invoke(ctx, id, "hotplug", buf.head, NULL, NULL, 3000); + err = ubus_invoke(ctx, id, "hotplug", buf.head, NULL, NULL, 3000); + } else { + err = -ENOENT; } ubus_free(ctx); + + return err; } static int mount_device(struct probe_info *pr, int type) @@ -1079,37 +1113,32 @@ static int mount_device(struct probe_info *pr, int type) handle_swapfiles(true); + if (type != TYPE_AUTOFS) + hotplug_call_mount("add", device); + return 0; } -static int umount_device(struct probe_info *pr) +static int umount_device(char *path, int type) { - struct mount *m; - char *device = basename(pr->dev); char *mp; int err; - if (!pr) - return -1; - - if (!strcmp(pr->type, "swap")) - return -1; - - mp = find_mount_point(pr->dev); + mp = find_mount_point(path); if (!mp) return -1; - m = find_block(pr->uuid, pr->label, device, NULL); - if (m && m->extroot) - return -1; + if (type != TYPE_AUTOFS) + hotplug_call_mount("remove", basename(path)); err = umount2(mp, MNT_DETACH); - if (err) - ULOG_ERR("unmounting %s (%s) failed (%d) - %m\n", - pr->dev, mp, errno); - else - ULOG_INFO("unmounted %s (%s)\n", - pr->dev, mp); + if (err) { + ULOG_ERR("unmounting %s (%s) failed (%d) - %m\n", path, mp, + errno); + } else { + ULOG_INFO("unmounted %s (%s)\n", path, mp); + rmdir(mp); + } free(mp); return err; @@ -1118,27 +1147,17 @@ static int umount_device(struct probe_info *pr) static int mount_action(char *action, char *device, int type) { char path[32]; - char *mount_point; if (!action || !device) return -1; snprintf(path, sizeof(path), "/dev/%s", device); if (!strcmp(action, "remove")) { - int err = 0; - if (type == TYPE_HOTPLUG) blockd_notify(device, NULL, NULL); - mount_point = find_mount_point(path); - if (mount_point) - err = umount2(mount_point, MNT_DETACH); - - if (err) - ULOG_ERR("umount of %s failed (%d) - %m\n", - mount_point, errno); + umount_device(path, type); - free(mount_point); return 0; } else if (strcmp(action, "add")) { ULOG_ERR("Unkown action %s\n", action); @@ -1160,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; @@ -1171,16 +1192,33 @@ static int main_autofs(int argc, char **argv) cache_load(0); list_for_each_entry(pr, &devices, list) { - struct mount *m = find_block(pr->uuid, pr->label, NULL, NULL); + struct mount *m; - if (m && m->autofs) - mount_device(pr, TYPE_HOTPLUG); - else - blockd_notify(pr->dev, m, pr); + if (!strcmp(pr->type, "swap")) + continue; + + m = find_block(pr->uuid, pr->label, NULL, NULL); + if (m && m->extroot) + continue; + + 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 (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) @@ -1577,8 +1615,18 @@ static int main_umount(int argc, char **argv) handle_swapfiles(false); cache_load(0); - list_for_each_entry(pr, &devices, list) - umount_device(pr); + list_for_each_entry(pr, &devices, list) { + struct mount *m; + + if (!strcmp(pr->type, "swap")) + continue; + + m = find_block(pr->uuid, pr->label, basename(pr->dev), NULL); + if (m && m->extroot) + continue; + + umount_device(pr->dev, TYPE_DEV); + } return 0; }