From: Karel Zak Date: Thu, 25 Jun 2026 12:52:21 +0000 (+0200) Subject: libmount: merge utab into listmount-based tables X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b76aaa07851e7745e6d9b2476688dfc47ce7f415;p=thirdparty%2Futil-linux.git libmount: merge utab into listmount-based tables Extract utab merge logic from __mnt_table_parse_mountinfo() into a shared mnt_table_merge_utab() function and call it at the end of mnt_table_fetch_listmount(). This makes userspace mount options (x-systemd.*, user=, etc.) available when the mount table is obtained via listmount/statmount syscalls. The merge sets user_optstr directly (instead of the combined optstr) to avoid conflicts with lazy statmount() which populates kernel options on demand. Add mnt_table_disable_useropts() public API to allow callers to skip utab merging when only kernel-side data is needed. Use the new API in findmnt --kernel=listmount to keep backward compatible behavior (kernel-only data); users who want userspace options can use --mtab. Signed-off-by: Karel Zak (cherry picked from commit c839a9ac8fed409c332c94ec69ddc11aea97ae80) --- diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 607036218..8d11867aa 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -413,6 +413,7 @@ mnt_table_next_fs mnt_table_over_fs mnt_table_parse_dir mnt_table_parse_file +mnt_table_disable_useropts mnt_table_parse_fstab mnt_table_parse_mtab mnt_table_parse_stream diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index 04b7b3074..d3b39e661 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -608,6 +608,7 @@ extern int mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname); extern int mnt_table_parse_fstab(struct libmnt_table *tb, const char *filename); extern int mnt_table_parse_swaps(struct libmnt_table *tb, const char *filename); extern int mnt_table_parse_mtab(struct libmnt_table *tb, const char *filename); +extern int mnt_table_disable_useropts(struct libmnt_table *tb, int disable); extern int mnt_table_set_parser_errcb(struct libmnt_table *tb, int (*cb)(struct libmnt_table *tb, const char *filename, int line)); diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 42fefc150..0240b5fe0 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -421,3 +421,7 @@ MOUNT_2_42 { mnt_fs_is_attached; mnt_fs_is_detached; } MOUNT_2_41; + +MOUNT_2_43 { + mnt_table_disable_useropts; +} MOUNT_2_42; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 3f5a93d94..0f6ee4f6d 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -151,6 +151,8 @@ extern int mnt_table_set_parser_fltrcb( struct libmnt_table *tb, extern int __mnt_table_parse_mountinfo(struct libmnt_table *tb, const char *filename, struct libmnt_table *u_tb); +extern int mnt_table_merge_utab(struct libmnt_table *tb, + struct libmnt_table *u_tb); extern struct libmnt_fs *mnt_table_get_fs_root(struct libmnt_table *tb, struct libmnt_fs *fs, @@ -336,6 +338,7 @@ struct libmnt_table { struct libmnt_statmnt *stmnt; /* statmount() stuff */ int noautofs; /* ignore autofs mounts */ + int nouseropts; /* do not merge utab */ struct list_head ents; /* list of entries (libmnt_fs) */ void *userdata; diff --git a/libmount/src/tab_listmount.c b/libmount/src/tab_listmount.c index dbbc2b8f6..e2c7508fe 100644 --- a/libmount/src/tab_listmount.c +++ b/libmount/src/tab_listmount.c @@ -408,6 +408,10 @@ int mnt_table_fetch_listmount(struct libmnt_table *tb) * have all the necessary data (or on error) */ tb->lsmnt->done = 1; + /* merge userspace mount options from utab */ + if (rc == 0) + rc = mnt_table_merge_utab(tb, NULL); + /* restore */ if (tb->stmnt) mnt_statmnt_disable_fetching(tb->stmnt, stmnt_status); diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c index 5077e9a35..c21d5d019 100644 --- a/libmount/src/tab_parse.c +++ b/libmount/src/tab_parse.c @@ -1108,6 +1108,27 @@ int mnt_table_is_noautofs(struct libmnt_table *tb) return tb ? tb->noautofs : 0; } +/** + * mnt_table_disable_useropts: + * @tb: table + * @disable: 1 to disable, 0 to enable + * + * Disable or enable merging of userspace mount options from utab when + * populating the mount table. This applies to both mountinfo and + * listmount-based table sources. + * + * Returns: 0 on success, <0 on error. + * + * Since: 2.43 + */ +int mnt_table_disable_useropts(struct libmnt_table *tb, int disable) +{ + if (!tb) + return -EINVAL; + tb->nouseropts = disable ? 1 : 0; + return 0; +} + /** * mnt_table_parse_swaps: * @tb: table @@ -1231,7 +1252,9 @@ static struct libmnt_fs *mnt_table_merge_user_fs(struct libmnt_table *tb, struct if (fs) { DBG_OBJ(TAB, tb, ul_debug(" found")); - mnt_fs_append_options(fs, optstr); + mnt_optstr_append_option(&fs->user_optstr, optstr, NULL); + free(fs->optstr); + fs->optstr = NULL; mnt_fs_append_attributes(fs, attrs); mnt_fs_set_bindsrc(fs, mnt_fs_get_bindsrc(uf)); fs->flags |= MNT_FS_MERGED; @@ -1241,45 +1264,22 @@ static struct libmnt_fs *mnt_table_merge_user_fs(struct libmnt_table *tb, struct return fs; } -/* default filename is /proc/self/mountinfo +/* + * Read utab and merge userspace options into the mount table @tb. + * If @u_tb is provided, use it as utab; otherwise read from + * /run/mount/utab. */ -int __mnt_table_parse_mountinfo(struct libmnt_table *tb, const char *filename, - struct libmnt_table *u_tb) +int mnt_table_merge_utab(struct libmnt_table *tb, struct libmnt_table *u_tb) { int rc = 0, priv_utab = 0; - int explicit_file = filename ? 1 : 0; assert(tb); - if (filename) - DBG_OBJ(TAB, tb, ul_debug("%s requested as mount table", filename)); - - if (!filename || strcmp(filename, _PATH_PROC_MOUNTINFO) == 0) { - filename = _PATH_PROC_MOUNTINFO; - tb->fmt = MNT_FMT_MOUNTINFO; - DBG_OBJ(TAB, tb, ul_debug("mountinfo parse: #1 read mountinfo")); - } else - tb->fmt = MNT_FMT_GUESS; - - rc = mnt_table_parse_file(tb, filename); - if (rc) { - if (explicit_file) - return rc; - - /* hmm, old kernel? ...try /proc/mounts */ - tb->fmt = MNT_FMT_MTAB; - return mnt_table_parse_file(tb, _PATH_PROC_MOUNTS); - } - - if (!is_mountinfo(tb)) + if (tb->nouseropts) return 0; - DBG_OBJ(TAB, tb, ul_debug("mountinfo parse: #2 read utab")); - if (mnt_table_get_nents(tb) == 0) - return 0; /* empty, ignore utab */ - /* - * try to read the user specific information from /run/mount/utabs - */ + return 0; + if (!u_tb) { const char *utab = mnt_get_utab_path(); @@ -1297,7 +1297,7 @@ int __mnt_table_parse_mountinfo(struct libmnt_table *tb, const char *filename, priv_utab = 1; } - DBG_OBJ(TAB, tb, ul_debug("mountinfo parse: #3 merge utab")); + DBG_OBJ(TAB, tb, ul_debug("merging utab")); if (rc == 0) { struct libmnt_fs *u_fs; @@ -1305,16 +1305,52 @@ int __mnt_table_parse_mountinfo(struct libmnt_table *tb, const char *filename, mnt_reset_iter(&itr, MNT_ITER_BACKWARD); - /* merge user options into mountinfo from the kernel */ - while(mnt_table_next_fs(u_tb, &itr, &u_fs) == 0) + while (mnt_table_next_fs(u_tb, &itr, &u_fs) == 0) mnt_table_merge_user_fs(tb, u_fs); } - if (priv_utab) mnt_unref_table(u_tb); return 0; } + +/* default filename is /proc/self/mountinfo + */ +int __mnt_table_parse_mountinfo(struct libmnt_table *tb, const char *filename, + struct libmnt_table *u_tb) +{ + int rc = 0; + int explicit_file = filename ? 1 : 0; + + assert(tb); + + if (filename) + DBG_OBJ(TAB, tb, ul_debug("%s requested as mount table", filename)); + + if (!filename || strcmp(filename, _PATH_PROC_MOUNTINFO) == 0) { + filename = _PATH_PROC_MOUNTINFO; + tb->fmt = MNT_FMT_MOUNTINFO; + DBG_OBJ(TAB, tb, ul_debug("mountinfo parse: #1 read mountinfo")); + } else + tb->fmt = MNT_FMT_GUESS; + + rc = mnt_table_parse_file(tb, filename); + if (rc) { + if (explicit_file) + return rc; + + /* hmm, old kernel? ...try /proc/mounts */ + tb->fmt = MNT_FMT_MTAB; + return mnt_table_parse_file(tb, _PATH_PROC_MOUNTS); + } + + if (!is_mountinfo(tb)) + return 0; + + DBG_OBJ(TAB, tb, ul_debug("mountinfo parse: #2 merge utab")); + return mnt_table_merge_utab(tb, u_tb); +} + /** * mnt_table_parse_mtab: * @tb: table diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index c892bf299..93c6192fc 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -1108,6 +1108,7 @@ static struct libmnt_table *fetch_listmount(struct findmnt *findmnt) mnt_table_set_userdata(tb, findmnt); mnt_table_refer_statmnt(tb, sm); + mnt_table_disable_useropts(tb, 1); if (mnt_table_fetch_listmount(tb) != 0) { warn(_("failed to fetch mount nodes"));