summaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_dir.c
diff options
context:
space:
mode:
authorAlex Zhuravlev <[email protected]>2018-01-08 10:57:47 -0800
committerBrian Behlendorf <[email protected]>2018-01-09 16:16:07 -0800
commit3910184d9ecf187f5f229798bab688d754fa1e30 (patch)
tree4d1d0a9f6352c93dc33ff55dc70b03ae701552e5 /module/zfs/zfs_dir.c
parentcba6fc61a2898395c47380a0c2303f19842a2ff0 (diff)
Use zap_count instead of cached z_size for unlink
As a performance optimization Lustre does not strictly update the SA_ZPL_SIZE when adding/removing from non-directory entries. This results in entries which cannot be removed through the ZPL layer even though the ZAP is empty and safe to remove. Resolve this issue by checking the zap_count() directly instead on relying on the cached SA_ZPL_SIZE. Micro-benchmarks show no significant performance impact due to the additional overhead of using zap_count(). Reviewed-by: Olaf Faaland <[email protected]> Reviewed-by: Giuseppe Di Natale <[email protected]> Signed-off-by: Alex Zhuravlev <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #7019
Diffstat (limited to 'module/zfs/zfs_dir.c')
-rw-r--r--module/zfs/zfs_dir.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/module/zfs/zfs_dir.c b/module/zfs/zfs_dir.c
index c6ee30291..9a8bbccd9 100644
--- a/module/zfs/zfs_dir.c
+++ b/module/zfs/zfs_dir.c
@@ -977,11 +977,25 @@ zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag,
* Indicate whether the directory is empty. Works with or without z_lock
* held, but can only be consider a hint in the latter case. Returns true
* if only "." and ".." remain and there's no work in progress.
+ *
+ * The internal ZAP size, rather than zp->z_size, needs to be checked since
+ * some consumers (Lustre) do not strictly maintain an accurate SA_ZPL_SIZE.
*/
boolean_t
zfs_dirempty(znode_t *dzp)
{
- return (dzp->z_size == 2 && dzp->z_dirlocks == 0);
+ zfsvfs_t *zfsvfs = ZTOZSB(dzp);
+ uint64_t count;
+ int error;
+
+ if (dzp->z_dirlocks != NULL)
+ return (B_FALSE);
+
+ error = zap_count(zfsvfs->z_os, dzp->z_id, &count);
+ if (error != 0 || count != 0)
+ return (B_FALSE);
+
+ return (B_TRUE);
}
int