Fix fail path in zfs_znode_alloc

When sa_bulk_lookup() fails, unlock_new_inode() will spit out a WARNING. It
will also recursive deadlock on ZFS_OBJ_HOLD_ENTER in zfs_zinactive().

Since we never call insert_inode_locked in fail path, I_NEW is never set, the
inode is never hashed. So unlock_new_inode() can be safely remove it.

We set z_sa_hdl to NULL in fail path so that iput path will stop at
zfs_inactive() without entering zfs_zinactive(). This way we can avoid the
deadlock and prevent double sa_handle_destroy().

Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #3899
This commit is contained in:
Chunwei Chen 2015-10-09 12:27:01 -07:00 committed by Brian Behlendorf
parent aa159afb56
commit 07d63f0cb9

View File

@ -410,7 +410,7 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) { if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) {
if (hdl == NULL) if (hdl == NULL)
sa_handle_destroy(zp->z_sa_hdl); sa_handle_destroy(zp->z_sa_hdl);
zp->z_sa_hdl = NULL;
goto error; goto error;
} }
@ -448,7 +448,6 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
return (zp); return (zp);
error: error:
unlock_new_inode(ip);
iput(ip); iput(ip);
return (NULL); return (NULL);
} }