svn commit: r332754 - in stable/10: sbin/mount sys/kern
Andriy Gapon
avg at FreeBSD.org
Thu Apr 19 05:52:48 UTC 2018
Author: avg
Date: Thu Apr 19 05:52:47 2018
New Revision: 332754
URL: https://svnweb.freebsd.org/changeset/base/332754
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.
stable/10 note: this branch does not have SYSCTL_BOOL, so SYSCTL_INT is
used instead.
Relnotes: yes
Modified:
stable/10/sbin/mount/mount.8
stable/10/sys/kern/vfs_mount.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sbin/mount/mount.8
==============================================================================
--- stable/10/sbin/mount/mount.8 Thu Apr 19 05:37:32 2018 (r332753)
+++ stable/10/sbin/mount/mount.8 Thu Apr 19 05:52:47 2018 (r332754)
@@ -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/10/sys/kern/vfs_mount.c
==============================================================================
--- stable/10/sys/kern/vfs_mount.c Thu Apr 19 05:37:32 2018 (r332753)
+++ stable/10/sys/kern/vfs_mount.c Thu Apr 19 05:52:47 2018 (r332754)
@@ -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 int default_autoro = false;
+SYSCTL_INT(_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");
static uma_zone_t mount_zone;
@@ -532,6 +536,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)
{
@@ -539,10 +568,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)
@@ -634,17 +665,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)
@@ -668,6 +710,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)
More information about the svn-src-stable
mailing list