Break out of zfs_zget early if unlinked znode
If zp->z_unlinked is set, we're working with a znode that has been marked for deletion. If that's the case, we can skip the "goto again" loop and return ENOENT, as the znode should not be discovered. Reviewed-by: Richard Yao <ryao@gentoo.org> Reviewed-by: Matt Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Heitor Alves de Siqueira <halves@canonical.com> Closes #9583
This commit is contained in:
parent
cc1a1e17d9
commit
41e1aa2a06
|
@ -1094,6 +1094,9 @@ again:
|
|||
mutex_enter(&zp->z_lock);
|
||||
ASSERT3U(zp->z_id, ==, obj_num);
|
||||
/*
|
||||
* If zp->z_unlinked is set, the znode is already marked
|
||||
* for deletion and should not be discovered.
|
||||
*
|
||||
* If igrab() returns NULL the VFS has independently
|
||||
* determined the inode should be evicted and has
|
||||
* called iput_final() to start the eviction process.
|
||||
|
@ -1107,19 +1110,24 @@ again:
|
|||
* need to detect the active SA hold thereby informing
|
||||
* the VFS that this inode should not be evicted.
|
||||
*/
|
||||
if (igrab(ZTOI(zp)) == NULL) {
|
||||
mutex_exit(&zp->z_lock);
|
||||
sa_buf_rele(db, NULL);
|
||||
zfs_znode_hold_exit(zfsvfs, zh);
|
||||
if (zp->z_unlinked) {
|
||||
err = SET_ERROR(ENOENT);
|
||||
} else if (igrab(ZTOI(zp)) == NULL) {
|
||||
err = SET_ERROR(EAGAIN);
|
||||
} else {
|
||||
*zpp = zp;
|
||||
err = 0;
|
||||
}
|
||||
|
||||
mutex_exit(&zp->z_lock);
|
||||
sa_buf_rele(db, NULL);
|
||||
zfs_znode_hold_exit(zfsvfs, zh);
|
||||
|
||||
if (err == EAGAIN) {
|
||||
/* inode might need this to finish evict */
|
||||
cond_resched();
|
||||
goto again;
|
||||
}
|
||||
*zpp = zp;
|
||||
err = 0;
|
||||
mutex_exit(&zp->z_lock);
|
||||
sa_buf_rele(db, NULL);
|
||||
zfs_znode_hold_exit(zfsvfs, zh);
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue