]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
mount_utils: add extended helpers for new mount api
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 5 Feb 2021 15:35:36 +0000 (16:35 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Fri, 5 Feb 2021 17:52:49 +0000 (18:52 +0100)
fs_prepare()
fs_set_property()
fs_attach()
fs_mount()

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/mount_utils.c
src/lxc/mount_utils.h

index 7be0352bcbfdb738d234af30fe72e7d50b3e36c0..590b4bf397ff48eabac332e05a32a4fd1e89d37c 100644 (file)
@@ -194,6 +194,121 @@ int mount_at(int dfd,
        return ret;
 }
 
+static int __fs_prepare(const char *fs_name, int fd_from)
+{
+       __do_close int fd_fs = -EBADF;
+       char source[LXC_PROC_PID_FD_LEN];
+       int ret;
+
+       /* This helper is only concerned with filesystems. */
+       if (is_empty_string(fs_name))
+               return ret_errno(EINVAL);
+
+       /*
+        * So here is where I'm a bit disappointed. The new mount api doesn't
+        * let you specify the block device source through an fd. You need to
+        * pass a path which is obviously crap and runs afoul of the mission to
+        * only use fds for mount.
+        */
+       if (fd_from >= 0) {
+               ret = snprintf(source, sizeof(source), "/proc/self/fd/%d", fd_from);
+               if (ret < 0 || ret >= sizeof(source))
+                       return log_error_errno(-EIO, EIO, "Failed to create /proc/self/fd/%d", fd_from);
+       }
+
+       fd_fs = fsopen(fs_name, FSOPEN_CLOEXEC);
+       if (fd_fs < 0)
+               return log_error_errno(-errno, errno, "Failed to create new open new %s filesystem context", fs_name);
+
+       if (fd_from >= 0) {
+               ret = fsconfig(fd_fs, FSCONFIG_SET_STRING, "source", source, 0);
+               if (ret)
+                       return log_error_errno(-errno, errno, "Failed to set %s filesystem source to %s", fs_name, source);
+
+               TRACE("Set %s filesystem source property to %s", fs_name, source);
+       }
+
+       TRACE("Finished initializing new %s filesystem context %d", fs_name, fd_fs);
+       return move_fd(fd_fs);
+}
+
+int fs_prepare(const char *fs_name,
+              int dfd_from, const char *path_from,
+              __u64 o_flags_from, __u64 resolve_flags_from)
+{
+       __do_close int __fd_from = -EBADF;
+       int fd_from;
+
+       if (!is_empty_string(path_from)) {
+               struct lxc_open_how how = {
+                       .flags          = o_flags_from,
+                       .resolve        = resolve_flags_from,
+               };
+
+               __fd_from = openat2(dfd_from, path_from, &how, sizeof(how));
+               if (__fd_from < 0)
+                       return -errno;
+               fd_from = __fd_from;
+       } else {
+               fd_from = dfd_from;
+       }
+
+       return __fs_prepare(fs_name, fd_from);
+}
+
+int fs_set_property(int fd_fs, const char *key, const char *val)
+{
+       int ret;
+
+       ret = fsconfig(fd_fs, FSCONFIG_SET_STRING, key, val, 0);
+       if (ret < 0)
+               return log_error_errno(-errno, errno,
+                                      "Failed to set \"%s\" to \"%s\" on filesystem context %d",
+                                      key, val, fd_fs);
+
+       TRACE("Set \"%s\" to \"%s\" on filesystem context %d", key, val, fd_fs);
+       return 0;
+}
+
+int fs_attach(int fd_fs,
+             int dfd_to, const char *path_to,
+             __u64 o_flags_to, __u64 resolve_flags_to,
+             unsigned int attr_flags)
+{
+       __do_close int __fd_to = -EBADF, fd_fsmnt = -EBADF;
+       int fd_to, ret;
+
+       if (!is_empty_string(path_to)) {
+               struct lxc_open_how how = {
+                       .flags          = o_flags_to,
+                       .resolve        = resolve_flags_to,
+               };
+
+               __fd_to = openat2(dfd_to, path_to, &how, sizeof(how));
+               if (__fd_to < 0)
+                       return -errno;
+               fd_to = __fd_to;
+       } else {
+               fd_to = dfd_to;
+       }
+
+       ret = fsconfig(fd_fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
+       if (ret < 0)
+               return log_error_errno(-errno, errno, "Failed to finalize filesystem context %d", fd_fs);
+
+       fd_fsmnt = fsmount(fd_fs, FSMOUNT_CLOEXEC, attr_flags);
+       if (fd_fsmnt < 0)
+               return log_error_errno(-errno, errno,
+                                      "Failed to create new mount for filesystem context %d", fd_fs);
+
+       ret = move_mount(fd_fsmnt, "", fd_to, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH);
+       if (ret)
+               return log_error_errno(-errno, errno, "Failed to mount %d onto %d", fd_fsmnt, fd_to);
+
+       TRACE("Mounted %d onto %d", fd_fsmnt, fd_to);
+       return 0;
+}
+
 int mount_from_at(int dfd_from, const char *path_from,
                  __u64 o_flags_from,
                  __u64 resolve_flags_from,
index dddba47be82ab89a3c76bcfb9ef6f505a0ec4e65..efb9915c65ab443452a57c659190811374fa95ae 100644 (file)
@@ -9,6 +9,7 @@
 #include <sys/mount.h>
 
 #include "compiler.h"
+#include "memory_utils.h"
 
 /* open_tree() flags */
 #ifndef OPEN_TREE_CLONE
@@ -162,5 +163,27 @@ __hidden extern int mount_from_at(int dfd_from, const char *path_from,
                                  __u64 o_flags_to, __u64 resolve_flags_to,
                                  const char *fstype, unsigned int mnt_flags,
                                  const void *data);
+__hidden extern int fs_prepare(const char *fs_name, int dfd_from,
+                              const char *path_from, __u64 o_flags_from,
+                              __u64 resolve_flags_from);
+__hidden extern int fs_set_property(int fd_fs, const char *key, const char *val);
+__hidden extern int fs_attach(int fd_fs, int dfd_to, const char *path_to,
+                             __u64 o_flags_to, __u64 resolve_flags_to,
+                             unsigned int attr_flags);
+
+static inline int fs_mount(const char *fs_name, int dfd_from,
+                          const char *path_from, __u64 o_flags_from,
+                          __u64 resolve_flags_from, int dfd_to,
+                          const char *path_to, __u64 o_flags_to,
+                          __u64 resolve_flags_to,
+                          unsigned int attr_flags)
+{
+       __do_close int fd_fs = -EBADF;
+
+       fd_fs = fs_prepare(fs_name, dfd_from, path_from, o_flags_from, resolve_flags_from);
+       if (fd_fs < 0)
+               return -errno;
+       return fs_attach(fd_fs, dfd_to, path_to, o_flags_to, resolve_flags_to, attr_flags);
+}
 
 #endif /* __LXC_MOUNT_UTILS_H */