Employ zfs_refcount_remove_unless_last in sa_idx_tab_rele

This avoids taking the lock in the common case.

This almost halves contention on z_hold_mtx as it avoids extending its
hold time by not contending on sa_lock.

Performance does not improve because contention shifts to other
global-ish locks.

Before:
108608922 (sx:zfsvfs->z_hold_mtx[i])
15464416 (sleep mutex:vnode_list)
12455346 (sx:os->os_lock)
10792604 (sx:sa->sa_lock)
3888049 (sx:zfsvfs->z_znodes_lock)
2863341 (sleep mutex:struct mount mtx)
835414 (sx:dn->dn_mtx)

After:
57594050 (sx:zfsvfs->z_hold_mtx[i])
22089617 (sleep mutex:vnode_list)
12148265 (sx:zfsvfs->z_znodes_lock)
9537666 (sx:os->os_lock)
6833254 (sleep mutex:struct mount mtx)
1131875 (sx:sa->sa_lock)
437455 (sx:dn->dn_mtx)

Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
This commit is contained in:
Mateusz Guzik 2023-10-28 05:37:24 +00:00
parent eee1810861
commit 7acd62b609
1 changed files with 3 additions and 0 deletions

View File

@ -1325,6 +1325,9 @@ sa_idx_tab_rele(objset_t *os, void *arg)
if (idx_tab == NULL)
return;
if (zfs_refcount_remove_not_last(&idx_tab->sa_refcount, NULL))
return;
mutex_enter(&sa->sa_lock);
if (zfs_refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
list_remove(&idx_tab->sa_layout->lot_idx_tab, idx_tab);