summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-01-14 00:38:47 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2019-04-03 12:44:02 -0400
commita858b75796dd5bb17ccb379b0d754bd010261ca2 (patch)
tree906fe7483a636b31a1c4d435694cd438926c2509
parenta437f50ee0c6e5d0b7f931d23a5c51259d79d723 (diff)
bcachefs: fixes for getting stuck flushing journal pins
-rw-r--r--fs/bcachefs/journal_reclaim.c43
-rw-r--r--fs/bcachefs/util.h1
2 files changed, 20 insertions, 24 deletions
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index d8d1b6b0e7dd..4a9973664a36 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -64,6 +64,9 @@ static inline void __journal_pin_drop(struct journal *j,
if (atomic_dec_and_test(&pin_list->count) &&
pin_list == &fifo_peek_front(&j->pin))
bch2_journal_reclaim_fast(j);
+ else if (fifo_used(&j->pin) == 1 &&
+ atomic_read(&pin_list->count) == 1)
+ journal_wake(j);
}
void bch2_journal_pin_drop(struct journal *j,
@@ -336,56 +339,48 @@ void bch2_journal_reclaim_work(struct work_struct *work)
msecs_to_jiffies(j->reclaim_delay_ms));
}
-static int journal_flush_done(struct journal *j, u64 seq_to_flush,
- struct journal_entry_pin **pin,
- u64 *pin_seq)
+static int journal_flush_done(struct journal *j, u64 seq_to_flush)
{
+ struct journal_entry_pin *pin;
+ u64 pin_seq;
int ret;
- *pin = NULL;
-
ret = bch2_journal_error(j);
if (ret)
return ret;
+ mutex_lock(&j->reclaim_lock);
spin_lock(&j->lock);
+
+ while ((pin = journal_get_next_pin(j, seq_to_flush, &pin_seq))) {
+ journal_pin_mark_flushing(j, pin, pin_seq);
+ spin_unlock(&j->lock);
+
+ journal_pin_flush(j, pin, pin_seq);
+
+ spin_lock(&j->lock);
+ }
/*
* If journal replay hasn't completed, the unreplayed journal entries
* hold refs on their corresponding sequence numbers
*/
- ret = (*pin = journal_get_next_pin(j, seq_to_flush, pin_seq)) != NULL ||
- !test_bit(JOURNAL_REPLAY_DONE, &j->flags) ||
+ ret = !test_bit(JOURNAL_REPLAY_DONE, &j->flags) ||
journal_last_seq(j) > seq_to_flush ||
(fifo_used(&j->pin) == 1 &&
atomic_read(&fifo_peek_front(&j->pin).count) == 1);
- if (*pin)
- journal_pin_mark_flushing(j, *pin, *pin_seq);
spin_unlock(&j->lock);
+ mutex_unlock(&j->reclaim_lock);
return ret;
}
void bch2_journal_flush_pins(struct journal *j, u64 seq_to_flush)
{
- struct journal_entry_pin *pin;
- u64 pin_seq;
-
if (!test_bit(JOURNAL_STARTED, &j->flags))
return;
- mutex_lock(&j->reclaim_lock);
-
- while (1) {
- wait_event(j->wait, journal_flush_done(j, seq_to_flush,
- &pin, &pin_seq));
- if (!pin)
- break;
-
- journal_pin_flush(j, pin, pin_seq);
- }
-
- mutex_unlock(&j->reclaim_lock);
+ closure_wait_event(&j->async_wait, journal_flush_done(j, seq_to_flush));
}
int bch2_journal_flush_device_pins(struct journal *j, int dev_idx)
diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h
index f1ab6aa6d48d..25d6750915e3 100644
--- a/fs/bcachefs/util.h
+++ b/fs/bcachefs/util.h
@@ -10,6 +10,7 @@
#include <linux/sched/clock.h>
#include <linux/llist.h>
#include <linux/log2.h>
+#include <linux/percpu.h>
#include <linux/ratelimit.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>