diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-11-19 21:40:35 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:46 -0400 |
commit | dab1e24867f0e694c8ab73c075d10676c2699d85 (patch) | |
tree | 294189f306bcc4db6955f73b6c2de03968a23bac /fs | |
parent | ff56d68cf9ea04504be94eb7a476efcb92028a42 (diff) | |
download | lwn-dab1e24867f0e694c8ab73c075d10676c2699d85.tar.gz lwn-dab1e24867f0e694c8ab73c075d10676c2699d85.zip |
bcachefs: Handle last journal write being torn
If the last journal write didn't complete sucessfully due to a torn
write, we'll detect it as a checksum error. In that case, we should just
pretend that journal entry was never written.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/journal_io.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 485fd6f3003b..d1deb0573ffd 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -1106,7 +1106,7 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq) struct bch_dev *ca; unsigned iter; struct printbuf buf = PRINTBUF; - bool degraded = false; + bool degraded = false, last_write_torn = false; u64 seq, last_seq = 0; int ret = 0; @@ -1142,8 +1142,13 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq) /* * Find most recent flush entry, and ignore newer non flush entries - * those entries will be blacklisted: + * + * + * XXX check for torn write on last journal entry */ genradix_for_each_reverse(&c->journal_entries, radix_iter, _i) { + int write = READ; + i = *_i; if (!i || i->ignore) @@ -1152,21 +1157,27 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq) if (!*start_seq) *blacklist_seq = *start_seq = le64_to_cpu(i->j.seq) + 1; - if (!JSET_NO_FLUSH(&i->j)) { - int write = READ; - if (journal_entry_err_on(le64_to_cpu(i->j.last_seq) > le64_to_cpu(i->j.seq), - c, &i->j, NULL, - "invalid journal entry: last_seq > seq (%llu > %llu)", - le64_to_cpu(i->j.last_seq), - le64_to_cpu(i->j.seq))) - i->j.last_seq = i->j.seq; - - last_seq = le64_to_cpu(i->j.last_seq); - *blacklist_seq = le64_to_cpu(i->j.seq) + 1; - break; + if (JSET_NO_FLUSH(&i->j)) { + journal_replay_free(c, i); + continue; } - journal_replay_free(c, i); + if (!last_write_torn && !i->csum_good) { + last_write_torn = true; + journal_replay_free(c, i); + continue; + } + + if (journal_entry_err_on(le64_to_cpu(i->j.last_seq) > le64_to_cpu(i->j.seq), + c, &i->j, NULL, + "invalid journal entry: last_seq > seq (%llu > %llu)", + le64_to_cpu(i->j.last_seq), + le64_to_cpu(i->j.seq))) + i->j.last_seq = i->j.seq; + + last_seq = le64_to_cpu(i->j.last_seq); + *blacklist_seq = le64_to_cpu(i->j.seq) + 1; + break; } if (!*start_seq) { |