From 54e4a6b145fd6ef943d93e16de748283e687855d Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 20 Jul 2023 12:34:14 +0200
Subject: [PATCH] libmount: use some MS_* flags as superblock flags

The old mount(2) API usually utilizes MS_* flags to set up the VFS
node. However, there are some exceptions like "sync" (MS_SYNCHRONOUS),
where the flag is used (by kernel) for the superblock instead. The new
API addresses this issue, ensuring that these options are used for
fsconfig().

This commit introduces MNT_SUPERBLOCK to identify these options in the
libmount options Linux map, and it enforces the new mount code to
utilize these options for fsconfig(FSCONFIG_SET_FLAG).

Reported-by: Abbink Esger <esger.abbink.ext@siemens.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
 libmount/src/hook_mount.c  | 11 +++++++++--
 libmount/src/libmount.h.in |  1 +
 libmount/src/optmap.c      | 14 +++++++-------
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c
index 77a7bed30..ed4ec349c 100644
--- a/libmount/src/hook_mount.c
+++ b/libmount/src/hook_mount.c
@@ -154,12 +154,19 @@ static int configure_superblock(struct libmnt_context *cxt,
 		const char *name = mnt_opt_get_name(opt);
 		const char *value = mnt_opt_get_value(opt);
 		const struct libmnt_optmap *ent = mnt_opt_get_mapent(opt);
+		const int is_linux = ent && mnt_opt_get_map(opt) == cxt->map_linux;
 
-		if (ent && mnt_opt_get_map(opt) == cxt->map_linux &&
-		    ent->id == MS_RDONLY) {
+		if (is_linux && ent->id == MS_RDONLY) {
+			/* Use ro/rw for superblock (for backward compatibility) */
 			value = NULL;
 			has_rwro = 1;
+
+		} else if (is_linux && ent->mask & MNT_SUPERBLOCK) {
+			/* Use some old MS_* (VFS) flags as superblock flags */
+			;
+
 		} else if (!name || mnt_opt_get_map(opt) || mnt_opt_is_external(opt))
+			/* Ignore VFS flags, userspace and external options */
 			continue;
 
 		rc = fsconfig_set_value(cxt, hs, fd, name, value);
diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in
index f156483b6..06c27047d 100644
--- a/libmount/src/libmount.h.in
+++ b/libmount/src/libmount.h.in
@@ -89,6 +89,7 @@ struct libmnt_optmap
 #define MNT_PREFIX	(1 << 3) /* prefix used for some options (e.g. "x-foo") */
 #define MNT_NOHLPS	(1 << 4) /* don't add the option to mount.<type> helpers command line */
 #define MNT_NOFSTAB	(1 << 5) /* not expected in fstab */
+#define MNT_SUPERBLOCK	(1 << 6) /* MS_* for mount(2), otherwise requires fsconfig() */
 
 /**
  * libmnt_fs:
diff --git a/libmount/src/optmap.c b/libmount/src/optmap.c
index 3a91f30d4..d7569a0f0 100644
--- a/libmount/src/optmap.c
+++ b/libmount/src/optmap.c
@@ -79,10 +79,10 @@ static const struct libmnt_optmap linux_flags_map[] =
    { "dev",      MS_NODEV, MNT_INVERT },      /* interpret device files  */
    { "nodev",    MS_NODEV },                  /* don't interpret devices */
 
-   { "sync",     MS_SYNCHRONOUS },            /* synchronous I/O */
-   { "async",    MS_SYNCHRONOUS, MNT_INVERT },/* asynchronous I/O */
+   { "sync",     MS_SYNCHRONOUS, MNT_SUPERBLOCK },            /* synchronous I/O */
+   { "async",    MS_SYNCHRONOUS, MNT_INVERT | MNT_SUPERBLOCK },/* asynchronous I/O */
 
-   { "dirsync",  MS_DIRSYNC },                /* synchronous directory modifications */
+   { "dirsync",  MS_DIRSYNC, MNT_SUPERBLOCK },/* synchronous directory modifications */
    { "remount",  MS_REMOUNT, MNT_NOMTAB },    /* alter flags of mounted FS */
    { "bind",     MS_BIND },                   /* Remount part of the tree elsewhere */
    { "rbind",    MS_BIND | MS_REC },          /* Idem, plus mounted subtrees */
@@ -95,8 +95,8 @@ static const struct libmnt_optmap linux_flags_map[] =
    { "loud",     MS_SILENT, MNT_INVERT },     /* print out messages. */
 #endif
 #ifdef MS_MANDLOCK
-   { "mand",     MS_MANDLOCK },               /* Allow mandatory locks on this FS */
-   { "nomand",   MS_MANDLOCK, MNT_INVERT },   /* Forbid mandatory locks on this FS */
+   { "mand",     MS_MANDLOCK, MNT_SUPERBLOCK },               /* Allow mandatory locks on this FS */
+   { "nomand",   MS_MANDLOCK, MNT_INVERT | MNT_SUPERBLOCK},   /* Forbid mandatory locks on this FS */
 #endif
 #ifdef MS_NOATIME
    { "atime",    MS_NOATIME, MNT_INVERT },    /* Update access time */
@@ -119,8 +119,8 @@ static const struct libmnt_optmap linux_flags_map[] =
    { "nostrictatime", MS_STRICTATIME, MNT_INVERT }, /* kernel default atime */
 #endif
 #ifdef MS_LAZYTIME
-   { "lazytime", MS_LAZYTIME },               /* Update {a,m,c}time on the in-memory inode only */
-   { "nolazytime", MS_LAZYTIME, MNT_INVERT },
+   { "lazytime", MS_LAZYTIME, MNT_SUPERBLOCK },               /* Update {a,m,c}time on the in-memory inode only */
+   { "nolazytime", MS_LAZYTIME, MNT_INVERT | MNT_SUPERBLOCK },
 #endif
 #ifdef MS_PROPAGATION
    { "unbindable",  MS_UNBINDABLE,          MNT_NOHLPS | MNT_NOMTAB }, /* Unbindable */
-- 
2.33.0

