summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-01-14 00:38:47 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:14 -0400
commit000de45996c4b0f9a7b4f2830c11ed584f473257 (patch)
tree8f0fa373b2770c0acfac23ee8cce7931b2684fbd /fs
parented4840308c9bd3f70e395bd6e37a410a96dcd883 (diff)
downloadlinux-stable-000de45996c4b0f9a7b4f2830c11ed584f473257.tar.gz
linux-stable-000de45996c4b0f9a7b4f2830c11ed584f473257.tar.bz2
linux-stable-000de45996c4b0f9a7b4f2830c11ed584f473257.zip
bcachefs: fixes for getting stuck flushing journal pins
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-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 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>