@@ -59,16 +59,38 @@ static inline size_t btree_cache_can_free(struct btree_cache_list *list)
59
59
60
60
static void btree_node_to_freedlist (struct btree_cache * bc , struct btree * b )
61
61
{
62
+ BUG_ON (!list_empty (& b -> list ));
63
+
62
64
if (b -> c .lock .readers )
63
- list_move (& b -> list , & bc -> freed_pcpu );
65
+ list_add (& b -> list , & bc -> freed_pcpu );
64
66
else
65
- list_move (& b -> list , & bc -> freed_nonpcpu );
67
+ list_add (& b -> list , & bc -> freed_nonpcpu );
68
+ }
69
+
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 );
66
77
}
67
78
68
- static void btree_node_data_free (struct bch_fs * c , struct btree * b )
79
+ void bch2_btree_node_to_freelist (struct bch_fs * c , struct btree * b )
69
80
{
70
81
struct btree_cache * bc = & c -> btree_cache ;
71
82
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 ));
72
94
BUG_ON (btree_node_hashed (b ));
73
95
74
96
/*
@@ -94,11 +116,17 @@ static void btree_node_data_free(struct bch_fs *c, struct btree *b)
94
116
#endif
95
117
b -> aux_data = NULL ;
96
118
97
- bc -> nr_freeable -- ;
98
-
99
119
btree_node_to_freedlist (bc , b );
100
120
}
101
121
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
+
102
130
static int bch2_btree_cache_cmp_fn (struct rhashtable_compare_arg * arg ,
103
131
const void * obj )
104
132
{
@@ -174,21 +202,10 @@ struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *c)
174
202
175
203
bch2_btree_lock_init (& b -> c , 0 );
176
204
177
- bc -> nr_freeable ++ ;
178
- list_add (& b -> list , & bc -> freeable );
205
+ __bch2_btree_node_to_freelist (bc , b );
179
206
return b ;
180
207
}
181
208
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
-
192
209
static inline bool __btree_node_pinned (struct btree_cache * bc , struct btree * b )
193
210
{
194
211
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)
236
253
237
254
/* Btree in memory cache - hash table */
238
255
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 )
240
257
{
241
258
lockdep_assert_held (& bc -> lock );
242
- int ret = rhashtable_remove_fast (& bc -> table , & b -> hash , bch_btree_cache_params );
243
259
260
+ int ret = rhashtable_remove_fast (& bc -> table , & b -> hash , bch_btree_cache_params );
244
261
BUG_ON (ret );
245
262
246
263
/* Cause future lookups for this node to fail: */
247
264
b -> hash_val = 0 ;
248
265
249
266
if (b -> c .btree_id < BTREE_ID_NR )
250
267
-- bc -> nr_by_btree [b -> c .btree_id ];
268
+ -- bc -> live [btree_node_pinned (b )].nr ;
269
+ list_del_init (& b -> list );
270
+ }
251
271
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 );
255
276
}
256
277
257
278
int __bch2_btree_node_hash_insert (struct btree_cache * bc , struct btree * b )
258
279
{
280
+ BUG_ON (!list_empty (& b -> list ));
259
281
BUG_ON (b -> hash_val );
260
- b -> hash_val = btree_ptr_hash_val (& b -> key );
261
282
283
+ b -> hash_val = btree_ptr_hash_val (& b -> key );
262
284
int ret = rhashtable_lookup_insert_fast (& bc -> table , & b -> hash ,
263
285
bch_btree_cache_params );
264
286
if (ret )
@@ -270,10 +292,8 @@ int __bch2_btree_node_hash_insert(struct btree_cache *bc, struct btree *b)
270
292
bool p = __btree_node_pinned (bc , b );
271
293
mod_bit (BTREE_NODE_pinned , & b -> flags , p );
272
294
273
- list_move_tail (& b -> list , & bc -> live [p ].list );
295
+ list_add_tail (& b -> list , & bc -> live [p ].list );
274
296
bc -> live [p ].nr ++ ;
275
-
276
- bc -> nr_freeable -- ;
277
297
return 0 ;
278
298
}
279
299
@@ -485,7 +505,7 @@ static unsigned long bch2_btree_cache_scan(struct shrinker *shrink,
485
505
goto out ;
486
506
487
507
if (!btree_node_reclaim (c , b , true)) {
488
- btree_node_data_free (c , b );
508
+ btree_node_data_free (bc , b );
489
509
six_unlock_write (& b -> c .lock );
490
510
six_unlock_intent (& b -> c .lock );
491
511
freed ++ ;
@@ -501,10 +521,10 @@ static unsigned long bch2_btree_cache_scan(struct shrinker *shrink,
501
521
bc -> not_freed [BCH_BTREE_CACHE_NOT_FREED_access_bit ]++ ;
502
522
-- touched ;;
503
523
} 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 );
505
526
506
527
freed ++ ;
507
- btree_node_data_free (c , b );
508
528
bc -> nr_freed ++ ;
509
529
510
530
six_unlock_write (& b -> c .lock );
@@ -587,7 +607,7 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
587
607
BUG_ON (btree_node_read_in_flight (b ) ||
588
608
btree_node_write_in_flight (b ));
589
609
590
- btree_node_data_free (c , b );
610
+ btree_node_data_free (bc , b );
591
611
}
592
612
593
613
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
786
806
787
807
BUG_ON (!six_trylock_intent (& b -> c .lock ));
788
808
BUG_ON (!six_trylock_write (& b -> c .lock ));
789
- got_node :
790
809
810
+ got_node :
791
811
/*
792
812
* btree_free() doesn't free memory; it sticks the node on the end of
793
813
* 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
796
816
if (!btree_node_reclaim (c , b2 , false)) {
797
817
swap (b -> data , b2 -> data );
798
818
swap (b -> aux_data , b2 -> aux_data );
819
+
820
+ list_del_init (& b2 -> list );
821
+ -- bc -> nr_freeable ;
799
822
btree_node_to_freedlist (bc , b2 );
823
+ mutex_unlock (& bc -> lock );
824
+
800
825
six_unlock_write (& b2 -> c .lock );
801
826
six_unlock_intent (& b2 -> c .lock );
802
827
goto got_mem ;
@@ -810,11 +835,8 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
810
835
goto err ;
811
836
}
812
837
813
- mutex_lock (& bc -> lock );
814
- bc -> nr_freeable ++ ;
815
838
got_mem :
816
- mutex_unlock (& bc -> lock );
817
-
839
+ BUG_ON (!list_empty (& b -> list ));
818
840
BUG_ON (btree_node_hashed (b ));
819
841
BUG_ON (btree_node_dirty (b ));
820
842
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
845
867
if (bc -> alloc_lock == current ) {
846
868
b2 = btree_node_cannibalize (c );
847
869
clear_btree_node_just_written (b2 );
848
- bch2_btree_node_hash_remove (bc , b2 );
870
+ __bch2_btree_node_hash_remove (bc , b2 );
849
871
850
872
if (b ) {
851
873
swap (b -> data , b2 -> data );
@@ -855,9 +877,9 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
855
877
six_unlock_intent (& b2 -> c .lock );
856
878
} else {
857
879
b = b2 ;
858
- list_del_init (& b -> list );
859
880
}
860
881
882
+ BUG_ON (!list_empty (& b -> list ));
861
883
mutex_unlock (& bc -> lock );
862
884
863
885
trace_and_count (c , btree_cache_cannibalize , trans );
@@ -936,7 +958,7 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
936
958
b -> hash_val = 0 ;
937
959
938
960
mutex_lock (& bc -> lock );
939
- list_add ( & b -> list , & bc -> freeable );
961
+ __bch2_btree_node_to_freelist ( bc , b );
940
962
mutex_unlock (& bc -> lock );
941
963
942
964
six_unlock_write (& b -> c .lock );
@@ -1312,9 +1334,12 @@ int bch2_btree_node_prefetch(struct btree_trans *trans,
1312
1334
1313
1335
b = bch2_btree_node_fill (trans , path , k , btree_id ,
1314
1336
level , SIX_LOCK_read , false);
1315
- if (!IS_ERR_OR_NULL (b ))
1337
+ int ret = PTR_ERR_OR_ZERO (b );
1338
+ if (ret )
1339
+ return ret ;
1340
+ if (b )
1316
1341
six_unlock_read (& b -> c .lock );
1317
- return bch2_trans_relock ( trans ) ?: PTR_ERR_OR_ZERO ( b ) ;
1342
+ return 0 ;
1318
1343
}
1319
1344
1320
1345
void bch2_btree_node_evict (struct btree_trans * trans , const struct bkey_i * k )
@@ -1353,7 +1378,7 @@ void bch2_btree_node_evict(struct btree_trans *trans, const struct bkey_i *k)
1353
1378
1354
1379
mutex_lock (& bc -> lock );
1355
1380
bch2_btree_node_hash_remove (bc , b );
1356
- btree_node_data_free (c , b );
1381
+ btree_node_data_free (bc , b );
1357
1382
mutex_unlock (& bc -> lock );
1358
1383
out :
1359
1384
six_unlock_write (& b -> c .lock );
0 commit comments