From 306a9b666e5ea2882f704d93483355e7e147544f Mon Sep 17 00:00:00 2001 From: Alexander Zarochentsev Date: Thu, 20 Oct 2022 22:23:39 +0300 Subject: [PATCH] LU-16272 libcfs: cfs_hash_for_each_empty optimization Restarts from bucket 0 in cfs_hash_for_each_empty() cause excessive cpu consumption while checking first empty buckets. HPE-bug-id: LUS-11311 Signed-off-by: Alexander Zarochentsev Change-Id: Ic03875ea25101052468213043128912ac46daf32 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/48972 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andrew Perepechko Reviewed-by: Alexander Boyko Reviewed-by: Oleg Drokin --- libcfs/libcfs/hash.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libcfs/libcfs/hash.c b/libcfs/libcfs/hash.c index 6fb32ad..e4e061b 100644 --- a/libcfs/libcfs/hash.c +++ b/libcfs/libcfs/hash.c @@ -1597,7 +1597,7 @@ EXPORT_SYMBOL(cfs_hash_size_get); */ static int cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, - void *data, int start) + void *data, int *pstart) { struct hlist_node *hnode; struct hlist_node *next = NULL; @@ -1620,7 +1620,7 @@ again: cfs_hash_for_each_bucket(hs, &bd, i) { struct hlist_head *hhead; - if (i < start) + if (pstart && i < *pstart) continue; else if (end > 0 && i >= end) break; @@ -1679,13 +1679,15 @@ again: break; } - if (start > 0 && rc == 0) { - end = start; - start = 0; + if (pstart && *pstart > 0 && rc == 0) { + end = *pstart; + *pstart = 0; goto again; } cfs_hash_unlock(hs, 0); + if (pstart) + *pstart = i; return count; } @@ -1706,7 +1708,7 @@ cfs_hash_for_each_nolock(struct cfs_hash *hs, RETURN(-EOPNOTSUPP); cfs_hash_for_each_enter(hs); - cfs_hash_for_each_relax(hs, func, data, start); + cfs_hash_for_each_relax(hs, func, data, &start); cfs_hash_for_each_exit(hs); RETURN(0); @@ -1729,6 +1731,7 @@ cfs_hash_for_each_empty(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, void *data) { unsigned i = 0; + int start = 0; ENTRY; if (cfs_hash_with_no_lock(hs)) @@ -1740,11 +1743,12 @@ cfs_hash_for_each_empty(struct cfs_hash *hs, return -EOPNOTSUPP; cfs_hash_for_each_enter(hs); - while (cfs_hash_for_each_relax(hs, func, data, 0)) { + while (cfs_hash_for_each_relax(hs, func, data, &start)) { CDEBUG(D_INFO, "Try to empty hash: %s, loop: %u\n", hs->hs_name, i++); } cfs_hash_for_each_exit(hs); + LASSERT(atomic_read(&hs->hs_count) == 0); RETURN(0); } EXPORT_SYMBOL(cfs_hash_for_each_empty); -- 1.8.3.1