summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c49
-rw-r--r--blockd.c74
2 files changed, 87 insertions, 36 deletions
diff --git a/block.c b/block.c
index ac95464..9458d52 100644
--- a/block.c
+++ b/block.c
@@ -886,35 +886,6 @@ 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)
{
@@ -966,7 +937,8 @@ static int handle_mount(const char *source, const char *target,
return err;
}
-static int blockd_notify(char *device, struct mount *m, struct probe_info *pr)
+static int blockd_notify(const char *method, char *device, struct mount *m,
+ struct probe_info *pr)
{
struct ubus_context *ctx = ubus_connect(NULL);
uint32_t id;
@@ -1019,7 +991,7 @@ static int blockd_notify(char *device, struct mount *m, struct probe_info *pr)
blobmsg_add_u32(&buf, "remove", 1);
}
- err = ubus_invoke(ctx, id, "hotplug", buf.head, NULL, NULL, 3000);
+ err = ubus_invoke(ctx, id, method, buf.head, NULL, NULL, 3000);
} else {
err = -ENOENT;
}
@@ -1070,7 +1042,7 @@ static int mount_device(struct probe_info *pr, int type)
}
if (type == TYPE_HOTPLUG)
- blockd_notify(device, m, pr);
+ blockd_notify("hotplug", device, m, pr);
/* Check if device should be mounted & set the target directory */
if (m) {
@@ -1127,7 +1099,7 @@ static int mount_device(struct probe_info *pr, int type)
handle_swapfiles(true);
if (type != TYPE_AUTOFS)
- hotplug_call_mount("add", device);
+ blockd_notify("mount", device, NULL, NULL);
return 0;
}
@@ -1144,7 +1116,7 @@ static int umount_device(char *path, int type, bool all)
return 0;
if (type != TYPE_AUTOFS)
- hotplug_call_mount("remove", basename(path));
+ blockd_notify("umount", basename(path), NULL, NULL);
err = umount2(mp, MNT_DETACH);
if (err) {
@@ -1169,7 +1141,7 @@ static int mount_action(char *action, char *device, int type)
if (!strcmp(action, "remove")) {
if (type == TYPE_HOTPLUG)
- blockd_notify(device, NULL, NULL);
+ blockd_notify("hotplug", device, NULL, NULL);
umount_device(path, type, true);
@@ -1208,6 +1180,7 @@ static int main_autofs(int argc, char **argv)
cache_load(0);
list_for_each_entry(pr, &devices, list) {
struct mount *m;
+ char *mp;
if (!strcmp(pr->type, "swap"))
continue;
@@ -1216,7 +1189,11 @@ static int main_autofs(int argc, char **argv)
if (m && m->extroot)
continue;
- blockd_notify(pr->dev, m, pr);
+ blockd_notify("hotplug", pr->dev, m, pr);
+ if (!m->autofs && (mp = find_mount_point(pr->dev))) {
+ blockd_notify("mount", pr->dev, NULL, NULL);
+ free(mp);
+ }
}
} else {
if (argc < 4)
diff --git a/blockd.c b/blockd.c
index d283f24..5c7fc89 100644
--- a/blockd.c
+++ b/blockd.c
@@ -305,6 +305,78 @@ block_hotplug(struct ubus_context *ctx, struct ubus_object *obj,
return 0;
}
+static int blockd_mount(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *data[__MOUNT_MAX];
+ struct device *device;
+ char *devname;
+
+ blobmsg_parse(mount_policy, __MOUNT_MAX, data, blob_data(msg), blob_len(msg));
+
+ if (!data[MOUNT_DEVICE])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ devname = blobmsg_get_string(data[MOUNT_DEVICE]);
+
+ device = vlist_find(&devices, devname, device, node);
+ if (!device)
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ hotplug_call_mount("add", device->name, NULL, NULL);
+
+ return 0;
+}
+
+struct blockd_umount_context {
+ struct ubus_context *ctx;
+ struct ubus_request_data req;
+};
+
+static void blockd_umount_hotplug_cb(struct uloop_process *p, int stat)
+{
+ struct hotplug_context *hctx = container_of(p, struct hotplug_context, process);
+ struct blockd_umount_context *c = hctx->priv;
+
+ ubus_complete_deferred_request(c->ctx, &c->req, 0);
+
+ free(c);
+ free(hctx);
+}
+
+static int blockd_umount(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *data[__MOUNT_MAX];
+ struct blockd_umount_context *c;
+ char *devname;
+ int err;
+
+ blobmsg_parse(mount_policy, __MOUNT_MAX, data, blob_data(msg), blob_len(msg));
+
+ if (!data[MOUNT_DEVICE])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ devname = blobmsg_get_string(data[MOUNT_DEVICE]);
+
+ c = calloc(1, sizeof(*c));
+ if (!c)
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ c->ctx = ctx;
+ ubus_defer_request(ctx, req, &c->req);
+
+ err = hotplug_call_mount("remove", devname, blockd_umount_hotplug_cb, c);
+ if (err) {
+ free(c);
+ return UBUS_STATUS_UNKNOWN_ERROR;
+ }
+
+ return 0;
+}
+
static int
block_info(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
@@ -341,6 +413,8 @@ block_info(struct ubus_context *ctx, struct ubus_object *obj,
static const struct ubus_method block_methods[] = {
UBUS_METHOD("hotplug", block_hotplug, mount_policy),
+ UBUS_METHOD("mount", blockd_mount, mount_policy),
+ UBUS_METHOD("umount", blockd_umount, mount_policy),
UBUS_METHOD_NOARG("info", block_info),
};