Index: zfs_vfsops.c =================================================================== --- zfs_vfsops.c (revision 248210) +++ zfs_vfsops.c (working copy) @@ -1880,6 +1880,28 @@ return (0); } +/* Undo non-transient changes made by zfs_umount() on failure. */ +static void +zfs_umount_failure(zfsvfs_t *zfsvfs, int fflag, boolean_t dropped) +{ + vnode_t *vp; + + if (!zfsvfs->z_issnap && zfsvfs->z_ctldir == NULL) { + zfsctl_create(zfsvfs); + ASSERT(zfsvfs->z_ctldir != NULL); + } + if (dropped) { + /* restore the zfs_mount() reference if needed */ + VERIFY(VFS_ROOT(zfsvfs->z_vfs, LK_EXCLUSIVE, &vp) == 0); + VOP_UNLOCK(vp, 0); + } + if (fflag & MS_FORCE) { + rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); + zfsvfs->z_unmounted = B_FALSE; + rrw_exit(&zfsvfs->z_teardown_lock, FTAG); + } +} + /*ARGSUSED*/ static int zfs_umount(vfs_t *vfsp, int fflag) @@ -1939,10 +1961,7 @@ */ ret = vflush(vfsp, 1, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); if (ret != 0) { - if (!zfsvfs->z_issnap) { - zfsctl_create(zfsvfs); - ASSERT(zfsvfs->z_ctldir != NULL); - } + zfs_umount_failure(zfsvfs, fflag, /*dropped*/B_FALSE); return (ret); } @@ -1959,12 +1978,16 @@ */ if (zfsvfs->z_ctldir == NULL) { if (vfsp->vfs_count > 1) - return (EBUSY); + ret = EBUSY; } else { if (vfsp->vfs_count > 2 || zfsvfs->z_ctldir->v_count > 1) - return (EBUSY); + ret = EBUSY; } + if (ret) { + zfs_umount_failure(zfsvfs, fflag, /*dropped*/B_TRUE); + return (ret); + } } VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0);