163 lines
4.9 KiB
Diff
163 lines
4.9 KiB
Diff
From 70feb569f2ce915068ac3d2050b843322cb5218c Mon Sep 17 00:00:00 2001
|
|
From: Kent Overstreet <kent.overstreet@linux.dev>
|
|
Date: Wed, 4 Dec 2024 18:14:14 -0500
|
|
Subject: [PATCH 169/233] bcachefs: Journal write path refactoring, debug
|
|
improvements
|
|
Content-Type: text/plain; charset="utf-8"
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
|
|
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
|
|
---
|
|
fs/bcachefs/journal.c | 6 ++++
|
|
fs/bcachefs/journal_io.c | 70 ++++++++++++++++++++++------------------
|
|
2 files changed, 45 insertions(+), 31 deletions(-)
|
|
|
|
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
|
|
index dc66521964b7..04a9ccf76d75 100644
|
|
--- a/fs/bcachefs/journal.c
|
|
+++ b/fs/bcachefs/journal.c
|
|
@@ -1564,6 +1564,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
|
|
printbuf_indent_sub(out, 2);
|
|
|
|
for_each_member_device_rcu(c, ca, &c->rw_devs[BCH_DATA_journal]) {
|
|
+ if (!ca->mi.durability)
|
|
+ continue;
|
|
+
|
|
struct journal_device *ja = &ca->journal;
|
|
|
|
if (!test_bit(ca->dev_idx, c->rw_devs[BCH_DATA_journal].d))
|
|
@@ -1573,6 +1576,7 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
|
|
continue;
|
|
|
|
prt_printf(out, "dev %u:\n", ca->dev_idx);
|
|
+ prt_printf(out, "durability %u:\n", ca->mi.durability);
|
|
printbuf_indent_add(out, 2);
|
|
prt_printf(out, "nr\t%u\n", ja->nr);
|
|
prt_printf(out, "bucket size\t%u\n", ca->mi.bucket_size);
|
|
@@ -1584,6 +1588,8 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
|
|
printbuf_indent_sub(out, 2);
|
|
}
|
|
|
|
+ prt_printf(out, "replicas want %u need %u\n", c->opts.metadata_replicas, c->opts.metadata_replicas_required);
|
|
+
|
|
rcu_read_unlock();
|
|
|
|
--out->atomic;
|
|
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
|
|
index 9a1647297d11..2f4daa8bd498 100644
|
|
--- a/fs/bcachefs/journal_io.c
|
|
+++ b/fs/bcachefs/journal_io.c
|
|
@@ -1420,6 +1420,35 @@ int bch2_journal_read(struct bch_fs *c,
|
|
|
|
/* journal write: */
|
|
|
|
+static void journal_advance_devs_to_next_bucket(struct journal *j,
|
|
+ struct dev_alloc_list *devs,
|
|
+ unsigned sectors, u64 seq)
|
|
+{
|
|
+ struct bch_fs *c = container_of(j, struct bch_fs, journal);
|
|
+
|
|
+ darray_for_each(*devs, i) {
|
|
+ struct bch_dev *ca = rcu_dereference(c->devs[*i]);
|
|
+ if (!ca)
|
|
+ continue;
|
|
+
|
|
+ struct journal_device *ja = &ca->journal;
|
|
+
|
|
+ if (sectors > ja->sectors_free &&
|
|
+ sectors <= ca->mi.bucket_size &&
|
|
+ bch2_journal_dev_buckets_available(j, ja,
|
|
+ journal_space_discarded)) {
|
|
+ ja->cur_idx = (ja->cur_idx + 1) % ja->nr;
|
|
+ ja->sectors_free = ca->mi.bucket_size;
|
|
+
|
|
+ /*
|
|
+ * ja->bucket_seq[ja->cur_idx] must always have
|
|
+ * something sensible:
|
|
+ */
|
|
+ ja->bucket_seq[ja->cur_idx] = le64_to_cpu(seq);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
static void __journal_write_alloc(struct journal *j,
|
|
struct journal_buf *w,
|
|
struct dev_alloc_list *devs,
|
|
@@ -1429,9 +1458,6 @@ static void __journal_write_alloc(struct journal *j,
|
|
{
|
|
struct bch_fs *c = container_of(j, struct bch_fs, journal);
|
|
|
|
- if (*replicas >= replicas_want)
|
|
- return;
|
|
-
|
|
darray_for_each(*devs, i) {
|
|
struct bch_dev *ca = rcu_dereference(c->devs[*i]);
|
|
if (!ca)
|
|
@@ -1491,6 +1517,7 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w)
|
|
READ_ONCE(c->opts.metadata_replicas);
|
|
unsigned replicas_need = min_t(unsigned, replicas_want,
|
|
READ_ONCE(c->opts.metadata_replicas_required));
|
|
+ bool advance_done = false;
|
|
|
|
rcu_read_lock();
|
|
|
|
@@ -1502,45 +1529,26 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w)
|
|
replicas += ca->mi.durability;
|
|
}
|
|
|
|
-retry:
|
|
+retry_target:
|
|
devs = target_rw_devs(c, BCH_DATA_journal, target);
|
|
-
|
|
devs_sorted = bch2_dev_alloc_list(c, &j->wp.stripe, &devs);
|
|
-
|
|
+retry_alloc:
|
|
__journal_write_alloc(j, w, &devs_sorted, sectors, &replicas, replicas_want);
|
|
|
|
- if (replicas >= replicas_want)
|
|
+ if (likely(replicas >= replicas_want))
|
|
goto done;
|
|
|
|
- darray_for_each(devs_sorted, i) {
|
|
- struct bch_dev *ca = rcu_dereference(c->devs[*i]);
|
|
- if (!ca)
|
|
- continue;
|
|
-
|
|
- struct journal_device *ja = &ca->journal;
|
|
-
|
|
- if (sectors > ja->sectors_free &&
|
|
- sectors <= ca->mi.bucket_size &&
|
|
- bch2_journal_dev_buckets_available(j, ja,
|
|
- journal_space_discarded)) {
|
|
- ja->cur_idx = (ja->cur_idx + 1) % ja->nr;
|
|
- ja->sectors_free = ca->mi.bucket_size;
|
|
-
|
|
- /*
|
|
- * ja->bucket_seq[ja->cur_idx] must always have
|
|
- * something sensible:
|
|
- */
|
|
- ja->bucket_seq[ja->cur_idx] = le64_to_cpu(w->data->seq);
|
|
- }
|
|
+ if (!advance_done) {
|
|
+ journal_advance_devs_to_next_bucket(j, &devs_sorted, sectors, w->data->seq);
|
|
+ advance_done = true;
|
|
+ goto retry_alloc;
|
|
}
|
|
|
|
- __journal_write_alloc(j, w, &devs_sorted,
|
|
- sectors, &replicas, replicas_want);
|
|
-
|
|
if (replicas < replicas_want && target) {
|
|
/* Retry from all devices: */
|
|
target = 0;
|
|
- goto retry;
|
|
+ advance_done = false;
|
|
+ goto retry_target;
|
|
}
|
|
done:
|
|
rcu_read_unlock();
|
|
--
|
|
2.45.2
|
|
|