diff options
| author | Karel Zak <kzak@redhat.com> | 2024-09-19 11:13:22 +0200 |
|---|---|---|
| committer | Karel Zak <kzak@redhat.com> | 2024-09-24 12:40:19 +0200 |
| commit | a904aefe307359700dc64e3ad524baa6ee19e82a (patch) | |
| tree | 5d6d0eaf4f7e22a1035da741884ada2055886ea2 /libmount/src | |
| parent | 466ed6db5fb7e976cae8e0ab8fd45dc505070e99 (diff) | |
| download | util-linux-a904aefe307359700dc64e3ad524baa6ee19e82a.tar.gz | |
libmount: add X-mount.nocanonicalize[=source|target]
The new kernel mount API can bind-mount over a symlink. However, this
feature does not work with libmount because it canonicalizes all paths
by default. A possible workaround is to use the --no-canonicalize
option on the mount(8) command line, but this is a heavy-handed
solution as it disables all conversions for all paths and tags (such
as LABEL=) and fstab processing.
This commit introduces the X-mount.nocanonicalize userspace mount
option to control canonicalization. It only affects paths used for
mounting and does not affect tags and searching in fstab. Additionally,
this setting possible to use in fstab.
If the optional argument [=source|target] is not specified, then paths
canonicalization is disabled for both the source and target paths.
Adresses: https://github.com/util-linux/util-linux/issues/2370
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libmount/src')
| -rw-r--r-- | libmount/src/context.c | 37 | ||||
| -rw-r--r-- | libmount/src/context_mount.c | 2 | ||||
| -rw-r--r-- | libmount/src/mountP.h | 2 |
3 files changed, 38 insertions, 3 deletions
diff --git a/libmount/src/context.c b/libmount/src/context.c index a9cb4ef26c..28cce65e83 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -506,13 +506,45 @@ int mnt_context_disable_canonicalize(struct libmnt_context *cxt, int disable) * mnt_context_is_nocanonicalize: * @cxt: mount context * - * Returns: 1 if no-canonicalize mode is enabled or 0. + * Returns: 1 if no-canonicalize mode (on [u]mount command line) is enabled or 0. */ int mnt_context_is_nocanonicalize(struct libmnt_context *cxt) { return cxt->flags & MNT_FL_NOCANONICALIZE ? 1 : 0; } + +/* + * Returns 1 if "x-mount.nocanonicalize[=<type>]" userspace mount option is + * specified. The optional arguments 'type' should be "source" or "target". + */ +int mnt_context_is_xnocanonicalize( + struct libmnt_context *cxt, + const char *type) +{ + struct libmnt_optlist *ol; + struct libmnt_opt *opt; + const char *arg; + + assert(cxt); + assert(type); + + if (mnt_context_is_nocanonicalize(cxt)) + return 1; + + ol = mnt_context_get_optlist(cxt); + if (!ol) + return 0; + opt = mnt_optlist_get_named(ol, "X-mount.nocanonicalize", + cxt->map_userspace); + if (!opt) + return 0; + arg = mnt_opt_get_value(opt); + if (!arg) + return 1; + return strcmp(arg, type) == 0; +} + /** * mnt_context_enable_lazy: * @cxt: mount context @@ -1884,7 +1916,8 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) rc = path ? mnt_fs_set_source(cxt->fs, path) : -MNT_ERR_NOSOURCE; - } else if (cache && !mnt_fs_is_pseudofs(cxt->fs)) { + } else if (cache && !mnt_fs_is_pseudofs(cxt->fs) + && !mnt_context_is_xnocanonicalize(cxt, "source")) { /* * Source is PATH (canonicalize) */ diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index e42c8705e2..599370782f 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -726,7 +726,7 @@ static int prepare_target(struct libmnt_context *cxt) return -MNT_ERR_NAMESPACE; /* canonicalize the path */ - if (rc == 0) { + if (rc == 0 && !mnt_context_is_xnocanonicalize(cxt, "target")) { struct libmnt_cache *cache = mnt_context_get_cache(cxt); if (cache) { diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index ed5f2ec29f..2c1f62a8ff 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -654,6 +654,8 @@ extern int mnt_context_apply_fs(struct libmnt_context *cxt, struct libmnt_fs *fs extern struct libmnt_optlist *mnt_context_get_optlist(struct libmnt_context *cxt); +extern int mnt_context_is_xnocanonicalize(struct libmnt_context *cxt, const char *type); + /* tab_update.c */ extern int mnt_update_emit_event(struct libmnt_update *upd); extern int mnt_update_set_filename(struct libmnt_update *upd, const char *filename); |
