Skip to content

Commit 9e90335

Browse files
author
Kent Overstreet
committed
bcachefs: Fix discard path journal flushing
The discard path is supposed to issue journal flushes when there's too many buckets empty buckets that need a journal commit before they can be written to again, but at some point this code seems to have been lost. Bring it back with a new optimization to make sure we don't issue too many journal flushes: the journal now tracks the sequence number of the most recent flush in progress, which the discard path uses when deciding which buckets need a journal flush. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 2ef995d commit 9e90335

File tree

8 files changed

+55
-35
lines changed

8 files changed

+55
-35
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,7 +1803,6 @@ struct discard_buckets_state {
18031803
u64 open;
18041804
u64 need_journal_commit;
18051805
u64 discarded;
1806-
u64 need_journal_commit_this_dev;
18071806
};
18081807

18091808
static int bch2_discard_one_bucket(struct btree_trans *trans,
@@ -1827,11 +1826,11 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
18271826
goto out;
18281827
}
18291828

1830-
if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal,
1831-
c->journal.flushed_seq_ondisk,
1832-
pos.inode, pos.offset)) {
1833-
s->need_journal_commit++;
1834-
s->need_journal_commit_this_dev++;
1829+
u64 seq_ready = bch2_bucket_journal_seq_ready(&c->buckets_waiting_for_journal,
1830+
pos.inode, pos.offset);
1831+
if (seq_ready > c->journal.flushed_seq_ondisk) {
1832+
if (seq_ready > c->journal.flushing_seq)
1833+
s->need_journal_commit++;
18351834
goto out;
18361835
}
18371836

@@ -1865,23 +1864,24 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
18651864
discard_locked = true;
18661865
}
18671866

1868-
if (!bkey_eq(*discard_pos_done, iter.pos) &&
1869-
ca->mi.discard && !c->opts.nochanges) {
1870-
/*
1871-
* This works without any other locks because this is the only
1872-
* thread that removes items from the need_discard tree
1873-
*/
1874-
bch2_trans_unlock_long(trans);
1875-
blkdev_issue_discard(ca->disk_sb.bdev,
1876-
k.k->p.offset * ca->mi.bucket_size,
1877-
ca->mi.bucket_size,
1878-
GFP_KERNEL);
1879-
*discard_pos_done = iter.pos;
1867+
if (!bkey_eq(*discard_pos_done, iter.pos)) {
18801868
s->discarded++;
1869+
*discard_pos_done = iter.pos;
18811870

1882-
ret = bch2_trans_relock_notrace(trans);
1883-
if (ret)
1884-
goto out;
1871+
if (ca->mi.discard && !c->opts.nochanges) {
1872+
/*
1873+
* This works without any other locks because this is the only
1874+
* thread that removes items from the need_discard tree
1875+
*/
1876+
bch2_trans_unlock_long(trans);
1877+
blkdev_issue_discard(ca->disk_sb.bdev,
1878+
k.k->p.offset * ca->mi.bucket_size,
1879+
ca->mi.bucket_size,
1880+
GFP_KERNEL);
1881+
ret = bch2_trans_relock_notrace(trans);
1882+
if (ret)
1883+
goto out;
1884+
}
18851885
}
18861886

18871887
SET_BCH_ALLOC_V4_NEED_DISCARD(&a->v, false);
@@ -1929,6 +1929,9 @@ static void bch2_do_discards_work(struct work_struct *work)
19291929
POS(ca->dev_idx, U64_MAX), 0, k,
19301930
bch2_discard_one_bucket(trans, ca, &iter, &discard_pos_done, &s, false)));
19311931

1932+
if (s.need_journal_commit > dev_buckets_available(ca, BCH_WATERMARK_normal))
1933+
bch2_journal_flush_async(&c->journal, NULL);
1934+
19321935
trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded,
19331936
bch2_err_str(ret));
19341937

@@ -2024,7 +2027,7 @@ static void bch2_do_discards_fast_work(struct work_struct *work)
20242027
break;
20252028
}
20262029

2027-
trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret));
2030+
trace_discard_buckets_fast(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret));
20282031

20292032
bch2_trans_put(trans);
20302033
percpu_ref_put(&ca->io_ref);

fs/bcachefs/alloc_foreground.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,12 @@ static inline bool may_alloc_bucket(struct bch_fs *c,
205205
return false;
206206
}
207207

208-
if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal,
209-
c->journal.flushed_seq_ondisk, bucket.inode, bucket.offset)) {
208+
u64 journal_seq_ready =
209+
bch2_bucket_journal_seq_ready(&c->buckets_waiting_for_journal,
210+
bucket.inode, bucket.offset);
211+
if (journal_seq_ready > c->journal.flushed_seq_ondisk) {
212+
if (journal_seq_ready > c->journal.flushing_seq)
213+
s->need_journal_commit++;
210214
s->skipped_need_journal_commit++;
211215
return false;
212216
}
@@ -570,7 +574,7 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans,
570574
? bch2_bucket_alloc_freelist(trans, ca, watermark, &s, cl)
571575
: bch2_bucket_alloc_early(trans, ca, watermark, &s, cl);
572576

573-
if (s.skipped_need_journal_commit * 2 > avail)
577+
if (s.need_journal_commit * 2 > avail)
574578
bch2_journal_flush_async(&c->journal, NULL);
575579

576580
if (!ob && s.btree_bitmap != BTREE_BITMAP_ANY) {

fs/bcachefs/alloc_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ struct bucket_alloc_state {
1818
u64 buckets_seen;
1919
u64 skipped_open;
2020
u64 skipped_need_journal_commit;
21+
u64 need_journal_commit;
2122
u64 skipped_nocow;
2223
u64 skipped_nouse;
2324
u64 skipped_mi_btree_bitmap;

fs/bcachefs/buckets_waiting_for_journal.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,21 @@ static void bucket_table_init(struct buckets_waiting_for_journal_table *t, size_
2222
memset(t->d, 0, sizeof(t->d[0]) << t->bits);
2323
}
2424

25-
bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *b,
26-
u64 flushed_seq,
27-
unsigned dev, u64 bucket)
25+
u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *b,
26+
unsigned dev, u64 bucket)
2827
{
2928
struct buckets_waiting_for_journal_table *t;
3029
u64 dev_bucket = (u64) dev << 56 | bucket;
31-
bool ret = false;
32-
unsigned i;
30+
u64 ret = 0;
3331

3432
mutex_lock(&b->lock);
3533
t = b->t;
3634

37-
for (i = 0; i < ARRAY_SIZE(t->hash_seeds); i++) {
35+
for (unsigned i = 0; i < ARRAY_SIZE(t->hash_seeds); i++) {
3836
struct bucket_hashed *h = bucket_hash(t, i, dev_bucket);
3937

4038
if (h->dev_bucket == dev_bucket) {
41-
ret = h->journal_seq > flushed_seq;
39+
ret = h->journal_seq;
4240
break;
4341
}
4442
}

fs/bcachefs/buckets_waiting_for_journal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
#include "buckets_waiting_for_journal_types.h"
66

7-
bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *,
8-
u64, unsigned, u64);
7+
u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *,
8+
unsigned, u64);
99
int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *,
1010
u64, unsigned, u64, u64);
1111

fs/bcachefs/journal.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ int bch2_journal_flush_seq_async(struct journal *j, u64 seq,
796796
}
797797

798798
buf->must_flush = true;
799+
j->flushing_seq = max(j->flushing_seq, seq);
799800

800801
if (parent && !closure_wait(&buf->wait, parent))
801802
BUG();

fs/bcachefs/journal_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ struct journal {
237237
/* seq, last_seq from the most recent journal entry successfully written */
238238
u64 seq_ondisk;
239239
u64 flushed_seq_ondisk;
240+
u64 flushing_seq;
240241
u64 last_seq_ondisk;
241242
u64 err_seq;
242243
u64 last_empty_seq;

fs/bcachefs/trace.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ DEFINE_EVENT(fs_str, bucket_alloc_fail,
727727
TP_ARGS(c, str)
728728
);
729729

730-
TRACE_EVENT(discard_buckets,
730+
DECLARE_EVENT_CLASS(discard_buckets_class,
731731
TP_PROTO(struct bch_fs *c, u64 seen, u64 open,
732732
u64 need_journal_commit, u64 discarded, const char *err),
733733
TP_ARGS(c, seen, open, need_journal_commit, discarded, err),
@@ -759,6 +759,18 @@ TRACE_EVENT(discard_buckets,
759759
__entry->err)
760760
);
761761

762+
DEFINE_EVENT(discard_buckets_class, discard_buckets,
763+
TP_PROTO(struct bch_fs *c, u64 seen, u64 open,
764+
u64 need_journal_commit, u64 discarded, const char *err),
765+
TP_ARGS(c, seen, open, need_journal_commit, discarded, err)
766+
);
767+
768+
DEFINE_EVENT(discard_buckets_class, discard_buckets_fast,
769+
TP_PROTO(struct bch_fs *c, u64 seen, u64 open,
770+
u64 need_journal_commit, u64 discarded, const char *err),
771+
TP_ARGS(c, seen, open, need_journal_commit, discarded, err)
772+
);
773+
762774
TRACE_EVENT(bucket_invalidate,
763775
TP_PROTO(struct bch_fs *c, unsigned dev, u64 bucket, u32 sectors),
764776
TP_ARGS(c, dev, bucket, sectors),

0 commit comments

Comments
 (0)