3
0
forked from pool/util-linux
util-linux/0001-libmount-fix-sync-options-between-context-and-fs-str.patch
Jan Engelhardt ae5a1c3844 Accepting request 1094801 from home:favogt:branches:Base:System
- Add patch to fix regression with mount options handling (gh#util-linux/util-linux#2326):
  * 0001-libmount-fix-sync-options-between-context-and-fs-str.patch

- Set --disable-libmount-mountfd-support, it's very broken and needs
  both util-linux and kernel fixes (gh#util-linux/util-linux#2287)

OBS-URL: https://build.opensuse.org/request/show/1094801
OBS-URL: https://build.opensuse.org/package/show/Base:System/util-linux?expand=0&rev=516
2023-06-23 09:44:19 +00:00

214 lines
5.3 KiB
Diff

From 7b37d5b5667103beac16f7ae3cca5feaf00a21b0 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 22 Jun 2023 13:11:57 +0200
Subject: [PATCH] libmount: fix sync options between context and fs structs
Since v2.39 libmount prefers "struct libmnt_optlist" to keep mount options
rather than the original "struct libmnt_fs". This is problem if the
"fs" struct is defined and maintained outside the context.
The library has already a way how to sync "fs" and "optlist", but this
needs to be improved and used more widely. Changes:
* force "fs" from context to always read options from "optlist"
* copy options from "fs" to "optlist" in mnt_context_set_fs()
* internally redirect mnt_fs_* API for options to "optlist" if optlist
defined
* add simple test to make sure options from different sources are
always merged together
Addresses: https://github.com/util-linux/util-linux/issues/2326
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/context.c | 82 ++++++++++++++++++++++++++++++++++++++++--
libmount/src/fs.c | 23 +++++++++---
2 files changed, 97 insertions(+), 8 deletions(-)
diff --git a/libmount/src/context.c b/libmount/src/context.c
index 4c5e65659..0cd320190 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -911,9 +911,29 @@ int mnt_context_set_fs(struct libmnt_context *cxt, struct libmnt_fs *fs)
if (!cxt)
return -EINVAL;
+ if (cxt->fs == fs)
+ return 0;
+
DBG(CXT, ul_debugobj(cxt, "setting new FS"));
- mnt_ref_fs(fs); /* new */
- mnt_unref_fs(cxt->fs); /* old */
+
+ /* new */
+ if (fs) {
+ struct libmnt_optlist *ol = mnt_context_get_optlist(cxt);
+
+ if (!ol)
+ return -ENOMEM;
+
+ mnt_ref_fs(fs);
+
+ mnt_optlist_set_optstr(ol, mnt_fs_get_options(fs), NULL);
+ mnt_fs_follow_optlist(fs, ol);
+ }
+
+ /* old */
+ if (cxt->fs)
+ mnt_fs_follow_optlist(cxt->fs, NULL);
+ mnt_unref_fs(cxt->fs);
+
cxt->fs = fs;
return 0;
}
@@ -932,8 +952,17 @@ struct libmnt_fs *mnt_context_get_fs(struct libmnt_context *cxt)
{
if (!cxt)
return NULL;
- if (!cxt->fs)
+ if (!cxt->fs) {
+ struct libmnt_optlist *ol = mnt_context_get_optlist(cxt);
+
+ if (!ol)
+ return NULL;
cxt->fs = mnt_new_fs();
+ if (!cxt->fs)
+ return NULL;
+
+ mnt_fs_follow_optlist(cxt->fs, ol);
+ }
return cxt->fs;
}
@@ -3314,6 +3343,50 @@ static int test_flags(struct libmnt_test *ts, int argc, char *argv[])
return rc;
}
+static int test_cxtsync(struct libmnt_test *ts, int argc, char *argv[])
+{
+ struct libmnt_context *cxt;
+ struct libmnt_fs *fs;
+ unsigned long flags = 0;
+ int rc;
+
+ if (argc != 4)
+ return -EINVAL;
+
+ fs = mnt_new_fs();
+ if (!fs)
+ return -ENOMEM;
+
+ rc = mnt_fs_set_options(fs, argv[1]);
+ if (rc)
+ return rc;
+
+ cxt = mnt_new_context();
+ if (!cxt)
+ return -ENOMEM;
+
+ rc = mnt_context_set_fs(cxt, fs);
+ if (rc)
+ return rc;
+
+ rc = mnt_context_append_options(cxt, argv[2]);
+ if (rc)
+ return rc;
+
+ rc = mnt_fs_append_options(fs, argv[3]);
+ if (rc)
+ return rc;
+
+ mnt_context_get_mflags(cxt, &flags);
+
+ printf(" fs options: %s\n", mnt_fs_get_options(fs));
+ printf("context options: %s\n", mnt_context_get_options(cxt));
+ printf(" context mflags: %08lx\n", flags);
+
+ mnt_free_context(cxt);
+ return 0;
+}
+
static int test_mountall(struct libmnt_test *ts, int argc, char *argv[])
{
struct libmnt_context *cxt;
@@ -3361,6 +3434,8 @@ static int test_mountall(struct libmnt_test *ts, int argc, char *argv[])
return 0;
}
+
+
int main(int argc, char *argv[])
{
struct libmnt_test tss[] = {
@@ -3368,6 +3443,7 @@ int main(int argc, char *argv[])
{ "--umount", test_umount, "[-t <type>] [-f][-l][-r] <src>|<target>" },
{ "--mount-all", test_mountall, "[-O <pattern>] [-t <pattern] mount all filesystems from fstab" },
{ "--flags", test_flags, "[-o <opts>] <spec>" },
+ { "--cxtsync", test_cxtsync, "<fsopts> <cxtopts> <fsopts>" },
{ "--search-helper", test_search_helper, "<fstype>" },
{ NULL }};
diff --git a/libmount/src/fs.c b/libmount/src/fs.c
index 655f07171..79e32a170 100644
--- a/libmount/src/fs.c
+++ b/libmount/src/fs.c
@@ -228,10 +228,14 @@ int mnt_fs_follow_optlist(struct libmnt_fs *fs, struct libmnt_optlist *ol)
if (fs->optlist == ol)
return 0;
+ if (fs->optlist)
+ mnt_unref_optlist(fs->optlist);
fs->opts_age = 0;
fs->optlist = ol;
- mnt_ref_optlist(ol);
+
+ if (ol)
+ mnt_ref_optlist(ol);
return 0;
}
@@ -919,7 +923,11 @@ int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr)
if (!fs)
return -EINVAL;
- fs->opts_age = 0;
+
+ if (fs->optlist) {
+ fs->opts_age = 0;
+ return mnt_optlist_set_optstr(fs->optlist, optstr, NULL);
+ }
if (optstr) {
int rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
@@ -968,8 +976,10 @@ int mnt_fs_append_options(struct libmnt_fs *fs, const char *optstr)
return -EINVAL;
if (!optstr)
return 0;
-
- fs->opts_age = 0;
+ if (fs->optlist) {
+ fs->opts_age = 0;
+ return mnt_optlist_append_optstr(fs->optlist, optstr, NULL);
+ }
rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
if (rc)
@@ -1013,7 +1023,10 @@ int mnt_fs_prepend_options(struct libmnt_fs *fs, const char *optstr)
if (!optstr)
return 0;
- fs->opts_age = 0;
+ if (fs->optlist) {
+ fs->opts_age = 0;
+ return mnt_optlist_prepend_optstr(fs->optlist, optstr, NULL);
+ }
rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
if (rc)
--
2.41.0