]> granicus.if.org Git - zfs/commitdiff
xattr dir doesn't get purged during iput
authorChunwei Chen <david.chen@osnexus.com>
Tue, 5 Jul 2016 19:39:47 +0000 (12:39 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 12 Jul 2016 21:04:30 +0000 (14:04 -0700)
We need to set inode->i_nlink to zero so iput will purge it. Without this, it
will get purged during shrink cache or umount, which would likely result in
deadlock due to zfs_zget waiting forever on its children which are in the
dispose_list of the same thread.

Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chris Dunlop <chris@onthe.net.au>
Issue #4359
Issue #3508
Issue #4413
Issue #4827

module/zfs/zfs_dir.c

index bdcb87b942f27cdf6d552dd0d374d1424e14f225..50fa7e2481ecc20393ebc649aefc49d12f1ff1c7 100644 (file)
@@ -594,7 +594,7 @@ zfs_purgedir(znode_t *dzp)
                if (error)
                        skipped += 1;
                dmu_tx_commit(tx);
-
+               set_nlink(ZTOI(xzp), xzp->z_links);
                zfs_iput_async(ZTOI(xzp));
        }
        zap_cursor_fini(&zc);
@@ -695,6 +695,7 @@ zfs_rmnode(znode_t *zp)
                mutex_enter(&xzp->z_lock);
                xzp->z_unlinked = B_TRUE;       /* mark xzp for deletion */
                xzp->z_links = 0;       /* no more links to it */
+               set_nlink(ZTOI(xzp), 0); /* this will let iput purge us */
                VERIFY(0 == sa_update(xzp->z_sa_hdl, SA_ZPL_LINKS(zsb),
                    &xzp->z_links, sizeof (xzp->z_links), tx));
                mutex_exit(&xzp->z_lock);