summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-05-27 23:16:25 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-05-27 23:46:10 -0400
commit8ea0358a147c09a608a83bff2beba9729525ccb5 (patch)
tree870e2faa426dfa0eb8ee7add8ce52d7efe1fe753
parent7a37d5ae827d4d7b0e9b015944b8284610984349 (diff)
bcachefs: Fix journal write error path
Journal write errors were racing with the submission path - potentially causing writes to other replicas to not get submitted. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/journal_io.c21
-rw-r--r--fs/bcachefs/journal_types.h1
2 files changed, 12 insertions, 10 deletions
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index b40952248a5d..691b559e682c 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -1233,8 +1233,6 @@ static void journal_write_done(struct closure *cl)
struct journal *j = container_of(cl, struct journal, io);
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct journal_buf *w = journal_last_unwritten_buf(j);
- struct bch_devs_list devs =
- bch2_bkey_devs(bkey_i_to_s_c(&w->key));
struct bch_replicas_padded replicas;
union journal_res_state old, new;
u64 v, seq;
@@ -1242,11 +1240,12 @@ static void journal_write_done(struct closure *cl)
bch2_time_stats_update(j->write_time, j->write_start_time);
- if (!devs.nr) {
+ if (!w->devs_written.nr) {
bch_err(c, "unable to write journal to sufficient devices");
err = -EIO;
} else {
- bch2_devlist_to_replicas(&replicas.e, BCH_DATA_journal, devs);
+ bch2_devlist_to_replicas(&replicas.e, BCH_DATA_journal,
+ w->devs_written);
if (bch2_mark_replicas(c, &replicas.e))
err = -EIO;
}
@@ -1258,7 +1257,7 @@ static void journal_write_done(struct closure *cl)
seq = le64_to_cpu(w->data->seq);
if (seq >= j->pin.front)
- journal_seq_pin(j, seq)->devs = devs;
+ journal_seq_pin(j, seq)->devs = w->devs_written;
j->seq_ondisk = seq;
if (err && (!j->err_seq || seq < j->err_seq))
@@ -1308,15 +1307,15 @@ static void journal_write_endio(struct bio *bio)
{
struct bch_dev *ca = bio->bi_private;
struct journal *j = &ca->fs->journal;
+ struct journal_buf *w = journal_last_unwritten_buf(j);
+ unsigned long flags;
- if (bch2_dev_io_err_on(bio->bi_status, ca, "journal write error: %s",
+ if (bch2_dev_io_err_on(bio->bi_status, ca, "error writing journal entry %llu: %s",
+ le64_to_cpu(w->data->seq),
bch2_blk_status_to_str(bio->bi_status)) ||
bch2_meta_write_fault("journal")) {
- struct journal_buf *w = journal_last_unwritten_buf(j);
- unsigned long flags;
-
spin_lock_irqsave(&j->err_lock, flags);
- bch2_bkey_drop_device(bkey_i_to_s(&w->key), ca->dev_idx);
+ bch2_dev_list_drop_dev(&w->devs_written, ca->dev_idx);
spin_unlock_irqrestore(&j->err_lock, flags);
}
@@ -1334,6 +1333,8 @@ static void do_journal_write(struct closure *cl)
struct bio *bio;
unsigned sectors = vstruct_sectors(w->data, c->block_bits);
+ w->devs_written = bch2_bkey_devs(bkey_i_to_s_c(&w->key));
+
extent_for_each_ptr(bkey_i_to_s_extent(&w->key), ptr) {
ca = bch_dev_bkey_exists(c, ptr->dev);
if (!percpu_ref_tryget(&ca->io_ref)) {
diff --git a/fs/bcachefs/journal_types.h b/fs/bcachefs/journal_types.h
index cacab22a35c1..61674ae1ab5f 100644
--- a/fs/bcachefs/journal_types.h
+++ b/fs/bcachefs/journal_types.h
@@ -21,6 +21,7 @@ struct journal_buf {
struct jset *data;
__BKEY_PADDED(key, BCH_REPLICAS_MAX);
+ struct bch_devs_list devs_written;
struct closure_waitlist wait;
u64 last_seq; /* copy of data->last_seq */