]> granicus.if.org Git - zfs/commitdiff
Remove incorrect ASSERT in zfs_sb_teardown()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 2 Dec 2013 18:26:21 +0000 (10:26 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 2 Dec 2013 23:58:58 +0000 (15:58 -0800)
As part of zfs_sb_teardown() there is an assertion that all inodes
which are part of the zsb->z_all_znodes list have at least one
reference on them.  This is always true for the standard unmount
case but there are two other cases where it is not strictly true.

* zfs_ioc_rollback() - This is the most common case and it results
  from the fact that we aren't unmounting the filesystem.  During a
  normal unmount the MS_ACTIVE flag will be cleared on the super block
  causing iput_final() to evict the inode when its reference count
  drops to zero.  However, during a rollback MS_ACTIVE remains set
  since we're rolling back a live filesystem and need to preserve the
  existing super block.  This allows inodes with a zero reference count
  to stay in the cache thereby violating the assertion.

* destroy_inode() / zfs_sb_teardown() - There exists a small race
  between dropping the last reference on an inode and removing it from
  the zsb->z_all_znodes list.  This is unlikely to occur but could also
  trigger the assertion which is incorrect.  The inode may safely have
  a zero reference count in this case.

Since allowing a zero reference count on the inode is expected and
safe for both of these cases the simplest thing to do is remove the
ASSERT.  This code is only enabled for default builds so removing
this entirely is a very safe change.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chris Dunlop <chris@onthe.net.au>
Signed-off-by: Tim Chase <tim@chase2k.com>
Closes #1417
Closes #1536

module/zfs/zfs_vfsops.c

index 5c65b964ae0d1c6670d3a658907109970b54d783..2c0e923dc289f1e027b25099d889324874b242c1 100644 (file)
@@ -1144,10 +1144,8 @@ zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting)
        mutex_enter(&zsb->z_znodes_lock);
        for (zp = list_head(&zsb->z_all_znodes); zp != NULL;
            zp = list_next(&zsb->z_all_znodes, zp)) {
-               if (zp->z_sa_hdl) {
-                       ASSERT(atomic_read(&ZTOI(zp)->i_count) > 0);
+               if (zp->z_sa_hdl)
                        zfs_znode_dmu_fini(zp);
-               }
        }
        mutex_exit(&zsb->z_znodes_lock);