bcachefs: Journal write path refactoring, debug improvements
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 4 Dec 2024 23:14:14 +0000 (18:14 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:22 +0000 (01:36 -0500)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/journal.c
fs/bcachefs/journal_io.c

index dc66521964b7523ced697c4b8fd727c35316ee5b..04a9ccf76d757aff32467db8073f1be170e8ea66 100644 (file)
@@ -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;
index 9a1647297d11789d7adb2618ba6c47d7a6c840b1..2f4daa8bd498b0f04b436e3adcd62452c11242b6 100644 (file)
@@ -1420,6 +1420,35 @@ fsck_err:
 
 /* 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();