@@ -59,16 +59,38 @@ static inline size_t btree_cache_can_free(struct btree_cache_list *list)
5959
6060static void btree_node_to_freedlist (struct btree_cache * bc , struct btree * b )
6161{
62+ BUG_ON (!list_empty (& b -> list ));
63+
6264 if (b -> c .lock .readers )
63- list_move (& b -> list , & bc -> freed_pcpu );
65+ list_add (& b -> list , & bc -> freed_pcpu );
6466 else
65- list_move (& b -> list , & bc -> freed_nonpcpu );
67+ list_add (& b -> list , & bc -> freed_nonpcpu );
6668}
6769
68- static void btree_node_data_free (struct bch_fs * c , struct btree * b )
70+ static void __bch2_btree_node_to_freelist (struct btree_cache * bc , struct btree * b )
71+ {
72+ BUG_ON (!list_empty (& b -> list ));
73+ BUG_ON (!b -> data );
74+
75+ bc -> nr_freeable ++ ;
76+ list_add (& b -> list , & bc -> freeable );
77+ }
78+
79+ void bch2_btree_node_to_freelist (struct bch_fs * c , struct btree * b )
6980{
7081 struct btree_cache * bc = & c -> btree_cache ;
7182
83+ mutex_lock (& bc -> lock );
84+ __bch2_btree_node_to_freelist (bc , b );
85+ mutex_unlock (& bc -> lock );
86+
87+ six_unlock_write (& b -> c .lock );
88+ six_unlock_intent (& b -> c .lock );
89+ }
90+
91+ static void __btree_node_data_free (struct btree_cache * bc , struct btree * b )
92+ {
93+ BUG_ON (!list_empty (& b -> list ));
7294 BUG_ON (btree_node_hashed (b ));
7395
7496 /*
@@ -94,11 +116,17 @@ static void btree_node_data_free(struct bch_fs *c, struct btree *b)
94116#endif
95117 b -> aux_data = NULL ;
96118
97- bc -> nr_freeable -- ;
98-
99119 btree_node_to_freedlist (bc , b );
100120}
101121
122+ static void btree_node_data_free (struct btree_cache * bc , struct btree * b )
123+ {
124+ BUG_ON (list_empty (& b -> list ));
125+ list_del_init (& b -> list );
126+ -- bc -> nr_freeable ;
127+ __btree_node_data_free (bc , b );
128+ }
129+
102130static int bch2_btree_cache_cmp_fn (struct rhashtable_compare_arg * arg ,
103131 const void * obj )
104132{
@@ -174,21 +202,10 @@ struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *c)
174202
175203 bch2_btree_lock_init (& b -> c , 0 );
176204
177- bc -> nr_freeable ++ ;
178- list_add (& b -> list , & bc -> freeable );
205+ __bch2_btree_node_to_freelist (bc , b );
179206 return b ;
180207}
181208
182- void bch2_btree_node_to_freelist (struct bch_fs * c , struct btree * b )
183- {
184- mutex_lock (& c -> btree_cache .lock );
185- list_move (& b -> list , & c -> btree_cache .freeable );
186- mutex_unlock (& c -> btree_cache .lock );
187-
188- six_unlock_write (& b -> c .lock );
189- six_unlock_intent (& b -> c .lock );
190- }
191-
192209static inline bool __btree_node_pinned (struct btree_cache * bc , struct btree * b )
193210{
194211 struct bbpos pos = BBPOS (b -> c .btree_id , b -> key .k .p );
@@ -236,29 +253,34 @@ void bch2_btree_cache_unpin(struct bch_fs *c)
236253
237254/* Btree in memory cache - hash table */
238255
239- void bch2_btree_node_hash_remove (struct btree_cache * bc , struct btree * b )
256+ void __bch2_btree_node_hash_remove (struct btree_cache * bc , struct btree * b )
240257{
241258 lockdep_assert_held (& bc -> lock );
242- int ret = rhashtable_remove_fast (& bc -> table , & b -> hash , bch_btree_cache_params );
243259
260+ int ret = rhashtable_remove_fast (& bc -> table , & b -> hash , bch_btree_cache_params );
244261 BUG_ON (ret );
245262
246263 /* Cause future lookups for this node to fail: */
247264 b -> hash_val = 0 ;
248265
249266 if (b -> c .btree_id < BTREE_ID_NR )
250267 -- bc -> nr_by_btree [b -> c .btree_id ];
268+ -- bc -> live [btree_node_pinned (b )].nr ;
269+ list_del_init (& b -> list );
270+ }
251271
252- bc -> live [btree_node_pinned (b )].nr -- ;
253- bc -> nr_freeable ++ ;
254- list_move (& b -> list , & bc -> freeable );
272+ void bch2_btree_node_hash_remove (struct btree_cache * bc , struct btree * b )
273+ {
274+ __bch2_btree_node_hash_remove (bc , b );
275+ __bch2_btree_node_to_freelist (bc , b );
255276}
256277
257278int __bch2_btree_node_hash_insert (struct btree_cache * bc , struct btree * b )
258279{
280+ BUG_ON (!list_empty (& b -> list ));
259281 BUG_ON (b -> hash_val );
260- b -> hash_val = btree_ptr_hash_val (& b -> key );
261282
283+ b -> hash_val = btree_ptr_hash_val (& b -> key );
262284 int ret = rhashtable_lookup_insert_fast (& bc -> table , & b -> hash ,
263285 bch_btree_cache_params );
264286 if (ret )
@@ -270,10 +292,8 @@ int __bch2_btree_node_hash_insert(struct btree_cache *bc, struct btree *b)
270292 bool p = __btree_node_pinned (bc , b );
271293 mod_bit (BTREE_NODE_pinned , & b -> flags , p );
272294
273- list_move_tail (& b -> list , & bc -> live [p ].list );
295+ list_add_tail (& b -> list , & bc -> live [p ].list );
274296 bc -> live [p ].nr ++ ;
275-
276- bc -> nr_freeable -- ;
277297 return 0 ;
278298}
279299
@@ -485,7 +505,7 @@ static unsigned long bch2_btree_cache_scan(struct shrinker *shrink,
485505 goto out ;
486506
487507 if (!btree_node_reclaim (c , b , true)) {
488- btree_node_data_free (c , b );
508+ btree_node_data_free (bc , b );
489509 six_unlock_write (& b -> c .lock );
490510 six_unlock_intent (& b -> c .lock );
491511 freed ++ ;
@@ -501,10 +521,10 @@ static unsigned long bch2_btree_cache_scan(struct shrinker *shrink,
501521 bc -> not_freed [BCH_BTREE_CACHE_NOT_FREED_access_bit ]++ ;
502522 -- touched ;;
503523 } else if (!btree_node_reclaim (c , b , true)) {
504- bch2_btree_node_hash_remove (bc , b );
524+ __bch2_btree_node_hash_remove (bc , b );
525+ __btree_node_data_free (bc , b );
505526
506527 freed ++ ;
507- btree_node_data_free (c , b );
508528 bc -> nr_freed ++ ;
509529
510530 six_unlock_write (& b -> c .lock );
@@ -587,7 +607,7 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
587607 BUG_ON (btree_node_read_in_flight (b ) ||
588608 btree_node_write_in_flight (b ));
589609
590- btree_node_data_free (c , b );
610+ btree_node_data_free (bc , b );
591611 }
592612
593613 BUG_ON (!bch2_journal_error (& c -> journal ) &&
@@ -786,8 +806,8 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
786806
787807 BUG_ON (!six_trylock_intent (& b -> c .lock ));
788808 BUG_ON (!six_trylock_write (& b -> c .lock ));
789- got_node :
790809
810+ got_node :
791811 /*
792812 * btree_free() doesn't free memory; it sticks the node on the end of
793813 * the list. Check if there's any freed nodes there:
@@ -796,7 +816,12 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
796816 if (!btree_node_reclaim (c , b2 , false)) {
797817 swap (b -> data , b2 -> data );
798818 swap (b -> aux_data , b2 -> aux_data );
819+
820+ list_del_init (& b2 -> list );
821+ -- bc -> nr_freeable ;
799822 btree_node_to_freedlist (bc , b2 );
823+ mutex_unlock (& bc -> lock );
824+
800825 six_unlock_write (& b2 -> c .lock );
801826 six_unlock_intent (& b2 -> c .lock );
802827 goto got_mem ;
@@ -810,11 +835,8 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
810835 goto err ;
811836 }
812837
813- mutex_lock (& bc -> lock );
814- bc -> nr_freeable ++ ;
815838got_mem :
816- mutex_unlock (& bc -> lock );
817-
839+ BUG_ON (!list_empty (& b -> list ));
818840 BUG_ON (btree_node_hashed (b ));
819841 BUG_ON (btree_node_dirty (b ));
820842 BUG_ON (btree_node_write_in_flight (b ));
@@ -845,7 +867,7 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
845867 if (bc -> alloc_lock == current ) {
846868 b2 = btree_node_cannibalize (c );
847869 clear_btree_node_just_written (b2 );
848- bch2_btree_node_hash_remove (bc , b2 );
870+ __bch2_btree_node_hash_remove (bc , b2 );
849871
850872 if (b ) {
851873 swap (b -> data , b2 -> data );
@@ -855,9 +877,9 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
855877 six_unlock_intent (& b2 -> c .lock );
856878 } else {
857879 b = b2 ;
858- list_del_init (& b -> list );
859880 }
860881
882+ BUG_ON (!list_empty (& b -> list ));
861883 mutex_unlock (& bc -> lock );
862884
863885 trace_and_count (c , btree_cache_cannibalize , trans );
@@ -936,7 +958,7 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
936958 b -> hash_val = 0 ;
937959
938960 mutex_lock (& bc -> lock );
939- list_add ( & b -> list , & bc -> freeable );
961+ __bch2_btree_node_to_freelist ( bc , b );
940962 mutex_unlock (& bc -> lock );
941963
942964 six_unlock_write (& b -> c .lock );
@@ -1356,7 +1378,7 @@ void bch2_btree_node_evict(struct btree_trans *trans, const struct bkey_i *k)
13561378
13571379 mutex_lock (& bc -> lock );
13581380 bch2_btree_node_hash_remove (bc , b );
1359- btree_node_data_free (c , b );
1381+ btree_node_data_free (bc , b );
13601382 mutex_unlock (& bc -> lock );
13611383out :
13621384 six_unlock_write (& b -> c .lock );
0 commit comments