From owner-svn-src-stable@freebsd.org Thu Apr 19 05:52:47 2018 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id CC0D5F81D03; Thu, 19 Apr 2018 05:52:47 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 72592707A1; Thu, 19 Apr 2018 05:52:47 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6A55125AB0; Thu, 19 Apr 2018 05:52:47 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w3J5qlfp071829; Thu, 19 Apr 2018 05:52:47 GMT (envelope-from avg@FreeBSD.org) Received: (from avg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w3J5qlnd071827; Thu, 19 Apr 2018 05:52:47 GMT (envelope-from avg@FreeBSD.org) Message-Id: <201804190552.w3J5qlnd071827@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avg set sender to avg@FreeBSD.org using -f From: Andriy Gapon Date: Thu, 19 Apr 2018 05:52:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r332754 - in stable/10: sbin/mount sys/kern X-SVN-Group: stable-10 X-SVN-Commit-Author: avg X-SVN-Commit-Paths: in stable/10: sbin/mount sys/kern X-SVN-Commit-Revision: 332754 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Apr 2018 05:52:48 -0000 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)