diff options
author | Heitor Alves de Siqueira <[email protected]> | 2019-11-15 14:56:05 -0300 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-11-15 09:56:05 -0800 |
commit | 41e1aa2a06f81640c3a3e1a6b12558d95887f662 (patch) | |
tree | 84efbc245240b283f3735f06e831642e536bc542 /module/os | |
parent | cc1a1e17d944fa4111443c41cdab7320061b38fa (diff) |
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 <[email protected]>
Reviewed-by: Matt Ahrens <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Heitor Alves de Siqueira <[email protected]>
Closes #9583
Diffstat (limited to 'module/os')
-rw-r--r-- | module/os/linux/zfs/zfs_znode.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c index ab24d875e..c623d61f7 100644 --- a/module/os/linux/zfs/zfs_znode.c +++ b/module/os/linux/zfs/zfs_znode.c @@ -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); - /* inode might need this to finish evict */ - cond_resched(); - goto again; + if (zp->z_unlinked) { + err = SET_ERROR(ENOENT); + } else if (igrab(ZTOI(zp)) == NULL) { + err = SET_ERROR(EAGAIN); + } else { + *zpp = zp; + err = 0; } - *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; + } return (err); } |