summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-03 18:39:07 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2019-04-03 12:44:09 -0400
commit319b6fb9fc86790ab4712ca6540800291df7be41 (patch)
tree3bffd476be964bc80919e3b0043d797f1f9ed3d0
parent89c9412c5d108b329d100716896a91983788a1c2 (diff)
bcachefs: Separate discards from rest of journal reclaim
-rw-r--r--fs/bcachefs/journal.c13
-rw-r--r--fs/bcachefs/journal_reclaim.c8
-rw-r--r--fs/bcachefs/journal_reclaim.h1
-rw-r--r--fs/bcachefs/journal_types.h2
4 files changed, 22 insertions, 2 deletions
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 16ec417910da..48a1bc54ead1 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -322,6 +322,7 @@ static int __journal_res_get(struct journal *j, struct journal_res *res,
{
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct journal_buf *buf;
+ bool can_discard;
int ret;
retry:
if (journal_res_get_fast(j, res, flags))
@@ -370,18 +371,28 @@ retry:
!j->res_get_blocked_start)
j->res_get_blocked_start = local_clock() ?: 1;
+ can_discard = j->can_discard;
spin_unlock(&j->lock);
if (!ret)
goto retry;
+
if (ret == -ENOSPC) {
/*
* Journal is full - can't rely on reclaim from work item due to
* freezing:
*/
trace_journal_full(c);
- if (!(flags & JOURNAL_RES_GET_NONBLOCK))
+
+ if (!(flags & JOURNAL_RES_GET_NONBLOCK)) {
+ if (can_discard) {
+ bch2_journal_do_discards(j);
+ goto retry;
+ }
+
bch2_journal_reclaim_work(&j->reclaim_work.work);
+ }
+
ret = -EAGAIN;
}
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index 37275ff57b31..68050db7914a 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -44,6 +44,7 @@ void bch2_journal_space_available(struct journal *j)
unsigned unwritten_sectors = j->reservations.prev_buf_unwritten
? journal_prev_buf(j)->sectors
: 0;
+ bool can_discard = false;
int ret = 0;
lockdep_assert_held(&j->lock);
@@ -64,9 +65,14 @@ void bch2_journal_space_available(struct journal *j)
ja->bucket_seq[ja->dirty_idx_ondisk] < j->last_seq_ondisk)
ja->dirty_idx_ondisk = (ja->dirty_idx_ondisk + 1) % ja->nr;
+ if (ja->discard_idx != ja->dirty_idx_ondisk)
+ can_discard = true;
+
nr_online++;
}
+ j->can_discard = can_discard;
+
if (nr_online < c->opts.metadata_replicas_required) {
ret = -EROFS;
sectors_next_entry = 0;
@@ -155,7 +161,7 @@ static bool should_discard_bucket(struct journal *j, struct journal_device *ja)
* Advance ja->discard_idx as long as it points to buckets that are no longer
* dirty, issuing discards if necessary:
*/
-static void bch2_journal_do_discards(struct journal *j)
+void bch2_journal_do_discards(struct journal *j)
{
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct bch_dev *ca;
diff --git a/fs/bcachefs/journal_reclaim.h b/fs/bcachefs/journal_reclaim.h
index 1d688d6fa2cc..75117f2464c0 100644
--- a/fs/bcachefs/journal_reclaim.h
+++ b/fs/bcachefs/journal_reclaim.h
@@ -33,6 +33,7 @@ void bch2_journal_pin_add_if_older(struct journal *,
journal_pin_flush_fn);
void bch2_journal_pin_flush(struct journal *, struct journal_entry_pin *);
+void bch2_journal_do_discards(struct journal *);
void bch2_journal_reclaim_work(struct work_struct *);
void bch2_journal_flush_pins(struct journal *, u64);
diff --git a/fs/bcachefs/journal_types.h b/fs/bcachefs/journal_types.h
index 9f1db6d28cd9..cb848ff6e24b 100644
--- a/fs/bcachefs/journal_types.h
+++ b/fs/bcachefs/journal_types.h
@@ -209,6 +209,8 @@ struct journal {
/* protects advancing ja->discard_idx: */
struct mutex discard_lock;
+ bool can_discard;
+
unsigned write_delay_ms;
unsigned reclaim_delay_ms;