diff options
author | Mauricio Faria de Oliveira <[email protected]> | 2019-11-21 17:24:03 -0300 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-11-21 12:24:03 -0800 |
commit | 0c46813805f428038f0f5e2541cdab8034c2f082 (patch) | |
tree | 54cc29245658bd7ec8842ffa959e8d516aa16efd /module/os | |
parent | da92d5cbb38cea3a860b8a6bb8ee21f9129e7d7c (diff) |
Check for unlinked znodes after igrab()
The changes in commit 41e1aa2a / PR #9583 introduced a regression on
tmpfile_001_pos: fsetxattr() on a O_TMPFILE file descriptor started
to fail with errno ENODATA:
openat(AT_FDCWD, "/test", O_RDWR|O_TMPFILE, 0666) = 3
<...>
fsetxattr(3, "user.test", <...>, 64, 0) = -1 ENODATA
The originally proposed change on PR #9583 is not susceptible to it,
so just move the code/if-checks around back in that way, to fix it.
Reviewed-by: Pavel Snajdr <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Original-patch-by: Heitor Alves de Siqueira <[email protected]>
Signed-off-by: Mauricio Faria de Oliveira <[email protected]>
Closes #9602
Diffstat (limited to 'module/os')
-rw-r--r-- | module/os/linux/zfs/zfs_znode.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c index 53ba1f63e..a476e58dd 100644 --- a/module/os/linux/zfs/zfs_znode.c +++ b/module/os/linux/zfs/zfs_znode.c @@ -1094,7 +1094,8 @@ again: ASSERT3U(zp->z_id, ==, obj_num); /* * If zp->z_unlinked is set, the znode is already marked - * for deletion and should not be discovered. + * for deletion and should not be discovered. Check this + * after checking igrab() due to fsetxattr() & O_TMPFILE. * * If igrab() returns NULL the VFS has independently * determined the inode should be evicted and has @@ -1109,10 +1110,11 @@ again: * need to detect the active SA hold thereby informing * the VFS that this inode should not be evicted. */ - if (zp->z_unlinked) { - err = SET_ERROR(ENOENT); - } else if (igrab(ZTOI(zp)) == NULL) { - err = SET_ERROR(EAGAIN); + if (igrab(ZTOI(zp)) == NULL) { + if (zp->z_unlinked) + err = SET_ERROR(ENOENT); + else + err = SET_ERROR(EAGAIN); } else { *zpp = zp; err = 0; |