@@ -49,7 +49,7 @@ void bch2_recalc_btree_reserve(struct bch_fs *c)
4949
5050static 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
5555static 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
187189void 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
200207int __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
212225int 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,
506516void 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 ++ ;
743756got_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 );
12861299out :
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 );
0 commit comments