summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-01-07 17:09:26 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2018-05-22 00:44:18 -0400
commit0318b62d732011e2b241db25efd9feade5b9ad13 (patch)
treeb6da539f63abe29ef57736dde01e5712b0b9de79
parent068e3da3565aeb3b808ce66b92e01ab847635abf (diff)
bcachefs: fix a deadlock in bch2_journal_flush_pins()
-rw-r--r--fs/bcachefs/journal.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index ed2753304aab..e8756cd8e01b 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -1223,6 +1223,8 @@ static enum {
buf = &j->buf[old.idx];
buf->data->u64s = cpu_to_le32(old.cur_entry_offset);
+
+ /* XXX: why set this here, and not in journal_write()? */
buf->data->last_seq = cpu_to_le64(last_seq(j));
j->prev_buf_sectors =
@@ -1732,6 +1734,7 @@ static inline void __journal_pin_add(struct journal *j,
list_add(&pin->list, &pin_list->list);
else
INIT_LIST_HEAD(&pin->list);
+ wake_up(&j->wait);
}
static void journal_pin_add_entry(struct journal *j,
@@ -1878,10 +1881,16 @@ void bch2_journal_flush_pins(struct journal *j, u64 seq_to_flush)
*/
if (!test_bit(JOURNAL_REPLAY_DONE, &j->flags))
return;
-
+again:
+ /* flushing a journal pin might cause a new one to be added: */
wait_event(j->wait,
+ (pin = journal_get_next_pin(j, seq_to_flush, &pin_seq)) ||
journal_flush_done(j, seq_to_flush) ||
bch2_journal_error(j));
+ if (pin) {
+ pin->flush(j, pin, pin_seq);
+ goto again;
+ }
}
int bch2_journal_flush_all_pins(struct journal *j)