]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
mount_utils: add support for bind-mounts through the new mount api
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 5 Feb 2021 16:38:05 +0000 (17:38 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Fri, 5 Feb 2021 17:52:54 +0000 (18:52 +0100)
fd_bind_mount()

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

index a11526d0e6b29b6a115326062d8310d4645a3e52..fa02d23d67913c86cf8ff9ea25b8e1a06c4164c2 100644 (file)
@@ -4,6 +4,7 @@
 #define _GNU_SOURCE 1
 #endif
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mount.h>
@@ -302,3 +303,57 @@ int mount_from_at(int dfd_from, const char *path_from,
 
        return ret;
 }
+
+int fd_bind_mount(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, bool recursive)
+{
+       __do_close int __fd_from = -EBADF, __fd_to = -EBADF;
+       __do_close int fd_tree_from = -EBADF;
+       unsigned int open_tree_flags = AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLONE;
+       int fd_from, fd_to, ret;
+
+       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;
+       }
+
+       if (recursive)
+               open_tree_flags |= AT_RECURSIVE;
+
+       fd_tree_from = open_tree(fd_from, "", open_tree_flags);
+       if (fd_tree_from < 0)
+               return log_error_errno(-errno, errno, "Failed to create detached mount");
+
+       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 = move_mount(fd_tree_from, "", fd_to, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH);
+       if (ret)
+               return log_error_errno(-errno, errno, "Failed to attach detached mount %d to filesystem at %d", fd_tree_from, fd_to);
+
+       TRACE("Attach detached mount %d to filesystem at %d", fd_tree_from, fd_to);
+       return 0;
+}
index 8f57802f5acbef8404b903cb56078dc667724386..cced086c40d426dad50a3ec30d3800d10e72e211 100644 (file)
 #include "memory_utils.h"
 
 /* open_tree() flags */
+
+#ifndef AT_RECURSIVE
+#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
+#endif
+
 #ifndef OPEN_TREE_CLONE
 #define OPEN_TREE_CLONE 1
 #endif
@@ -181,4 +186,10 @@ static inline int fs_mount(const char *fs_name, int dfd_from,
        return fs_attach(fd_fs, dfd_to, path_to, o_flags_to, resolve_flags_to, attr_flags);
 }
 
+__hidden extern int fd_bind_mount(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, bool recursive);
+
 #endif /* __LXC_MOUNT_UTILS_H */