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 <ztong0...@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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to