@@ -1604,13 +1604,36 @@ int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
16041604 return ret ;
16051605}
16061606
1607+ struct discard_buckets_state {
1608+ u64 seen ;
1609+ u64 open ;
1610+ u64 need_journal_commit ;
1611+ u64 discarded ;
1612+ struct bch_dev * ca ;
1613+ u64 need_journal_commit_this_dev ;
1614+ };
1615+
1616+ static void discard_buckets_next_dev (struct bch_fs * c , struct discard_buckets_state * s , struct bch_dev * ca )
1617+ {
1618+ if (s -> ca == ca )
1619+ return ;
1620+
1621+ if (s -> ca && s -> need_journal_commit_this_dev >
1622+ bch2_dev_usage_read (s -> ca ).d [BCH_DATA_free ].buckets )
1623+ bch2_journal_flush_async (& c -> journal , NULL );
1624+
1625+ if (s -> ca )
1626+ percpu_ref_put (& s -> ca -> ref );
1627+ if (ca )
1628+ percpu_ref_get (& ca -> ref );
1629+ s -> ca = ca ;
1630+ s -> need_journal_commit_this_dev = 0 ;
1631+ }
1632+
16071633static int bch2_discard_one_bucket (struct btree_trans * trans ,
16081634 struct btree_iter * need_discard_iter ,
16091635 struct bpos * discard_pos_done ,
1610- u64 * seen ,
1611- u64 * open ,
1612- u64 * need_journal_commit ,
1613- u64 * discarded )
1636+ struct discard_buckets_state * s )
16141637{
16151638 struct bch_fs * c = trans -> c ;
16161639 struct bpos pos = need_discard_iter -> pos ;
@@ -1622,20 +1645,24 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
16221645 int ret = 0 ;
16231646
16241647 ca = bch_dev_bkey_exists (c , pos .inode );
1648+
16251649 if (!percpu_ref_tryget (& ca -> io_ref )) {
16261650 bch2_btree_iter_set_pos (need_discard_iter , POS (pos .inode + 1 , 0 ));
16271651 return 0 ;
16281652 }
16291653
1654+ discard_buckets_next_dev (c , s , ca );
1655+
16301656 if (bch2_bucket_is_open_safe (c , pos .inode , pos .offset )) {
1631- ( * open ) ++ ;
1657+ s -> open ++ ;
16321658 goto out ;
16331659 }
16341660
16351661 if (bch2_bucket_needs_journal_commit (& c -> buckets_waiting_for_journal ,
16361662 c -> journal .flushed_seq_ondisk ,
16371663 pos .inode , pos .offset )) {
1638- (* need_journal_commit )++ ;
1664+ s -> need_journal_commit ++ ;
1665+ s -> need_journal_commit_this_dev ++ ;
16391666 goto out ;
16401667 }
16411668
@@ -1711,9 +1738,9 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
17111738 goto out ;
17121739
17131740 count_event (c , bucket_discard );
1714- ( * discarded ) ++ ;
1741+ s -> discarded ++ ;
17151742out :
1716- ( * seen ) ++ ;
1743+ s -> seen ++ ;
17171744 bch2_trans_iter_exit (trans , & iter );
17181745 percpu_ref_put (& ca -> io_ref );
17191746 printbuf_exit (& buf );
@@ -1723,7 +1750,7 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
17231750static void bch2_do_discards_work (struct work_struct * work )
17241751{
17251752 struct bch_fs * c = container_of (work , struct bch_fs , discard_work );
1726- u64 seen = 0 , open = 0 , need_journal_commit = 0 , discarded = 0 ;
1753+ struct discard_buckets_state s = {} ;
17271754 struct bpos discard_pos_done = POS_MAX ;
17281755 int ret ;
17291756
@@ -1735,19 +1762,14 @@ static void bch2_do_discards_work(struct work_struct *work)
17351762 ret = bch2_trans_run (c ,
17361763 for_each_btree_key (trans , iter ,
17371764 BTREE_ID_need_discard , POS_MIN , 0 , k ,
1738- bch2_discard_one_bucket (trans , & iter , & discard_pos_done ,
1739- & seen ,
1740- & open ,
1741- & need_journal_commit ,
1742- & discarded )));
1743-
1744- if (need_journal_commit * 2 > seen )
1745- bch2_journal_flush_async (& c -> journal , NULL );
1765+ bch2_discard_one_bucket (trans , & iter , & discard_pos_done , & s )));
17461766
1747- bch2_write_ref_put (c , BCH_WRITE_REF_discard );
1767+ discard_buckets_next_dev (c , & s , NULL );
17481768
1749- trace_discard_buckets (c , seen , open , need_journal_commit , discarded ,
1769+ trace_discard_buckets (c , s . seen , s . open , s . need_journal_commit , s . discarded ,
17501770 bch2_err_str (ret ));
1771+
1772+ bch2_write_ref_put (c , BCH_WRITE_REF_discard );
17511773}
17521774
17531775void bch2_do_discards (struct bch_fs * c )
0 commit comments