diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-01-14 00:38:47 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:14 -0400 |
commit | 000de45996c4b0f9a7b4f2830c11ed584f473257 (patch) | |
tree | 8f0fa373b2770c0acfac23ee8cce7931b2684fbd | |
parent | ed4840308c9bd3f70e395bd6e37a410a96dcd883 (diff) |
bcachefs: fixes for getting stuck flushing journal pins
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/journal_reclaim.c | 43 | ||||
-rw-r--r-- | fs/bcachefs/util.h | 1 |
2 files changed, 20 insertions, 24 deletions
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c index 770a6e0c7d97..eaf77c77b2c4 100644 --- a/fs/bcachefs/journal_reclaim.c +++ b/fs/bcachefs/journal_reclaim.c @@ -65,6 +65,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, @@ -337,56 +340,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 094c35f40209..8bbb0e30d07f 100644 --- a/fs/bcachefs/util.h +++ b/fs/bcachefs/util.h @@ -11,6 +11,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> |