From: Karel Zak Date: Tue, 18 Oct 2022 10:33:39 +0000 (+0200) Subject: libmount: (subdir) use new FD based API X-Git-Tag: v2.39-rc1~233 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=f3bb0ca17a17701ad61aa6ffde8dd46b8391952c;p=thirdparty%2Futil-linux.git libmount: (subdir) use new FD based API Signed-off-by: Karel Zak --- diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index 397a2aa330..91bb4b6f55 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -50,18 +50,6 @@ #define get_sysapi(_cxt) mnt_context_get_sysapi(_cxt) -#define set_syscall_status(_cxt, _name, _x) __extension__ ({ \ - if (!(_x)) { \ - DBG(HOOK, ul_debug("syscall '%s' [%m]", _name)); \ - (_cxt)->syscall_status = -errno; \ - (_cxt)->syscall_name = (_name); \ - } else { \ - DBG(HOOK, ul_debug("syscall '%s' [succes]", _name)); \ - (_cxt)->syscall_status = 0; \ - } \ - }) - - /* * This hookset uses 'struct libmnt_sysapi' (mountP.h) as hookset data. */ diff --git a/libmount/src/hook_subdir.c b/libmount/src/hook_subdir.c index d0a274bc70..74120f6d74 100644 --- a/libmount/src/hook_subdir.c +++ b/libmount/src/hook_subdir.c @@ -147,25 +147,71 @@ static int tmptgt_cleanup(int old_ns_fd) #endif } -static int do_mount_subdir(const char *root, - const char *subdir, - const char *target) +static int do_mount_subdir( + struct libmnt_context *cxt, + const char *root, + const char *subdir, + const char *target) { - char *src = NULL; int rc = 0; - if (asprintf(&src, "%s/%s", root, subdir) < 0) - return -ENOMEM; +#ifdef UL_HAVE_MOUNT_API + struct libmnt_sysapi *api; + + api = mnt_context_get_sysapi(cxt); + if (api) { + /* FD based way - unfortunately, it's impossible to open + * sub-directory on not-yet attached mount. It means hook_mount.c + * attaches to FS to temporary directory, and we clone + * and move the subdir, and umount the old temporary tree. + * + * The old mount(2) way does the same, but by BIND. + */ + int fd; + + DBG(HOOK, ul_debug("attach subdir %s", subdir)); + fd = open_tree(api->fd_tree, subdir, + OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE); + set_syscall_status(cxt, "open_tree", fd >= 0); + if (fd < 0) + rc = -errno; + + if (!rc) { + rc = move_mount(fd, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH); + set_syscall_status(cxt, "move_mount", rc == 0); + if (rc) + rc = -errno; + } + if (!rc) { + close(api->fd_tree); + api->fd_tree = fd; + } + } else +#endif + { + char *src = NULL; + + if (asprintf(&src, "%s/%s", root, subdir) < 0) + return -ENOMEM; + + /* Classic mount(2) based way */ + DBG(HOOK, ul_debug("mount subdir %s to %s", src, target)); + rc = mount(src, target, NULL, MS_BIND, NULL); - DBG(HOOK, ul_debug("mount subdir %s to %s", src, target)); - if (mount(src, target, NULL, MS_BIND | MS_REC, NULL) != 0) - rc = -MNT_ERR_APPLYFLAGS; + set_syscall_status(cxt, "mount", rc == 0); + if (rc) + rc = -errno; + free(src); + } - DBG(HOOK, ul_debug("umount old root %s", root)); - if (umount(root) != 0) - rc = -MNT_ERR_APPLYFLAGS; + if (!rc) { + DBG(HOOK, ul_debug("umount old root %s", root)); + rc = umount(root); + set_syscall_status(cxt, "umount", rc == 0); + if (rc) + rc = -errno; + } - free(src); return rc; } @@ -186,7 +232,7 @@ static int hook_mount_post( mnt_fs_set_target(cxt->fs, hsd->org_target); /* bind subdir to the real target, umount temporary target */ - rc = do_mount_subdir(MNT_PATH_TMPTGT, + rc = do_mount_subdir(cxt, MNT_PATH_TMPTGT, hsd->subdir, mnt_fs_get_target(cxt->fs)); if (rc) diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 1c7f579aca..d2fced092d 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -463,6 +463,17 @@ struct libmnt_context /* Flags usable with MS_BIND|MS_REMOUNT */ #define MNT_BIND_SETTABLE (MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_NOATIME|MS_NODIRATIME|MS_RELATIME|MS_RDONLY|MS_NOSYMFOLLOW) +#define set_syscall_status(_cxt, _name, _x) __extension__ ({ \ + if (!(_x)) { \ + DBG(CXT, ul_debug("syscall '%s' [%m]", _name)); \ + (_cxt)->syscall_status = -errno; \ + (_cxt)->syscall_name = (_name); \ + } else { \ + DBG(CXT, ul_debug("syscall '%s' [succes]", _name)); \ + (_cxt)->syscall_status = 0; \ + } \ + }) + /* optmap.c */ extern const struct libmnt_optmap *mnt_optmap_get_entry( struct libmnt_optmap const **maps,