Author: pjd
Date: Sat Sep 12 19:53:31 2009
New Revision: 197133
URL: http://svn.freebsd.org/changeset/base/197133

Log:
  - Protect reclaim with z_teardown_inactive_lock.
  - Be prepared for dbuf to disappear in zfs_reclaim_complete() and check if
    z_dbuf field is NULL - this might happen in case of rollback or forced
    unmount between zfs_freebsd_reclaim() and zfs_reclaim_complete().
  - On forced unmount wait for all znodes to be destroyed - destruction can be
    done asynchronously via zfs_reclaim_complete().
  
  MFC after:    1 week

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c    Sat Sep 
12 19:45:55 2009        (r197132)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c    Sat Sep 
12 19:53:31 2009        (r197133)
@@ -947,6 +947,18 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolea
                zfsvfs->z_unmounted = B_TRUE;
                rrw_exit(&zfsvfs->z_teardown_lock, FTAG);
                rw_exit(&zfsvfs->z_teardown_inactive_lock);
+
+#ifdef __FreeBSD__
+               /*
+                * Some znodes might not be fully reclaimed, wait for them.
+                */
+               mutex_enter(&zfsvfs->z_znodes_lock);
+               while (list_head(&zfsvfs->z_all_znodes) != NULL) {
+                       msleep(zfsvfs, &zfsvfs->z_znodes_lock, 0,
+                           "zteardown", 0);
+               }
+               mutex_exit(&zfsvfs->z_znodes_lock);
+#endif
        }
 
        /*

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c     Sat Sep 
12 19:45:55 2009        (r197132)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c     Sat Sep 
12 19:53:31 2009        (r197133)
@@ -4343,11 +4343,20 @@ zfs_reclaim_complete(void *arg, int pend
        znode_t *zp = arg;
        zfsvfs_t *zfsvfs = zp->z_zfsvfs;
 
-       ZFS_LOG(1, "zp=%p", zp);
-       ZFS_OBJ_HOLD_ENTER(zfsvfs, zp->z_id);
-       zfs_znode_dmu_fini(zp);
-       ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id);
+       rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER);
+       if (zp->z_dbuf != NULL) {
+               ZFS_OBJ_HOLD_ENTER(zfsvfs, zp->z_id);
+               zfs_znode_dmu_fini(zp);
+               ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id);
+       }
        zfs_znode_free(zp);
+       rw_exit(&zfsvfs->z_teardown_inactive_lock);
+       /*
+        * If the file system is being unmounted, there is a process waiting
+        * for us, wake it up.
+        */
+       if (zfsvfs->z_unmounted)
+               wakeup_one(zfsvfs);
 }
 
 static int
@@ -4359,6 +4368,9 @@ zfs_freebsd_reclaim(ap)
 {
        vnode_t *vp = ap->a_vp;
        znode_t *zp = VTOZ(vp);
+       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+
+       rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER);
 
        ASSERT(zp != NULL);
 
@@ -4377,7 +4389,6 @@ zfs_freebsd_reclaim(ap)
        else if (zp->z_dbuf == NULL)
                zfs_znode_free(zp);
        else /* if (!zp->z_unlinked && zp->z_dbuf != NULL) */ {
-               zfsvfs_t *zfsvfs = zp->z_zfsvfs;
                int locked;
 
                locked = MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)) ? 2 :
@@ -4400,6 +4411,7 @@ zfs_freebsd_reclaim(ap)
        vp->v_data = NULL;
        ASSERT(vp->v_holdcnt >= 1);
        VI_UNLOCK(vp);
+       rw_exit(&zfsvfs->z_teardown_inactive_lock);
        return (0);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to