Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Apr 2018 05:37:32 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r332753 - in stable/11: sbin/mount sys/kern
Message-ID:  <201804190537.w3J5bW03061999@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Thu Apr 19 05:37:32 2018
New Revision: 332753
URL: https://svnweb.freebsd.org/changeset/base/332753

Log:
  MFC r331616: vfs_donmount: in certain cases try r/o mount if r/w mount fails
  
  If the operation is not an update, if neither r/w nor r/o mode is
  explicitly requested, if the error code hints at the possibility of the
  media being read-only, and if the fallback is allowed, then we can try
  to automatically downgrade to the readonly mode.
  
  This is especially useful for auto-mounting of removable media that
  sometimes can happen to be write-protected.
  
  The fallback to r/o is not enabled by default.  It can be requested on a
  per-mount basis with a new mount option, 'autoro'.  Or it can be
  globally allowed by setting vfs.default_autoro.
  
  Relnotes:	yes

Modified:
  stable/11/sbin/mount/mount.8
  stable/11/sys/kern/vfs_mount.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/mount/mount.8
==============================================================================
--- stable/11/sbin/mount/mount.8	Thu Apr 19 05:06:56 2018	(r332752)
+++ stable/11/sbin/mount/mount.8	Thu Apr 19 05:37:32 2018	(r332753)
@@ -155,6 +155,10 @@ This flag indicates that the file system was mounted b
 .Xr automountd 8 .
 Automounted file systems are automatically unmounted by
 .Xr autounmountd 8 .
+.It Cm autoro
+Mount the file system read-write.
+If that fails with an error that suggests that the media could be read-only,
+then automatically try to mount the file system read-only.
 .It Cm current
 When used with the
 .Fl u

Modified: stable/11/sys/kern/vfs_mount.c
==============================================================================
--- stable/11/sys/kern/vfs_mount.c	Thu Apr 19 05:06:56 2018	(r332752)
+++ stable/11/sys/kern/vfs_mount.c	Thu Apr 19 05:37:32 2018	(r332753)
@@ -78,6 +78,10 @@ static int	usermount = 0;
 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
     "Unprivileged users may mount and unmount file systems");
 
+static bool	default_autoro = false;
+SYSCTL_BOOL(_vfs, OID_AUTO, default_autoro, CTLFLAG_RW, &default_autoro, 0,
+    "Retry failed r/w mount as r/o if no explicit ro/rw option is specified");
+
 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
 MALLOC_DEFINE(M_STATFS, "statfs", "statfs structure");
 static uma_zone_t mount_zone;
@@ -534,6 +538,31 @@ vfs_mount_destroy(struct mount *mp)
 	uma_zfree(mount_zone, mp);
 }
 
+static bool
+vfs_should_downgrade_to_ro_mount(uint64_t fsflags, int error)
+{
+	/* This is an upgrade of an exisiting mount. */
+	if ((fsflags & MNT_UPDATE) != 0)
+		return (false);
+	/* This is already an R/O mount. */
+	if ((fsflags & MNT_RDONLY) != 0)
+		return (false);
+
+	switch (error) {
+	case ENODEV:	/* generic, geom, ... */
+	case EACCES:	/* cam/scsi, ... */
+	case EROFS:	/* md, mmcsd, ... */
+		/*
+		 * These errors can be returned by the storage layer to signal
+		 * that the media is read-only.  No harm in the R/O mount
+		 * attempt if the error was returned for some other reason.
+		 */
+		return (true);
+	default:
+		return (false);
+	}
+}
+
 int
 vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
 {
@@ -541,10 +570,12 @@ vfs_donmount(struct thread *td, uint64_t fsflags, stru
 	struct vfsopt *opt, *tmp_opt;
 	char *fstype, *fspath, *errmsg;
 	int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
+	bool autoro;
 
 	errmsg = fspath = NULL;
 	errmsg_len = fspathlen = 0;
 	errmsg_pos = -1;
+	autoro = default_autoro;
 
 	error = vfs_buildopts(fsoptions, &optlist);
 	if (error)
@@ -636,17 +667,28 @@ vfs_donmount(struct thread *td, uint64_t fsflags, stru
 			free(opt->name, M_MOUNT);
 			opt->name = strdup("nonosymfollow", M_MOUNT);
 		}
-		else if (strcmp(opt->name, "noro") == 0)
+		else if (strcmp(opt->name, "noro") == 0) {
 			fsflags &= ~MNT_RDONLY;
-		else if (strcmp(opt->name, "rw") == 0)
+			autoro = false;
+		}
+		else if (strcmp(opt->name, "rw") == 0) {
 			fsflags &= ~MNT_RDONLY;
-		else if (strcmp(opt->name, "ro") == 0)
+			autoro = false;
+		}
+		else if (strcmp(opt->name, "ro") == 0) {
 			fsflags |= MNT_RDONLY;
+			autoro = false;
+		}
 		else if (strcmp(opt->name, "rdonly") == 0) {
 			free(opt->name, M_MOUNT);
 			opt->name = strdup("ro", M_MOUNT);
 			fsflags |= MNT_RDONLY;
+			autoro = false;
 		}
+		else if (strcmp(opt->name, "autoro") == 0) {
+			vfs_freeopt(optlist, opt);
+			autoro = true;
+		}
 		else if (strcmp(opt->name, "suiddir") == 0)
 			fsflags |= MNT_SUIDDIR;
 		else if (strcmp(opt->name, "sync") == 0)
@@ -670,6 +712,19 @@ vfs_donmount(struct thread *td, uint64_t fsflags, stru
 	}
 
 	error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
+
+	/*
+	 * See if we can mount in the read-only mode if the error code suggests
+	 * that it could be possible and the mount options allow for that.
+	 * Never try it if "[no]{ro|rw}" has been explicitly requested and not
+	 * overridden by "autoro".
+	 */
+	if (autoro && vfs_should_downgrade_to_ro_mount(fsflags, error)) {
+		printf("%s: R/W mount failed, possibly R/O media,"
+		    " trying R/O mount\n", __func__);
+		fsflags |= MNT_RDONLY;
+		error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
+	}
 bail:
 	/* copyout the errmsg */
 	if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804190537.w3J5bW03061999>