From: Karel Zak Date: Mon, 26 Sep 2022 07:45:04 +0000 (+0200) Subject: libmount: (mount) support propagation by new kernel API X-Git-Tag: v2.39-rc1~252 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6753e6f6912658e836966a6316df956e1af5fcae;p=thirdparty%2Futil-linux.git libmount: (mount) support propagation by new kernel API Signed-off-by: Karel Zak --- diff --git a/libmount/src/context.c b/libmount/src/context.c index 1cf8321c07..e602ce54bc 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -2456,12 +2456,11 @@ int mnt_context_propagation_only(struct libmnt_context *cxt) if (cxt->action != MNT_ACT_MOUNT) return 0; - if (cxt->mountdata || cxt->fs == NULL) return 0; - - if ((cxt->fs->fstype && strcmp(cxt->fs->fstype, "none") != 0) || - (cxt->fs->source && strcmp(cxt->fs->source, "none") == 0)) + if (cxt->fs->fstype && strcmp(cxt->fs->fstype, "none") != 0) + return 0; + if (cxt->fs->source && strcmp(cxt->fs->source, "none") != 0) return 0; ls = mnt_context_get_optlist(cxt); diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index abfd00ebf7..4cc44b8c19 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -140,6 +140,8 @@ static int hook_set_vfsflags(struct libmnt_context *cxt, uint64_t set = 0, clr = 0; int rc; + DBG(HOOK, ul_debugobj(hs, "setting VFS flags")); + api = get_sysapi(cxt, hs); assert(api); assert(api->fd_tree >= 0); @@ -166,10 +168,55 @@ static int hook_set_vfsflags(struct libmnt_context *cxt, return rc == 0 ? 0 : -errno; } -static int hook_set_propagation(struct libmnt_context *cxt __attribute__((__unused__)), - const struct libmnt_hookset *hs __attribute__((__unused__)), +static int hook_set_propagation(struct libmnt_context *cxt, + const struct libmnt_hookset *hs, void *data __attribute__((__unused__))) { + struct libmnt_sysapi *api; + struct libmnt_optlist *ol; + struct libmnt_iter itr; + struct libmnt_opt *opt; + int rc = 0; + + DBG(HOOK, ul_debugobj(hs, "setting propagation")); + + ol = mnt_context_get_optlist(cxt); + if (!ol) + return -ENOMEM; + + api = get_sysapi(cxt, hs); + assert(api); + assert(api->fd_tree >= 0); + + mnt_reset_iter(&itr, MNT_ITER_FORWARD); + + while (mnt_optlist_next_opt(ol, &itr, &opt) == 0) { + const struct libmnt_optmap *map = mnt_opt_get_map(opt); + const struct libmnt_optmap *ent = mnt_opt_get_mapent(opt); + struct mount_attr attr = { .attr_clr = 0 }; + unsigned int flgs = AT_EMPTY_PATH; + + if (cxt->map_linux != map) + continue; + if (mnt_opt_is_external(opt)) + continue; + if (!ent || !ent->id || !(ent->id & MS_PROPAGATION)) + continue; + + attr.propagation = ent->id & MS_PROPAGATION; + if (ent->id & MS_REC) + flgs |= AT_RECURSIVE; + + DBG(HOOK, ul_debugobj(hs, + "mount_setattr(propagation=0x%08" PRIx64")", + (uint64_t) attr.propagation)); + + rc = mount_setattr(api->fd_tree, "", flgs, &attr, sizeof(attr)); + set_syscall_status(cxt, "move_setattr", rc == 0); + if (rc != 0) + return rc; + } + return 0; } @@ -210,9 +257,12 @@ static int init_sysapi(struct libmnt_context *cxt, assert(cxt); assert(hs); + DBG(HOOK, ul_debugobj(hs, "initialize API fds")); + /* A) tree based operation -- the tree is mount source */ if ((flags & MS_BIND) || (flags & MS_MOVE)) { + DBG(HOOK, ul_debugobj(hs, " BIND/MOVE")); path = mnt_fs_get_srcpath(cxt->fs); if (!path) return -EINVAL; @@ -220,6 +270,7 @@ static int init_sysapi(struct libmnt_context *cxt, /* B) tree based operation -- the tree is mount point */ } else if ((flags & MS_REMOUNT) || mnt_context_propagation_only(cxt)) { + DBG(HOOK, ul_debugobj(hs, " REMOUNT/propagation")); path = mnt_fs_get_target(cxt->fs); if (!path) return -EINVAL; @@ -238,7 +289,7 @@ static int init_sysapi(struct libmnt_context *cxt, if (flags & MS_BIND) oflg |= OPEN_TREE_CLONE; - DBG(HOOK, ul_debugobj(hs, "open_tree(%s)", path)); + DBG(HOOK, ul_debugobj(hs, "open_tree(path=%s, flgs=0x%08lx)", path, oflg)); if (mnt_context_is_fake(cxt)) goto fake; @@ -249,6 +300,7 @@ static int init_sysapi(struct libmnt_context *cxt, /* C) FS based operation */ } else { + DBG(HOOK, ul_debugobj(hs, " new FS")); const char *type = mnt_fs_get_fstype(cxt->fs); if (!type) @@ -345,7 +397,7 @@ static int hook_prepare(struct libmnt_context *cxt, hook_attach_target); /* set propagation (has to be attached to VFS) */ - if (!rc && mnt_optlist_get_propagation(ol) != 0) + if (!rc && mnt_optlist_get_propagation(ol)) rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT_POST, NULL, hook_set_propagation); diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 8304d3af0e..3345a14dec 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -557,7 +557,7 @@ extern int mnt_opt_set_external(struct libmnt_opt *opt, int enable); extern int mnt_opt_set_value(struct libmnt_opt *opt, const char *str); extern int mnt_opt_set_u64value(struct libmnt_opt *opt, uint64_t num); extern int mnt_opt_set_quoted_value(struct libmnt_opt *opt, const char *str); - +extern int mnt_opt_is_external(struct libmnt_opt *opt); /* fs.c */ extern int mnt_fs_follow_optlist(struct libmnt_fs *fs, struct libmnt_optlist *ol); diff --git a/libmount/src/optlist.c b/libmount/src/optlist.c index 939473dc56..dfef48fd08 100644 --- a/libmount/src/optlist.c +++ b/libmount/src/optlist.c @@ -747,28 +747,27 @@ int mnt_optlist_get_flags(struct libmnt_optlist *ls, unsigned long *flags, } #ifdef UL_HAVE_MOUNT_API -static inline uint64_t flags_to_attrs(unsigned long flags) +static inline uint64_t flag_to_attr(unsigned long flag) { - uint64_t attrs = 0; - - if (flags & MS_RDONLY) - attrs |= MOUNT_ATTR_RDONLY; - if (flags & MS_NOSUID) - attrs |= MOUNT_ATTR_NOSUID; - if (flags & MS_NOEXEC) - attrs |= MOUNT_ATTR_NOEXEC; - if (flags & MS_NODIRATIME) - attrs |= MOUNT_ATTR_NODIRATIME; - if (flags & MS_RELATIME) - attrs |= MOUNT_ATTR_RELATIME; - if (flags & MS_NOATIME) - attrs |= MOUNT_ATTR_NOATIME; - if (flags & MS_STRICTATIME) - attrs |= MOUNT_ATTR_STRICTATIME; - if (flags & MS_NOSYMFOLLOW) - attrs |= MOUNT_ATTR_NOSYMFOLLOW; - - return attrs; + switch (flag) { + case MS_RDONLY: + return MOUNT_ATTR_RDONLY; + case MS_NOSUID: + return MOUNT_ATTR_NOSUID; + case MS_NOEXEC: + return MOUNT_ATTR_NOEXEC; + case MS_NODIRATIME: + return MOUNT_ATTR_NODIRATIME; + case MS_RELATIME: + return MOUNT_ATTR_RELATIME; + case MS_NOATIME: + return MOUNT_ATTR_NOATIME; + case MS_STRICTATIME: + return MOUNT_ATTR_STRICTATIME; + case MS_NOSYMFOLLOW: + return MOUNT_ATTR_NOSYMFOLLOW; + } + return 0; } #endif @@ -785,24 +784,30 @@ int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *cl if (!ls || !ls->linux_map || !set || !clr) return -EINVAL; + *set = 0, *clr = 0; mnt_reset_iter(&itr, MNT_ITER_FORWARD); while (mnt_optlist_next_opt(ls, &itr, &opt) == 0) { + uint64_t x; + if (ls->linux_map != opt->map) continue; if (!opt->ent || !opt->ent->id) continue; if (!is_wanted_opt(opt, ls->linux_map, MNT_OL_FLTR_DFLT)) continue; + x = flag_to_attr( opt->ent->id ); + if (!x) + continue; if (opt->ent->mask & MNT_INVERT) - *clr |= flags_to_attrs( opt->ent->id ); + *clr |= x; else - *set |= flags_to_attrs( opt->ent->id ); + *set |= x; } DBG(OPTLIST, ul_debugobj(ls, "return attrs set=0x%08" PRIx64 - ", clr=0x08%" PRIx64, *set, *clr)); + ", clr=0x%08" PRIx64, *set, *clr)); return 0; #endif @@ -922,7 +927,7 @@ int mnt_optlist_is_propagation_only(struct libmnt_optlist *ls) return 0; rest = flags & ~MS_PROPAGATION; - return (rest == 0 || rest == MS_SILENT); + return (rest == 0 || (rest & (MS_SILENT | MS_REC))); } int mnt_optlist_is_remount(struct libmnt_optlist *ls) @@ -1032,6 +1037,10 @@ int mnt_opt_set_external(struct libmnt_opt *opt, int enable) return 0; } +int mnt_opt_is_external(struct libmnt_opt *opt) +{ + return opt && opt->external ? 1 : 0; +} #ifdef TEST_PROGRAM