Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Aug 2015 13:18:14 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r287107 - in head/sys: kern sys
Message-ID:  <201508241318.t7ODIEiL039798@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trasz
Date: Mon Aug 24 13:18:13 2015
New Revision: 287107
URL: https://svnweb.freebsd.org/changeset/base/287107

Log:
  Make vfs_unmountall() unmount /dev after /, not before.  The only
  reason this didn't result in an unclean shutdown is that devfs ignores
  MNT_FORCE flag.
  
  Reviewed by:	kib@
  MFC after:	1 month
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D3467

Modified:
  head/sys/kern/vfs_mount.c
  head/sys/kern/vfs_mountroot.c
  head/sys/kern/vfs_subr.c
  head/sys/sys/vnode.h

Modified: head/sys/kern/vfs_mount.c
==============================================================================
--- head/sys/kern/vfs_mount.c	Mon Aug 24 12:17:15 2015	(r287106)
+++ head/sys/kern/vfs_mount.c	Mon Aug 24 13:18:13 2015	(r287107)
@@ -1359,6 +1359,8 @@ dounmount(struct mount *mp, int flags, s
 		vput(coveredvp);
 	}
 	vfs_event_signal(NULL, VQ_UNMOUNT, 0);
+	if (mp == rootdevmp)
+		rootdevmp = NULL;
 	vfs_mount_destroy(mp);
 	return (0);
 }

Modified: head/sys/kern/vfs_mountroot.c
==============================================================================
--- head/sys/kern/vfs_mountroot.c	Mon Aug 24 12:17:15 2015	(r287106)
+++ head/sys/kern/vfs_mountroot.c	Mon Aug 24 13:18:13 2015	(r287107)
@@ -95,6 +95,11 @@ static struct mntarg *parse_mountroot_op
  */
 struct vnode *rootvnode;
 
+/*
+ * Mount of the system's /dev.
+ */
+struct mount *rootdevmp;
+
 char *rootdevnames[2] = {NULL, NULL};
 
 struct mtx root_holds_mtx;
@@ -236,6 +241,7 @@ vfs_mountroot_devfs(struct thread *td, s
 	mtx_unlock(&mountlist_mtx);
 
 	*mpp = mp;
+	rootdevmp = mp;
 	set_rootvnode();
 
 	error = kern_symlinkat(td, "/", AT_FDCWD, "dev", UIO_SYSSPACE);

Modified: head/sys/kern/vfs_subr.c
==============================================================================
--- head/sys/kern/vfs_subr.c	Mon Aug 24 12:17:15 2015	(r287106)
+++ head/sys/kern/vfs_subr.c	Mon Aug 24 13:18:13 2015	(r287107)
@@ -3543,6 +3543,21 @@ SYSCTL_PROC(_kern, KERN_VNODE, vnode, CT
     "");
 #endif
 
+static void
+unmount_or_warn(struct mount *mp)
+{
+	int error;
+
+	error = dounmount(mp, MNT_FORCE, curthread);
+	if (error != 0) {
+		printf("unmount of %s failed (", mp->mnt_stat.f_mntonname);
+		if (error == EBUSY)
+			printf("BUSY)\n");
+		else
+			printf("%d)\n", error);
+	}
+}
+
 /*
  * Unmount all filesystems. The list is traversed in reverse order
  * of mounting to avoid dependencies.
@@ -3550,42 +3565,28 @@ SYSCTL_PROC(_kern, KERN_VNODE, vnode, CT
 void
 vfs_unmountall(void)
 {
-	struct mount *mp;
-	struct thread *td;
-	int error;
+	struct mount *mp, *tmp;
 
 	CTR1(KTR_VFS, "%s: unmounting all filesystems", __func__);
-	td = curthread;
 
 	/*
 	 * Since this only runs when rebooting, it is not interlocked.
 	 */
-	while(!TAILQ_EMPTY(&mountlist)) {
-		mp = TAILQ_LAST(&mountlist, mntlist);
+	TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, tmp) {
 		vfs_ref(mp);
-		error = dounmount(mp, MNT_FORCE, td);
-		if (error != 0) {
-			TAILQ_REMOVE(&mountlist, mp, mnt_list);
-			/*
-			 * XXX: Due to the way in which we mount the root
-			 * file system off of devfs, devfs will generate a
-			 * "busy" warning when we try to unmount it before
-			 * the root.  Don't print a warning as a result in
-			 * order to avoid false positive errors that may
-			 * cause needless upset.
-			 */
-			if (strcmp(mp->mnt_vfc->vfc_name, "devfs") != 0) {
-				printf("unmount of %s failed (",
-				    mp->mnt_stat.f_mntonname);
-				if (error == EBUSY)
-					printf("BUSY)\n");
-				else
-					printf("%d)\n", error);
-			}
-		} else {
-			/* The unmount has removed mp from the mountlist */
-		}
+
+		/*
+		 * Forcibly unmounting "/dev" before "/" would prevent clean
+		 * unmount of the latter.
+		 */
+		if (mp == rootdevmp)
+			continue;
+
+		unmount_or_warn(mp);
 	}
+
+	if (rootdevmp != NULL)
+		unmount_or_warn(rootdevmp);
 }
 
 /*

Modified: head/sys/sys/vnode.h
==============================================================================
--- head/sys/sys/vnode.h	Mon Aug 24 12:17:15 2015	(r287106)
+++ head/sys/sys/vnode.h	Mon Aug 24 13:18:13 2015	(r287107)
@@ -420,6 +420,7 @@ extern int		vttoif_tab[];
  * Global vnode data.
  */
 extern	struct vnode *rootvnode;	/* root (i.e. "/") vnode */
+extern	struct mount *rootdevmp;	/* "/dev" mount */
 extern	int async_io_version;		/* 0 or POSIX version of AIO i'face */
 extern	int desiredvnodes;		/* number of vnodes desired */
 extern	struct uma_zone *namei_zone;



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