From ebef1f2fb67c102f791c702386c6b8fe5bb8e9ae Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 7 Feb 2017 18:57:50 -0500 Subject: [PATCH] Fix iput() calls within a tx As explicitly stated in section 2 of the 'Programming rules' comments at the top of zfs_vnops.c. If you must call iput() within a tx then use zfs_iput_async(). Move iput() calls after dmu_tx_commit() / dmu_tx_abort when possible. When not possible convert the iput() calls to zfs_iput_async(). Reviewed-by: Don Brady Reviewed-by: Chunwei Chen Reviewed-by: George Melikov Signed-off-by: Brian Behlendorf Closes #5758 --- module/zfs/zfs_vnops.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 384a37fea5..437a63a638 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -1602,13 +1602,13 @@ top: error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { zfs_dirent_unlock(dl); - iput(ip); - if (xzp) - iput(ZTOI(xzp)); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); + iput(ip); + if (xzp) + iput(ZTOI(xzp)); goto top; } #ifdef HAVE_PN_UTILS @@ -1616,6 +1616,9 @@ top: pn_free(realnmp); #endif /* HAVE_PN_UTILS */ dmu_tx_abort(tx); + iput(ip); + if (xzp) + iput(ZTOI(xzp)); ZFS_EXIT(zsb); return (error); } @@ -1944,14 +1947,15 @@ top: rw_exit(&zp->z_parent_lock); rw_exit(&zp->z_name_lock); zfs_dirent_unlock(dl); - iput(ip); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); + iput(ip); goto top; } dmu_tx_abort(tx); + iput(ip); ZFS_EXIT(zsb); return (error); } @@ -3025,8 +3029,6 @@ out: ASSERT(err2 == 0); } - if (attrzp) - iput(ZTOI(attrzp)); if (aclp) zfs_acl_free(aclp); @@ -3037,11 +3039,15 @@ out: if (err) { dmu_tx_abort(tx); + if (attrzp) + iput(ZTOI(attrzp)); if (err == ERESTART) goto top; } else { err2 = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx); dmu_tx_commit(tx); + if (attrzp) + iput(ZTOI(attrzp)); zfs_inode_update(zp); } @@ -3074,7 +3080,7 @@ zfs_rename_unlock(zfs_zlock_t **zlpp) while ((zl = *zlpp) != NULL) { if (zl->zl_znode != NULL) - iput(ZTOI(zl->zl_znode)); + zfs_iput_async(ZTOI(zl->zl_znode)); rw_exit(zl->zl_rwlock); *zlpp = zl->zl_next; kmem_free(zl, sizeof (*zl)); @@ -3411,16 +3417,19 @@ top: if (sdzp == tdzp) rw_exit(&sdzp->z_name_lock); - iput(ZTOI(szp)); - if (tzp) - iput(ZTOI(tzp)); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); + iput(ZTOI(szp)); + if (tzp) + iput(ZTOI(tzp)); goto top; } dmu_tx_abort(tx); + iput(ZTOI(szp)); + if (tzp) + iput(ZTOI(tzp)); ZFS_EXIT(zsb); return (error); }