@@ -327,8 +327,10 @@ void bch2_journal_reclaim_fast(struct journal *j)
327327 popped = true;
328328 }
329329
330- if (popped )
330+ if (popped ) {
331331 bch2_journal_space_available (j );
332+ __closure_wake_up (& j -> reclaim_flush_wait );
333+ }
332334}
333335
334336bool __bch2_journal_pin_put (struct journal * j , u64 seq )
@@ -362,6 +364,9 @@ static inline bool __journal_pin_drop(struct journal *j,
362364 pin -> seq = 0 ;
363365 list_del_init (& pin -> list );
364366
367+ if (j -> reclaim_flush_wait .list .first )
368+ __closure_wake_up (& j -> reclaim_flush_wait );
369+
365370 /*
366371 * Unpinning a journal entry may make journal_next_bucket() succeed, if
367372 * writing a new last_seq will now make another bucket available:
@@ -383,11 +388,11 @@ static enum journal_pin_type journal_pin_type(journal_pin_flush_fn fn)
383388{
384389 if (fn == bch2_btree_node_flush0 ||
385390 fn == bch2_btree_node_flush1 )
386- return JOURNAL_PIN_btree ;
391+ return JOURNAL_PIN_TYPE_btree ;
387392 else if (fn == bch2_btree_key_cache_journal_flush )
388- return JOURNAL_PIN_key_cache ;
393+ return JOURNAL_PIN_TYPE_key_cache ;
389394 else
390- return JOURNAL_PIN_other ;
395+ return JOURNAL_PIN_TYPE_other ;
391396}
392397
393398static inline void bch2_journal_pin_set_locked (struct journal * j , u64 seq ,
@@ -406,7 +411,12 @@ static inline void bch2_journal_pin_set_locked(struct journal *j, u64 seq,
406411 atomic_inc (& pin_list -> count );
407412 pin -> seq = seq ;
408413 pin -> flush = flush_fn ;
409- list_add (& pin -> list , & pin_list -> list [type ]);
414+
415+ if (list_empty (& pin_list -> unflushed [type ]) &&
416+ j -> reclaim_flush_wait .list .first )
417+ __closure_wake_up (& j -> reclaim_flush_wait );
418+
419+ list_add (& pin -> list , & pin_list -> unflushed [type ]);
410420}
411421
412422void bch2_journal_pin_copy (struct journal * j ,
@@ -499,16 +509,15 @@ journal_get_next_pin(struct journal *j,
499509{
500510 struct journal_entry_pin_list * pin_list ;
501511 struct journal_entry_pin * ret = NULL ;
502- unsigned i ;
503512
504513 fifo_for_each_entry_ptr (pin_list , & j -> pin , * seq ) {
505514 if (* seq > seq_to_flush && !allowed_above_seq )
506515 break ;
507516
508- for (i = 0 ; i < JOURNAL_PIN_NR ; i ++ )
509- if (((( 1U << i ) & allowed_below_seq ) && * seq <= seq_to_flush ) ||
510- (( 1U << i ) & allowed_above_seq )) {
511- ret = list_first_entry_or_null (& pin_list -> list [i ],
517+ for (unsigned i = 0 ; i < JOURNAL_PIN_TYPE_NR ; i ++ )
518+ if (((BIT ( i ) & allowed_below_seq ) && * seq <= seq_to_flush ) ||
519+ (BIT ( i ) & allowed_above_seq )) {
520+ ret = list_first_entry_or_null (& pin_list -> unflushed [i ],
512521 struct journal_entry_pin , list );
513522 if (ret )
514523 return ret ;
@@ -544,16 +553,18 @@ static size_t journal_flush_pins(struct journal *j,
544553 }
545554
546555 if (min_key_cache ) {
547- allowed_above |= 1U << JOURNAL_PIN_key_cache ;
548- allowed_below |= 1U << JOURNAL_PIN_key_cache ;
556+ allowed_above |= BIT ( JOURNAL_PIN_TYPE_key_cache ) ;
557+ allowed_below |= BIT ( JOURNAL_PIN_TYPE_key_cache ) ;
549558 }
550559
551560 cond_resched ();
552561
553562 j -> last_flushed = jiffies ;
554563
555564 spin_lock (& j -> lock );
556- pin = journal_get_next_pin (j , seq_to_flush , allowed_below , allowed_above , & seq );
565+ pin = journal_get_next_pin (j , seq_to_flush ,
566+ allowed_below ,
567+ allowed_above , & seq );
557568 if (pin ) {
558569 BUG_ON (j -> flush_in_progress );
559570 j -> flush_in_progress = pin ;
@@ -576,7 +587,7 @@ static size_t journal_flush_pins(struct journal *j,
576587 spin_lock (& j -> lock );
577588 /* Pin might have been dropped or rearmed: */
578589 if (likely (!err && !j -> flush_in_progress_dropped ))
579- list_move (& pin -> list , & journal_seq_pin (j , seq )-> flushed );
590+ list_move (& pin -> list , & journal_seq_pin (j , seq )-> flushed [ journal_pin_type ( flush_fn )] );
580591 j -> flush_in_progress = NULL ;
581592 j -> flush_in_progress_dropped = false;
582593 spin_unlock (& j -> lock );
@@ -816,23 +827,60 @@ int bch2_journal_reclaim_start(struct journal *j)
816827 return 0 ;
817828}
818829
830+ static bool journal_pins_still_flushing (struct journal * j , u64 seq_to_flush ,
831+ unsigned types )
832+ {
833+ struct journal_entry_pin_list * pin_list ;
834+ u64 seq ;
835+
836+ spin_lock (& j -> lock );
837+ fifo_for_each_entry_ptr (pin_list , & j -> pin , seq ) {
838+ if (seq > seq_to_flush )
839+ break ;
840+
841+ for (unsigned i = 0 ; i < JOURNAL_PIN_TYPE_NR ; i ++ )
842+ if ((BIT (i ) & types ) &&
843+ (!list_empty (& pin_list -> unflushed [i ]) ||
844+ !list_empty (& pin_list -> flushed [i ]))) {
845+ spin_unlock (& j -> lock );
846+ return true;
847+ }
848+ }
849+ spin_unlock (& j -> lock );
850+
851+ return false;
852+ }
853+
854+ static bool journal_flush_pins_or_still_flushing (struct journal * j , u64 seq_to_flush ,
855+ unsigned types )
856+ {
857+ return journal_flush_pins (j , seq_to_flush , types , 0 , 0 , 0 ) ||
858+ journal_pins_still_flushing (j , seq_to_flush , types );
859+ }
860+
819861static int journal_flush_done (struct journal * j , u64 seq_to_flush ,
820862 bool * did_work )
821863{
822- int ret ;
864+ int ret = 0 ;
823865
824866 ret = bch2_journal_error (j );
825867 if (ret )
826868 return ret ;
827869
828870 mutex_lock (& j -> reclaim_lock );
829871
830- if (journal_flush_pins (j , seq_to_flush ,
831- (1U << JOURNAL_PIN_key_cache )|
832- (1U << JOURNAL_PIN_other ), 0 , 0 , 0 ) ||
833- journal_flush_pins (j , seq_to_flush ,
834- (1U << JOURNAL_PIN_btree ), 0 , 0 , 0 ))
872+ if (journal_flush_pins_or_still_flushing (j , seq_to_flush ,
873+ BIT (JOURNAL_PIN_TYPE_key_cache )|
874+ BIT (JOURNAL_PIN_TYPE_other ))) {
875+ * did_work = true;
876+ goto unlock ;
877+ }
878+
879+ if (journal_flush_pins_or_still_flushing (j , seq_to_flush ,
880+ BIT (JOURNAL_PIN_TYPE_btree ))) {
835881 * did_work = true;
882+ goto unlock ;
883+ }
836884
837885 if (seq_to_flush > journal_cur_seq (j ))
838886 bch2_journal_entry_close (j );
@@ -847,6 +895,7 @@ static int journal_flush_done(struct journal *j, u64 seq_to_flush,
847895 !fifo_used (& j -> pin );
848896
849897 spin_unlock (& j -> lock );
898+ unlock :
850899 mutex_unlock (& j -> reclaim_lock );
851900
852901 return ret ;
@@ -860,7 +909,7 @@ bool bch2_journal_flush_pins(struct journal *j, u64 seq_to_flush)
860909 if (!test_bit (JOURNAL_running , & j -> flags ))
861910 return false;
862911
863- closure_wait_event (& j -> async_wait ,
912+ closure_wait_event (& j -> reclaim_flush_wait ,
864913 journal_flush_done (j , seq_to_flush , & did_work ));
865914
866915 return did_work ;
@@ -926,3 +975,54 @@ int bch2_journal_flush_device_pins(struct journal *j, int dev_idx)
926975
927976 return ret ;
928977}
978+
979+ bool bch2_journal_seq_pins_to_text (struct printbuf * out , struct journal * j , u64 * seq )
980+ {
981+ struct journal_entry_pin_list * pin_list ;
982+ struct journal_entry_pin * pin ;
983+
984+ spin_lock (& j -> lock );
985+ if (!test_bit (JOURNAL_running , & j -> flags )) {
986+ spin_unlock (& j -> lock );
987+ return true;
988+ }
989+
990+ * seq = max (* seq , j -> pin .front );
991+
992+ if (* seq >= j -> pin .back ) {
993+ spin_unlock (& j -> lock );
994+ return true;
995+ }
996+
997+ out -> atomic ++ ;
998+
999+ pin_list = journal_seq_pin (j , * seq );
1000+
1001+ prt_printf (out , "%llu: count %u\n" , * seq , atomic_read (& pin_list -> count ));
1002+ printbuf_indent_add (out , 2 );
1003+
1004+ prt_printf (out , "unflushed:\n" );
1005+ for (unsigned i = 0 ; i < ARRAY_SIZE (pin_list -> unflushed ); i ++ )
1006+ list_for_each_entry (pin , & pin_list -> unflushed [i ], list )
1007+ prt_printf (out , "\t%px %ps\n" , pin , pin -> flush );
1008+
1009+ prt_printf (out , "flushed:\n" );
1010+ for (unsigned i = 0 ; i < ARRAY_SIZE (pin_list -> flushed ); i ++ )
1011+ list_for_each_entry (pin , & pin_list -> flushed [i ], list )
1012+ prt_printf (out , "\t%px %ps\n" , pin , pin -> flush );
1013+
1014+ printbuf_indent_sub (out , 2 );
1015+
1016+ -- out -> atomic ;
1017+ spin_unlock (& j -> lock );
1018+
1019+ return false;
1020+ }
1021+
1022+ void bch2_journal_pins_to_text (struct printbuf * out , struct journal * j )
1023+ {
1024+ u64 seq = 0 ;
1025+
1026+ while (!bch2_journal_seq_pins_to_text (out , j , & seq ))
1027+ seq ++ ;
1028+ }
0 commit comments