Skip to content

Commit 797f55e

Browse files
authored
Do not persist user/group/project quota zap objects when unneeded
In the zfs_id_over*quota functions, there is a short-circuit to skip the zap_lookup when the quota zap does not exist. If quotas are never used in a zpool, then the quota zap will never exist. But if user/group/project quotas are ever used, the zap objects will be created and will persist even if the quotas are deleted. The quota zap_lookup in the write path can become a bottleneck for write-heavy small I/O workloads. Before this commit, it was not possible to remove this lookup without creating a new zpool. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Sam Atkinson <[email protected]> Closes #14721
1 parent 57b4098 commit 797f55e

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

module/zfs/zfs_quota.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,18 +347,32 @@ zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
347347
if (*objp == 0) {
348348
*objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA,
349349
DMU_OT_NONE, 0, tx);
350-
VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
350+
VERIFY0(zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
351351
zfs_userquota_prop_prefixes[type], 8, 1, objp, tx));
352352
}
353-
mutex_exit(&zfsvfs->z_lock);
354353

355354
if (quota == 0) {
356355
err = zap_remove(zfsvfs->z_os, *objp, buf, tx);
357356
if (err == ENOENT)
358357
err = 0;
358+
/*
359+
* If the quota contains no more entries after the entry
360+
* was removed, destroy the quota zap and remove the
361+
* reference from zfsvfs. This will save us unnecessary
362+
* zap_lookups for the quota during writes.
363+
*/
364+
uint64_t zap_nentries;
365+
VERIFY0(zap_count(zfsvfs->z_os, *objp, &zap_nentries));
366+
if (zap_nentries == 0) {
367+
VERIFY0(zap_remove(zfsvfs->z_os, MASTER_NODE_OBJ,
368+
zfs_userquota_prop_prefixes[type], tx));
369+
VERIFY0(zap_destroy(zfsvfs->z_os, *objp, tx));
370+
*objp = 0;
371+
}
359372
} else {
360373
err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, &quota, tx);
361374
}
375+
mutex_exit(&zfsvfs->z_lock);
362376
ASSERT(err == 0);
363377
if (fuid_dirtied)
364378
zfs_fuid_sync(zfsvfs, tx);

0 commit comments

Comments
 (0)