Skip to content

Commit 91ddd71

Browse files
author
Kent Overstreet
committed
bcachefs: split up btree cache counters for live, freeable
this is prep for introducing a second live list and shrinker for pinned nodes Signed-off-by: Kent Overstreet <[email protected]>
1 parent 691f2cb commit 91ddd71

File tree

6 files changed

+47
-32
lines changed

6 files changed

+47
-32
lines changed

fs/bcachefs/btree_cache.c

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void bch2_recalc_btree_reserve(struct bch_fs *c)
4949

5050
static inline size_t btree_cache_can_free(struct btree_cache *bc)
5151
{
52-
return max_t(int, 0, bc->nr_used - bc->nr_reserve);
52+
return max_t(int, 0, bc->nr_live + bc->nr_freeable - bc->nr_reserve);
5353
}
5454

5555
static void btree_node_to_freedlist(struct btree_cache *bc, struct btree *b)
@@ -64,6 +64,8 @@ static void btree_node_data_free(struct bch_fs *c, struct btree *b)
6464
{
6565
struct btree_cache *bc = &c->btree_cache;
6666

67+
BUG_ON(btree_node_hashed(b));
68+
6769
/*
6870
* This should really be done in slub/vmalloc, but we're using the
6971
* kmalloc_large() path, so we're working around a slub bug by doing
@@ -87,7 +89,7 @@ static void btree_node_data_free(struct bch_fs *c, struct btree *b)
8789
#endif
8890
b->aux_data = NULL;
8991

90-
bc->nr_used--;
92+
bc->nr_freeable--;
9193

9294
btree_node_to_freedlist(bc, b);
9395
}
@@ -167,7 +169,7 @@ struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *c)
167169

168170
bch2_btree_lock_init(&b->c, 0);
169171

170-
bc->nr_used++;
172+
bc->nr_freeable++;
171173
list_add(&b->list, &bc->freeable);
172174
return b;
173175
}
@@ -186,6 +188,7 @@ void bch2_btree_node_to_freelist(struct bch_fs *c, struct btree *b)
186188

187189
void bch2_btree_node_hash_remove(struct btree_cache *bc, struct btree *b)
188190
{
191+
lockdep_assert_held(&bc->lock);
189192
int ret = rhashtable_remove_fast(&bc->table, &b->hash, bch_btree_cache_params);
190193

191194
BUG_ON(ret);
@@ -195,6 +198,10 @@ void bch2_btree_node_hash_remove(struct btree_cache *bc, struct btree *b)
195198

196199
if (b->c.btree_id < BTREE_ID_NR)
197200
--bc->nr_by_btree[b->c.btree_id];
201+
202+
bc->nr_live--;
203+
bc->nr_freeable++;
204+
list_move(&b->list, &bc->freeable);
198205
}
199206

200207
int __bch2_btree_node_hash_insert(struct btree_cache *bc, struct btree *b)
@@ -204,23 +211,25 @@ int __bch2_btree_node_hash_insert(struct btree_cache *bc, struct btree *b)
204211

205212
int ret = rhashtable_lookup_insert_fast(&bc->table, &b->hash,
206213
bch_btree_cache_params);
207-
if (!ret && b->c.btree_id < BTREE_ID_NR)
214+
if (ret)
215+
return ret;
216+
217+
if (b->c.btree_id < BTREE_ID_NR)
208218
bc->nr_by_btree[b->c.btree_id]++;
209-
return ret;
219+
bc->nr_live++;
220+
bc->nr_freeable--;
221+
list_move_tail(&b->list, &bc->live);
222+
return 0;
210223
}
211224

212225
int bch2_btree_node_hash_insert(struct btree_cache *bc, struct btree *b,
213226
unsigned level, enum btree_id id)
214227
{
215-
int ret;
216-
217228
b->c.level = level;
218229
b->c.btree_id = id;
219230

220231
mutex_lock(&bc->lock);
221-
ret = __bch2_btree_node_hash_insert(bc, b);
222-
if (!ret)
223-
list_add_tail(&b->list, &bc->live);
232+
int ret = __bch2_btree_node_hash_insert(bc, b);
224233
mutex_unlock(&bc->lock);
225234

226235
return ret;
@@ -402,7 +411,7 @@ static unsigned long bch2_btree_cache_scan(struct shrinker *shrink,
402411
unsigned i, flags;
403412
unsigned long ret = SHRINK_STOP;
404413
bool trigger_writes = atomic_long_read(&bc->nr_dirty) + nr >=
405-
bc->nr_used * 3 / 4;
414+
(bc->nr_live + bc->nr_freeable) * 3 / 4;
406415

407416
if (bch2_btree_shrinker_disabled)
408417
return SHRINK_STOP;
@@ -451,11 +460,12 @@ static unsigned long bch2_btree_cache_scan(struct shrinker *shrink,
451460
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_access_bit]++;
452461
--touched;;
453462
} else if (!btree_node_reclaim(c, b, true)) {
463+
bch2_btree_node_hash_remove(bc, b);
464+
454465
freed++;
455466
btree_node_data_free(c, b);
456467
bc->nr_freed++;
457468

458-
bch2_btree_node_hash_remove(bc, b);
459469
six_unlock_write(&b->c.lock);
460470
six_unlock_intent(&b->c.lock);
461471

@@ -506,7 +516,7 @@ static unsigned long bch2_btree_cache_count(struct shrinker *shrink,
506516
void bch2_fs_btree_cache_exit(struct bch_fs *c)
507517
{
508518
struct btree_cache *bc = &c->btree_cache;
509-
struct btree *b;
519+
struct btree *b, *t;
510520
unsigned i, flags;
511521

512522
shrinker_free(bc->shrink);
@@ -527,11 +537,10 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
527537
list_add(&r->b->list, &bc->live);
528538
}
529539

530-
list_splice(&bc->freeable, &bc->live);
531-
532-
while (!list_empty(&bc->live)) {
533-
b = list_first_entry(&bc->live, struct btree, list);
540+
list_for_each_entry_safe(b, t, &bc->live, list)
541+
bch2_btree_node_hash_remove(bc, b);
534542

543+
list_for_each_entry_safe(b, t, &bc->freeable, list) {
535544
BUG_ON(btree_node_read_in_flight(b) ||
536545
btree_node_write_in_flight(b));
537546

@@ -543,8 +552,7 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
543552

544553
list_splice(&bc->freed_pcpu, &bc->freed_nonpcpu);
545554

546-
while (!list_empty(&bc->freed_nonpcpu)) {
547-
b = list_first_entry(&bc->freed_nonpcpu, struct btree, list);
555+
list_for_each_entry_safe(b, t, &bc->freed_nonpcpu, list) {
548556
list_del(&b->list);
549557
six_lock_exit(&b->c.lock);
550558
kfree(b);
@@ -553,6 +561,11 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
553561
mutex_unlock(&bc->lock);
554562
memalloc_nofs_restore(flags);
555563

564+
for (unsigned i = 0; i < ARRAY_SIZE(bc->nr_by_btree); i++)
565+
BUG_ON(bc->nr_by_btree[i]);
566+
BUG_ON(bc->nr_live);
567+
BUG_ON(bc->nr_freeable);
568+
556569
if (bc->table_init_done)
557570
rhashtable_destroy(&bc->table);
558571
}
@@ -739,7 +752,7 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
739752
}
740753

741754
mutex_lock(&bc->lock);
742-
bc->nr_used++;
755+
bc->nr_freeable++;
743756
got_mem:
744757
mutex_unlock(&bc->lock);
745758

@@ -1280,8 +1293,8 @@ void bch2_btree_node_evict(struct btree_trans *trans, const struct bkey_i *k)
12801293
BUG_ON(btree_node_dirty(b));
12811294

12821295
mutex_lock(&bc->lock);
1283-
btree_node_data_free(c, b);
12841296
bch2_btree_node_hash_remove(bc, b);
1297+
btree_node_data_free(c, b);
12851298
mutex_unlock(&bc->lock);
12861299
out:
12871300
six_unlock_write(&b->c.lock);
@@ -1374,7 +1387,8 @@ void bch2_btree_cache_to_text(struct printbuf *out, const struct btree_cache *bc
13741387
if (!out->nr_tabstops)
13751388
printbuf_tabstop_push(out, 32);
13761389

1377-
prt_btree_cache_line(out, c, "total:", bc->nr_used);
1390+
prt_btree_cache_line(out, c, "nr_live:", bc->nr_live);
1391+
prt_btree_cache_line(out, c, "nr_freeable:", bc->nr_freeable);
13781392
prt_btree_cache_line(out, c, "nr dirty:", atomic_long_read(&bc->nr_dirty));
13791393
prt_printf(out, "cannibalize lock:\t%p\n", bc->alloc_lock);
13801394
prt_newline(out);

fs/bcachefs/btree_gc.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,9 +549,8 @@ int bch2_check_topology(struct bch_fs *c)
549549
six_unlock_read(&b->c.lock);
550550

551551
if (ret == DROP_THIS_NODE) {
552-
bch2_btree_node_hash_remove(&c->btree_cache, b);
553552
mutex_lock(&c->btree_cache.lock);
554-
list_move(&b->list, &c->btree_cache.freeable);
553+
bch2_btree_node_hash_remove(&c->btree_cache, b);
555554
mutex_unlock(&c->btree_cache.lock);
556555

557556
r->b = NULL;

fs/bcachefs/btree_io.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,10 +1749,8 @@ static int __bch2_btree_root_read(struct btree_trans *trans, enum btree_id id,
17491749
bch2_btree_node_read(trans, b, true);
17501750

17511751
if (btree_node_read_error(b)) {
1752-
bch2_btree_node_hash_remove(&c->btree_cache, b);
1753-
17541752
mutex_lock(&c->btree_cache.lock);
1755-
list_move(&b->list, &c->btree_cache.freeable);
1753+
bch2_btree_node_hash_remove(&c->btree_cache, b);
17561754
mutex_unlock(&c->btree_cache.lock);
17571755

17581756
ret = -BCH_ERR_btree_node_read_error;

fs/bcachefs/btree_types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ struct btree_cache {
179179
struct list_head freed_pcpu;
180180
struct list_head freed_nonpcpu;
181181

182-
/* Number of elements in live + freeable lists */
183-
size_t nr_used;
182+
size_t nr_live;
183+
size_t nr_freeable;
184184
size_t nr_reserve;
185185
size_t nr_by_btree[BTREE_ID_NR];
186186
atomic_long_t nr_dirty;

fs/bcachefs/btree_update_interior.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,13 @@ static void bch2_btree_node_free_inmem(struct btree_trans *trans,
251251
unsigned i, level = b->c.level;
252252

253253
bch2_btree_node_lock_write_nofail(trans, path, &b->c);
254+
255+
mutex_lock(&c->btree_cache.lock);
254256
bch2_btree_node_hash_remove(&c->btree_cache, b);
257+
mutex_unlock(&c->btree_cache.lock);
258+
255259
__btree_node_free(trans, b);
260+
256261
six_unlock_write(&b->c.lock);
257262
mark_btree_node_locked_noreset(path, level, BTREE_NODE_INTENT_LOCKED);
258263

@@ -284,7 +289,6 @@ static void bch2_btree_node_free_never_used(struct btree_update *as,
284289
clear_btree_node_need_write(b);
285290

286291
mutex_lock(&c->btree_cache.lock);
287-
list_del_init(&b->list);
288292
bch2_btree_node_hash_remove(&c->btree_cache, b);
289293
mutex_unlock(&c->btree_cache.lock);
290294

fs/bcachefs/journal_reclaim.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ static int __bch2_journal_reclaim(struct journal *j, bool direct, bool kicked)
681681
if (j->watermark != BCH_WATERMARK_stripe)
682682
min_nr = 1;
683683

684-
if (atomic_long_read(&c->btree_cache.nr_dirty) * 2 > c->btree_cache.nr_used)
684+
if (atomic_long_read(&c->btree_cache.nr_dirty) * 2 > c->btree_cache.nr_live)
685685
min_nr = 1;
686686

687687
min_key_cache = min(bch2_nr_btree_keys_need_flush(c), (size_t) 128);
@@ -690,7 +690,7 @@ static int __bch2_journal_reclaim(struct journal *j, bool direct, bool kicked)
690690
direct, kicked,
691691
min_nr, min_key_cache,
692692
atomic_long_read(&c->btree_cache.nr_dirty),
693-
c->btree_cache.nr_used,
693+
c->btree_cache.nr_live,
694694
atomic_long_read(&c->btree_key_cache.nr_dirty),
695695
atomic_long_read(&c->btree_key_cache.nr_keys));
696696

0 commit comments

Comments
 (0)