]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: try read-only mount on write-protected superblock too
authorKarel Zak <kzak@redhat.com>
Tue, 3 Mar 2020 10:39:10 +0000 (11:39 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 3 Mar 2020 10:39:10 +0000 (11:39 +0100)
The classic mount(8) behavior is to try read-only on write-protected devices
if the first mount syscall attempt ends with EACCES.

It seems we can implement this feature also for EBUSY if the same mount source
is already mounted with "ro" superblock option.

The typical use-case is iso image (always read-only) mounted on two places.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1809124
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context_mount.c
sys-utils/mount.8

index 0c4b7657bb86f4624160921c62d46134b70e7ed6..efd70502a761fb17cb7c7b76ae936ee19ff9531b 100644 (file)
@@ -1149,6 +1149,18 @@ static struct libmnt_fs *get_already_mounted_source(struct libmnt_context *cxt)
        return NULL;
 }
 
+/*
+ * Checks if source filesystem superblock is already ro-mounted. Note that we
+ * care about FS superblock as VFS node is irrelevant here.
+ */
+static int is_source_already_rdonly(struct libmnt_context *cxt)
+{
+       struct libmnt_fs *fs = get_already_mounted_source(cxt);
+       const char *opts = fs ? mnt_fs_get_fs_options(fs) : NULL;
+
+       return opts && mnt_optstr_get_option(opts, "ro", NULL, NULL) == 0;
+}
+
 /**
  * mnt_context_finalize_mount:
  * @cxt: context
@@ -1250,11 +1262,14 @@ again:
                rc = mnt_context_update_tabs(cxt);
 
        /*
-        * Read-only device; try mount filesystem read-only
+        * Read-only device or already read-only mounted FS.
+        * Try mount the filesystem read-only.
         */
        if ((rc == -EROFS && !mnt_context_syscall_called(cxt))  /* before syscall; rdonly loopdev */
             || mnt_context_get_syscall_errno(cxt) == EROFS     /* syscall failed with EROFS */
-            || mnt_context_get_syscall_errno(cxt) == EACCES)   /* syscall failed with EACCES */
+            || mnt_context_get_syscall_errno(cxt) == EACCES    /* syscall failed with EACCES */
+            || (mnt_context_get_syscall_errno(cxt) == EBUSY    /* already ro-mounted FS */
+                && is_source_already_rdonly(cxt)))
        {
                unsigned long mflags = 0;
 
@@ -1630,7 +1645,7 @@ int mnt_context_get_mount_excode(
                 * Libmount success && syscall success.
                 */
                if (buf && mnt_context_forced_rdonly(cxt))
-                       snprintf(buf, bufsz, _("WARNING: device write-protected, mounted read-only"));
+                       snprintf(buf, bufsz, _("WARNING: source write-protected, mounted read-only"));
                return MNT_EX_SUCCESS;
        }
 
index 698b0f0115ac7f41a0056170e0dacdd597c0b124..eddf05a2f51a50eb43162cca8287a3ec7c25b310 100644 (file)
@@ -931,12 +931,17 @@ Mount the partition that has the specified
 Verbose mode.
 .TP
 .BR \-w , " \-\-rw" , " \-\-read\-write"
-Mount the filesystem read/write. The read-write is kernel default.  A synonym is
+Mount the filesystem read/write.  The read-write is kernel default and
+.BR mount (8)
+default is to try read-only if the previous mount syscall with read-write flags
+on write-protected devices of filesystems failed.
+.sp
+A synonym is
 .BR "\-o rw" .
 
-Note that specify \fB\-w\fR on command line forces \fBmount\fR command
-to never try read-only mount on write-protected devices. The default is
-try read-only if the previous mount syscall with read-write flags failed.
+Note that specify \fB\-w\fR on command line forces \fBmount\fR command to never
+try read-only mount on write-protected devices or already mounted read-only
+filesystems.
 .TP
 .BR \-V , " \-\-version"
 Display version information and exit.