svn commit: r368075 - head/sys/kern

Konstantin Belousov kib at FreeBSD.org
Thu Nov 26 18:08:43 UTC 2020


Author: kib
Date: Thu Nov 26 18:08:42 2020
New Revision: 368075
URL: https://svnweb.freebsd.org/changeset/base/368075

Log:
  More careful handling of the mount failure.
  
  - VFS_UNMOUNT() requires vn_start_write() around it [*].
  - call VFS_PURGE() before unmount.
  - do not destroy mp if cleanup unmount did not succeed.
  - set MNTK_UNMOUNT, and indicate forced unmount with MNTK_UNMOUNTF
    for VFS_UNMOUNT() in cleanup.
  
  PR:	251320 [*]
  Reported by:	Tong Zhang <ztong0001 at gmail.com>
  Reviewed by:	markj, mjg
  Discussed with:	rmacklem
  Sponsored by:	The FreeBSD Foundation
  Differential revision:	https://reviews.freebsd.org/D27327

Modified:
  head/sys/kern/vfs_mount.c

Modified: head/sys/kern/vfs_mount.c
==============================================================================
--- head/sys/kern/vfs_mount.c	Thu Nov 26 18:03:24 2020	(r368074)
+++ head/sys/kern/vfs_mount.c	Thu Nov 26 18:08:42 2020	(r368075)
@@ -903,6 +903,7 @@ vfs_domount_first(
 	struct mount *mp;
 	struct vnode *newdp, *rootvp;
 	int error, error1;
+	bool unmounted;
 
 	ASSERT_VOP_ELOCKED(vp, __func__);
 	KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here"));
@@ -964,23 +965,39 @@ vfs_domount_first(
 	 * get.  No freeing of cn_pnbuf.
 	 */
 	error1 = 0;
+	unmounted = true;
 	if ((error = VFS_MOUNT(mp)) != 0 ||
 	    (error1 = VFS_STATFS(mp, &mp->mnt_stat)) != 0 ||
 	    (error1 = VFS_ROOT(mp, LK_EXCLUSIVE, &newdp)) != 0) {
 		rootvp = NULL;
 		if (error1 != 0) {
-			error = error1;
+			MPASS(error == 0);
 			rootvp = vfs_cache_root_clear(mp);
 			if (rootvp != NULL) {
 				vhold(rootvp);
 				vrele(rootvp);
 			}
-			if ((error1 = VFS_UNMOUNT(mp, 0)) != 0)
-				printf("VFS_UNMOUNT returned %d\n", error1);
+			(void)vn_start_write(NULL, &mp, V_WAIT);
+			MNT_ILOCK(mp);
+			mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_UNMOUNTF;
+			MNT_IUNLOCK(mp);
+			VFS_PURGE(mp);
+			error = VFS_UNMOUNT(mp, 0);
+			vn_finished_write(mp);
+			if (error != 0) {
+				printf(
+		    "failed post-mount (%d): rollback unmount returned %d\n",
+				    error1, error);
+				unmounted = false;
+			}
+			error = error1;
 		}
 		vfs_unbusy(mp);
 		mp->mnt_vnodecovered = NULL;
-		vfs_mount_destroy(mp);
+		if (unmounted) {
+			/* XXXKIB wait for mnt_lockref drain? */
+			vfs_mount_destroy(mp);
+		}
 		VI_LOCK(vp);
 		vp->v_iflag &= ~VI_MOUNT;
 		VI_UNLOCK(vp);


More information about the svn-src-all mailing list