svn commit: r302388 - in head: sbin/umount sys/kern sys/sys usr.sbin/autofs

Edward Tomasz Napierala trasz at FreeBSD.org
Thu Jul 7 09:03:58 UTC 2016


Author: trasz
Date: Thu Jul  7 09:03:57 2016
New Revision: 302388
URL: https://svnweb.freebsd.org/changeset/base/302388

Log:
  Add new unmount(2) flag, MNT_NONBUSY, to check whether there are
  any open vnodes before proceeding. Make autounmound(8) use this flag.
  Without it, even an unsuccessfull unmount causes filesystem flush,
  which interferes with normal operation.
  
  Reviewed by:	kib@
  Approved by:	re (gjb@)
  MFC after:	1 month
  Differential Revision:	https://reviews.freebsd.org/D7047

Modified:
  head/sbin/umount/umount.8
  head/sbin/umount/umount.c
  head/sys/kern/vfs_mount.c
  head/sys/sys/mount.h
  head/usr.sbin/autofs/autounmountd.c

Modified: head/sbin/umount/umount.8
==============================================================================
--- head/sbin/umount/umount.8	Thu Jul  7 05:47:42 2016	(r302387)
+++ head/sbin/umount/umount.8	Thu Jul  7 09:03:57 2016	(r302388)
@@ -28,7 +28,7 @@
 .\"     @(#)umount.8	8.2 (Berkeley) 5/8/95
 .\" $FreeBSD$
 .\"
-.Dd June 17, 2015
+.Dd July 7, 2016
 .Dt UMOUNT 8
 .Os
 .Sh NAME
@@ -36,12 +36,12 @@
 .Nd unmount file systems
 .Sh SYNOPSIS
 .Nm
-.Op Fl fv
+.Op Fl fnv
 .Ar special ... | node ... | fsid ...
 .Nm
 .Fl a | A
 .Op Fl F Ar fstab
-.Op Fl fv
+.Op Fl fnv
 .Op Fl h Ar host
 .Op Fl t Ar type
 .Sh DESCRIPTION
@@ -94,6 +94,15 @@ option and, unless otherwise specified w
 option, will only unmount
 .Tn NFS
 file systems.
+.It Fl n
+Unless the
+.Fl f
+is used, the
+.Nm
+will not unmount an active file system.
+It will, however, perform a flush.
+This flag disables this behaviour, preventing the flush
+if there are any files open.
 .It Fl t Ar type
 Is used to indicate the actions should only be taken on
 file systems of the specified type.

Modified: head/sbin/umount/umount.c
==============================================================================
--- head/sbin/umount/umount.c	Thu Jul  7 05:47:42 2016	(r302387)
+++ head/sbin/umount/umount.c	Thu Jul  7 09:03:57 2016	(r302388)
@@ -91,7 +91,7 @@ main(int argc, char *argv[])
 	struct addrinfo hints;
 
 	all = errs = 0;
-	while ((ch = getopt(argc, argv, "AaF:fh:t:v")) != -1)
+	while ((ch = getopt(argc, argv, "AaF:fh:nt:v")) != -1)
 		switch (ch) {
 		case 'A':
 			all = 2;
@@ -103,12 +103,15 @@ main(int argc, char *argv[])
 			setfstab(optarg);
 			break;
 		case 'f':
-			fflag = MNT_FORCE;
+			fflag |= MNT_FORCE;
 			break;
 		case 'h':	/* -h implies -A. */
 			all = 2;
 			nfshost = optarg;
 			break;
+		case 'n':
+			fflag |= MNT_NONBUSY;
+			break;
 		case 't':
 			if (typelist != NULL)
 				err(1, "only one -t option may be specified");
@@ -124,8 +127,11 @@ main(int argc, char *argv[])
 	argc -= optind;
 	argv += optind;
 
+	if ((fflag & MNT_FORCE) != 0 && (fflag & MNT_NONBUSY) != 0)
+		err(1, "-f and -n are mutually exclusive");
+
 	/* Start disks transferring immediately. */
-	if ((fflag & MNT_FORCE) == 0)
+	if ((fflag & (MNT_FORCE | MNT_NONBUSY)) == 0)
 		sync();
 
 	if ((argc == 0 && !all) || (argc != 0 && all))
@@ -609,7 +615,7 @@ usage(void)
 {
 
 	(void)fprintf(stderr, "%s\n%s\n",
-	    "usage: umount [-fv] special ... | node ... | fsid ...",
-	    "       umount -a | -A [-F fstab] [-fv] [-h host] [-t type]");
+	    "usage: umount [-fnv] special ... | node ... | fsid ...",
+	    "       umount -a | -A [-F fstab] [-fnv] [-h host] [-t type]");
 	exit(1);
 }

Modified: head/sys/kern/vfs_mount.c
==============================================================================
--- head/sys/kern/vfs_mount.c	Thu Jul  7 05:47:42 2016	(r302387)
+++ head/sys/kern/vfs_mount.c	Thu Jul  7 09:03:57 2016	(r302388)
@@ -1205,6 +1205,28 @@ sys_unmount(struct thread *td, struct un
 }
 
 /*
+ * Return error if any of the vnodes, ignoring the root vnode
+ * and the syncer vnode, have non-zero usecount.
+ */
+static int
+vfs_check_usecounts(struct mount *mp)
+{
+	struct vnode *vp, *mvp;
+
+	MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
+		if ((vp->v_vflag & VV_ROOT) == 0 && vp->v_type != VNON &&
+		    vp->v_usecount != 0) {
+			VI_UNLOCK(vp);
+			MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
+			return (EBUSY);
+		}
+		VI_UNLOCK(vp);
+	}
+
+	return (0);
+}
+
+/*
  * Do the actual filesystem unmount.
  */
 int
@@ -1260,6 +1282,21 @@ dounmount(struct mount *mp, int flags, s
 		return (EBUSY);
 	}
 	mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
+	if (flags & MNT_NONBUSY) {
+		MNT_IUNLOCK(mp);
+		error = vfs_check_usecounts(mp);
+		MNT_ILOCK(mp);
+		if (error != 0) {
+			mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ);
+			MNT_IUNLOCK(mp);
+			if (coveredvp != NULL) {
+				VOP_UNLOCK(coveredvp, 0);
+				vdrop(coveredvp);
+			}
+			vn_finished_write(mp);
+			return (error);
+		}
+	}
 	/* Allow filesystems to detect that a forced unmount is in progress. */
 	if (flags & MNT_FORCE) {
 		mp->mnt_kern_flag |= MNTK_UNMOUNTF;

Modified: head/sys/sys/mount.h
==============================================================================
--- head/sys/sys/mount.h	Thu Jul  7 05:47:42 2016	(r302387)
+++ head/sys/sys/mount.h	Thu Jul  7 09:03:57 2016	(r302388)
@@ -312,17 +312,21 @@ void          __mnt_vnode_markerfree_act
  * External filesystem command modifier flags.
  * Unmount can use the MNT_FORCE flag.
  * XXX: These are not STATES and really should be somewhere else.
- * XXX: MNT_BYFSID collides with MNT_ACLS, but because MNT_ACLS is only used for
- *      mount(2) and MNT_BYFSID is only used for unmount(2) it's harmless.
+ * XXX: MNT_BYFSID and MNT_NONBUSY collide with MNT_ACLS and MNT_MULTILABEL,
+ *      but because MNT_ACLS and MNT_MULTILABEL are only used for mount(2),
+ *      and MNT_BYFSID and MNT_NONBUSY are only used for unmount(2),
+ *      it's harmless.
  */
 #define	MNT_UPDATE	0x0000000000010000ULL /* not real mount, just update */
 #define	MNT_DELEXPORT	0x0000000000020000ULL /* delete export host lists */
 #define	MNT_RELOAD	0x0000000000040000ULL /* reload filesystem data */
 #define	MNT_FORCE	0x0000000000080000ULL /* force unmount or readonly */
 #define	MNT_SNAPSHOT	0x0000000001000000ULL /* snapshot the filesystem */
+#define	MNT_NONBUSY	0x0000000004000000ULL /* check vnode use counts. */
 #define	MNT_BYFSID	0x0000000008000000ULL /* specify filesystem by ID. */
 #define MNT_CMDFLAGS   (MNT_UPDATE	| MNT_DELEXPORT	| MNT_RELOAD	| \
-			MNT_FORCE	| MNT_SNAPSHOT	| MNT_BYFSID)
+			MNT_FORCE	| MNT_SNAPSHOT	| MNT_NONBUSY	| \
+			MNT_BYFSID)
 /*
  * Internal filesystem control flags stored in mnt_kern_flag.
  *

Modified: head/usr.sbin/autofs/autounmountd.c
==============================================================================
--- head/usr.sbin/autofs/autounmountd.c	Thu Jul  7 05:47:42 2016	(r302387)
+++ head/usr.sbin/autofs/autounmountd.c	Thu Jul  7 09:03:57 2016	(r302388)
@@ -161,7 +161,7 @@ unmount_by_fsid(const fsid_t fsid, const
 	if (ret < 0)
 		log_err(1, "asprintf");
 
-	error = unmount(fsid_str, MNT_BYFSID);
+	error = unmount(fsid_str, MNT_NONBUSY | MNT_BYFSID);
 	if (error != 0) {
 		if (errno == EBUSY) {
 			log_debugx("cannot unmount %s (%s): %s",


More information about the svn-src-head mailing list