bcachefs: Ensure journal doesn't get stuck in nochanges mode
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 28 Oct 2021 22:22:25 +0000 (18:22 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:15 +0000 (17:09 -0400)
This tweaks the journal code to always act as if there's space available
in nochanges mode, when we're not going to be doing any writes. This
helps in recovering filesystems that won't mount because they need
journal replay and the journal has gotten stuck.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/journal.h
fs/bcachefs/journal_io.c
fs/bcachefs/journal_reclaim.c
fs/bcachefs/journal_types.h
fs/bcachefs/super.c

index 1d556790b38ee09d3eb2450efbc9904b9dd1dcb0..99fd253648bf675960d0f348169010a05744ff23 100644 (file)
@@ -446,6 +446,7 @@ static inline int bch2_journal_preres_get_fast(struct journal *j,
                ret = 0;
 
                if ((flags & JOURNAL_RES_GET_RESERVED) ||
+                   test_bit(JOURNAL_NOCHANGES, &j->flags) ||
                    new.reserved + d < new.remaining) {
                        new.reserved += d;
                        ret = 1;
index e797d6376a824e996152623487f8125aa99d439c..ed8d7f90b6071dc47cdaf80af5eb038531dbf322 100644 (file)
@@ -1512,7 +1512,7 @@ retry_alloc:
 
        w->devs_written = bch2_bkey_devs(bkey_i_to_s_c(&w->key));
 
-       if (c->opts.nochanges)
+       if (test_bit(JOURNAL_NOCHANGES, &j->flags))
                goto no_io;
 
        for_each_rw_member(ca, c, i)
index 0bc4681ccc24a31377457f5b79b4549eb256be58..3f417af16e5900f85a6ff788ae3364a489f4d378 100644 (file)
@@ -34,8 +34,10 @@ unsigned bch2_journal_dev_buckets_available(struct journal *j,
                                            struct journal_device *ja,
                                            enum journal_space_from from)
 {
-       unsigned available = (journal_space_from(ja, from) -
-                             ja->cur_idx - 1 + ja->nr) % ja->nr;
+       unsigned available = !test_bit(JOURNAL_NOCHANGES, &j->flags)
+               ? ((journal_space_from(ja, from) -
+                   ja->cur_idx - 1 + ja->nr) % ja->nr)
+               : ja->nr;
 
        /*
         * Don't use the last bucket unless writing the new last_seq
index cce02bad850cc9ce5e46f421a840047786812793..0647a53eb35c02baa4c23591957688d750ae89f1 100644 (file)
@@ -154,6 +154,7 @@ enum {
        JOURNAL_NEED_WRITE,
        JOURNAL_MAY_GET_UNRESERVED,
        JOURNAL_MAY_SKIP_FLUSH,
+       JOURNAL_NOCHANGES,
 };
 
 /* Embedded in struct bch_fs */
index ca2acb7c6134c5370b2395d824ff40528929fd35..501fe129ea9c5410297ddd78ff9583919a5f9435 100644 (file)
@@ -801,6 +801,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
            bch2_fs_fsio_init(c))
                goto err;
 
+       if (c->opts.nochanges)
+               set_bit(JOURNAL_NOCHANGES, &c->journal.flags);
+
        mi = bch2_sb_get_members(c->disk_sb.sb);
        for (i = 0; i < c->sb.nr_devices; i++)
                if (bch2_dev_exists(c->disk_sb.sb, mi, i) &&