]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: (mount) create new FS instance by new Linux API
authorKarel Zak <kzak@redhat.com>
Mon, 26 Sep 2022 13:22:57 +0000 (15:22 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 3 Jan 2023 11:58:42 +0000 (12:58 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/hook_mount.c

index 4cc44b8c19fc7a0e17b996a9185c543ac7334cd0..df5bc573986a9cf771f43bbc375f9f398e42ac54 100644 (file)
@@ -122,13 +122,95 @@ static int hook_reconfigure_mount(struct libmnt_context *cxt __attribute__((__un
        return 0;
 }
 
-static int hook_create_mount(struct libmnt_context *cxt __attribute__((__unused__)),
-                       const struct libmnt_hookset *hs __attribute__((__unused__)),
-                       void *data __attribute__((__unused__)))
+static int configure_superblock(struct libmnt_context *cxt,
+                               const struct libmnt_hookset *hs, int fd)
 {
+       struct libmnt_optlist *ol;
+       struct libmnt_iter itr;
+       struct libmnt_opt *opt;
+       int rc;
+
+       DBG(HOOK, ul_debugobj(hs, " configure FS"));
+
+       ol = mnt_context_get_optlist(cxt);
+       if (!ol)
+               return -ENOMEM;
+
+       mnt_reset_iter(&itr, MNT_ITER_FORWARD);
+
+       while (mnt_optlist_next_opt(ol, &itr, &opt) == 0) {
+               const char *name = mnt_opt_get_name(opt);
+               const char *value = mnt_opt_get_value(opt);
+               const struct libmnt_optmap *ent = mnt_opt_get_mapent(opt);
+
+               if (ent && mnt_opt_get_map(opt) == cxt->map_linux &&
+                   ent->id == MS_RDONLY)
+                       ;
+               else if (!name || mnt_opt_get_map(opt) || mnt_opt_is_external(opt))
+                       continue;
+
+               DBG(HOOK, ul_debugobj(hs, "  fsconfig(name=%s,value=%s)", name, value));
+               if (value)
+                       rc = fsconfig(fd, FSCONFIG_SET_STRING, name, value, 0);
+               else
+                       rc = fsconfig(fd, FSCONFIG_SET_FLAG, name, NULL, 0);
+
+               set_syscall_status(cxt, "fsconfig", rc == 0);
+               if (rc != 0)
+                       return -errno;
+       }
+
        return 0;
 }
 
+static int hook_create_mount(struct libmnt_context *cxt,
+                       const struct libmnt_hookset *hs,
+                       void *data __attribute__((__unused__)))
+{
+       struct libmnt_sysapi *api;
+       const char *src;
+       int rc = 0;
+
+       assert(cxt);
+       assert(cxt->fs);
+
+       api = get_sysapi(cxt, hs);
+       assert(api);
+       assert(api->fd_fs >= 0);
+
+       src = mnt_fs_get_srcpath(cxt->fs);
+       if (!src)
+               return -EINVAL;
+
+       DBG(HOOK, ul_debugobj(hs, "create FS instance"));
+
+       rc = fsconfig(api->fd_fs, FSCONFIG_SET_STRING, "source", src, 0);
+       set_syscall_status(cxt, "fsconfig", rc == 0);
+
+       if (!rc)
+               rc = configure_superblock(cxt, hs, api->fd_fs);
+       if (!rc) {
+               rc = fsconfig(api->fd_fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
+               set_syscall_status(cxt, "fsconfig", rc == 0);
+       }
+
+       if (!rc) {
+               api->fd_tree = fsmount(api->fd_fs, FSMOUNT_CLOEXEC, 0);
+               set_syscall_status(cxt, "fsmount", api->fd_tree >= 0);
+               if (api->fd_tree < 0)
+                       return -errno;
+       }
+       if (!rc && cxt->fs) {
+               struct statx st;
+
+               rc = statx(api->fd_tree, "", AT_EMPTY_PATH, STATX_MNT_ID, &st);
+               cxt->fs->id = (int) st.stx_mnt_id;
+       }
+
+       DBG(HOOK, ul_debugobj(hs, "create FS done [rc=%d]", rc));
+       return rc;
+}
+
 static int hook_set_vfsflags(struct libmnt_context *cxt,
                        const struct libmnt_hookset *hs,
                        void *data __attribute__((__unused__)))
@@ -375,13 +457,8 @@ static int hook_prepare(struct libmnt_context *cxt,
                rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT, NULL,
                                        hook_reconfigure_mount);
 
-       /* call mount_setattr() */
-       if (!rc && (set != 0 || clr != 0))
-               rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT, NULL,
-                                       hook_set_vfsflags);
-
        /* create a new FS instance */
-       if (!rc
+       else if (!rc
            && !(flags & MS_BIND)
            && !(flags & MS_MOVE)
            && !(flags & MS_REMOUNT)
@@ -389,6 +466,11 @@ static int hook_prepare(struct libmnt_context *cxt,
                rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT, NULL,
                                        hook_create_mount);
 
+       /* call mount_setattr() */
+       if (!rc && (set != 0 || clr != 0))
+               rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT, NULL,
+                                       hook_set_vfsflags);
+
        /* call move_mount() to attach target */
        if (!rc
            && !(flags & MS_REMOUNT)