bcachefs: don't use rht_bucket() in btree_key_cache_scan()
rht_bucket() does strange complicated things when a rehash is in progress. Instead, just skip scanning when a rehash is in progress: scanning is going to be more expensive (many more empty slots to cover), and some sort of infinite loop is being observed Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
3e878fe5a0
commit
a592cdf516
@ -778,6 +778,20 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
|
||||
|
||||
rcu_read_lock();
|
||||
tbl = rht_dereference_rcu(bc->table.tbl, &bc->table);
|
||||
|
||||
/*
|
||||
* Scanning is expensive while a rehash is in progress - most elements
|
||||
* will be on the new hashtable, if it's in progress
|
||||
*
|
||||
* A rehash could still start while we're scanning - that's ok, we'll
|
||||
* still see most elements.
|
||||
*/
|
||||
if (unlikely(tbl->nest)) {
|
||||
rcu_read_unlock();
|
||||
srcu_read_unlock(&c->btree_trans_barrier, srcu_idx);
|
||||
return SHRINK_STOP;
|
||||
}
|
||||
|
||||
if (bc->shrink_iter >= tbl->size)
|
||||
bc->shrink_iter = 0;
|
||||
start = bc->shrink_iter;
|
||||
@ -785,7 +799,7 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
|
||||
do {
|
||||
struct rhash_head *pos, *next;
|
||||
|
||||
pos = rht_ptr_rcu(rht_bucket(tbl, bc->shrink_iter));
|
||||
pos = rht_ptr_rcu(&tbl->buckets[bc->shrink_iter]);
|
||||
|
||||
while (!rht_is_a_nulls(pos)) {
|
||||
next = rht_dereference_bucket_rcu(pos->next, tbl, bc->shrink_iter);
|
||||
@ -866,12 +880,22 @@ void bch2_fs_btree_key_cache_exit(struct btree_key_cache *bc)
|
||||
while (atomic_long_read(&bc->nr_keys)) {
|
||||
rcu_read_lock();
|
||||
tbl = rht_dereference_rcu(bc->table.tbl, &bc->table);
|
||||
if (tbl)
|
||||
if (tbl) {
|
||||
if (tbl->nest) {
|
||||
/* wait for in progress rehash */
|
||||
rcu_read_unlock();
|
||||
mutex_lock(&bc->table.mutex);
|
||||
mutex_unlock(&bc->table.mutex);
|
||||
rcu_read_lock();
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < tbl->size; i++)
|
||||
rht_for_each_entry_rcu(ck, pos, tbl, i, hash) {
|
||||
while (pos = rht_ptr_rcu(&tbl->buckets[i]), !rht_is_a_nulls(pos)) {
|
||||
ck = container_of(pos, struct bkey_cached, hash);
|
||||
bkey_cached_evict(bc, ck);
|
||||
list_add(&ck->list, &items);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user