summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-10-28 18:22:25 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:15 -0400
commitfae1157d184084f1716a10273423f8e949d8471f (patch)
treefb5a654f7bdde8e55b8c78f04ea0d92f181d68a9
parent285b181ad460bb240041a9ca7935f9e884040405 (diff)
downloadlinux-stable-fae1157d184084f1716a10273423f8e949d8471f.tar.gz
linux-stable-fae1157d184084f1716a10273423f8e949d8471f.tar.bz2
linux-stable-fae1157d184084f1716a10273423f8e949d8471f.zip
bcachefs: Ensure journal doesn't get stuck in nochanges mode
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>
-rw-r--r--fs/bcachefs/journal.h1
-rw-r--r--fs/bcachefs/journal_io.c2
-rw-r--r--fs/bcachefs/journal_reclaim.c6
-rw-r--r--fs/bcachefs/journal_types.h1
-rw-r--r--fs/bcachefs/super.c3
5 files changed, 10 insertions, 3 deletions
diff --git a/fs/bcachefs/journal.h b/fs/bcachefs/journal.h
index 1d556790b38e..99fd253648bf 100644
--- a/fs/bcachefs/journal.h
+++ b/fs/bcachefs/journal.h
@@ -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;
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index e797d6376a82..ed8d7f90b607 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -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)
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index 0bc4681ccc24..3f417af16e59 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -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
diff --git a/fs/bcachefs/journal_types.h b/fs/bcachefs/journal_types.h
index cce02bad850c..0647a53eb35c 100644
--- a/fs/bcachefs/journal_types.h
+++ b/fs/bcachefs/journal_types.h
@@ -154,6 +154,7 @@ enum {
JOURNAL_NEED_WRITE,
JOURNAL_MAY_GET_UNRESERVED,
JOURNAL_MAY_SKIP_FLUSH,
+ JOURNAL_NOCHANGES,
};
/* Embedded in struct bch_fs */
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index ca2acb7c6134..501fe129ea9c 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -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) &&