summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-03-15 02:41:21 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-03-15 15:31:04 -0400
commit06bfb089b0496eac37a40a31d8e67e3718881a8d (patch)
treea4c09ed6bfcd2074c9dd61d0203e9f89c74c84a4
parent3985f5f4eff86ee667da7da6e36ca2c346f56be3 (diff)
bcachefs: Restore journal write point at startup
This patch tweaks the journal recovery path so that we start writing right after where we left off, instead of the next empty bucket. This is partly prep work for supporting zoned devices, but it's also good to do in general to avoid the journal completely filling up and getting stuck. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/journal_io.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index bacb8058f60a..abb3e657c965 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -909,6 +909,7 @@ static void bch2_journal_read_device(struct closure *cl)
struct bch_fs *c = ca->fs;
struct journal_list *jlist =
container_of(cl->parent, struct journal_list, cl);
+ struct journal_replay *r;
struct journal_read_buf buf = { NULL, 0 };
u64 min_seq = U64_MAX;
unsigned i;
@@ -944,11 +945,28 @@ static void bch2_journal_read_device(struct closure *cl)
* allocate
*/
while (ja->bucket_seq[ja->cur_idx] > min_seq &&
- ja->bucket_seq[ja->cur_idx] >
+ ja->bucket_seq[ja->cur_idx] ==
ja->bucket_seq[(ja->cur_idx + 1) % ja->nr])
ja->cur_idx = (ja->cur_idx + 1) % ja->nr;
- ja->sectors_free = 0;
+ ja->sectors_free = ca->mi.bucket_size;
+
+ mutex_lock(&jlist->lock);
+ list_for_each_entry(r, jlist->head, list) {
+ for (i = 0; i < r->nr_ptrs; i++) {
+ if (r->ptrs[i].dev == ca->dev_idx &&
+ sector_to_bucket(ca, r->ptrs[i].sector) == ja->buckets[ja->cur_idx]) {
+ unsigned wrote = (r->ptrs[i].sector % ca->mi.bucket_size) +
+ vstruct_sectors(&r->j, c->block_bits);
+
+ ja->sectors_free = min(ja->sectors_free,
+ ca->mi.bucket_size - wrote);
+ }
+ }
+ }
+ mutex_unlock(&jlist->lock);
+
+ BUG_ON(ja->sectors_free == ca->mi.bucket_size);
/*
* Set dirty_idx to indicate the entire journal is full and needs to be