diff options
-rw-r--r-- | drivers/md/bcache/journal.c | 47 | ||||
-rw-r--r-- | drivers/md/bcache/journal_types.h | 3 |
2 files changed, 32 insertions, 18 deletions
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index d20f2d2a143f..cce103a8c59f 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -472,6 +472,8 @@ const char *bch_journal_read(struct cache_set *c, struct list_head *list) c->journal.pin.back = j->seq - j->last_seq + 1; c->journal.seq = j->seq; + c->journal.last_seq_ondisk = j->last_seq; + BUG_ON(last_seq(&c->journal) != j->last_seq); i = list_first_entry(list, struct journal_replay, list); @@ -664,7 +666,7 @@ static void journal_discard_work(struct work_struct *work) submit_bio(&ja->discard_bio); } -static bool do_journal_discard(struct cache *ca) +static void do_journal_discard(struct cache *ca) { struct journal_device *ja = &ca->journal; struct bio *bio = &ja->discard_bio; @@ -672,12 +674,12 @@ static bool do_journal_discard(struct cache *ca) if (!CACHE_DISCARD(&ca->mi) || !blk_queue_discard(bdev_get_queue(ca->disk_sb.bdev))) { ja->discard_idx = ja->last_idx; - return true; + return; } switch (atomic_read(&ja->discard_in_flight)) { case DISCARD_IN_FLIGHT: - return false; + break; case DISCARD_DONE: ja->discard_idx = (ja->discard_idx + 1) % @@ -688,7 +690,7 @@ static bool do_journal_discard(struct cache *ca) case DISCARD_READY: if (ja->discard_idx == ja->last_idx) - return true; + break; atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT); @@ -707,11 +709,9 @@ static bool do_journal_discard(struct cache *ca) INIT_WORK(&ja->discard_work, journal_discard_work); schedule_work(&ja->discard_work); - return false; - + break; default: BUG(); - return true; } } @@ -833,11 +833,9 @@ static void journal_reclaim_work(struct work_struct *work) * * Called from IO submission context, does not block. Cleans up after btree * write completions by advancing the journal pin and each cache's last_idx, - * and kicking off discards. - * - * Returns true if background reclaim needs to run. + * kicking off discards and background reclaim as necessary. */ -static bool journal_reclaim_fast(struct cache_set *c) +static void journal_reclaim_fast(struct cache_set *c) { struct cache *ca; u64 last_seq; @@ -858,7 +856,7 @@ static bool journal_reclaim_fast(struct cache_set *c) if (fifo_free(&c->journal.pin) <= (c->journal.pin.size >> 6)) need_reclaim = true; - last_seq = last_seq(&c->journal); + last_seq = c->journal.last_seq_ondisk; rcu_read_lock(); @@ -886,7 +884,8 @@ static bool journal_reclaim_fast(struct cache_set *c) rcu_read_unlock(); - return need_reclaim; + if (need_reclaim) + queue_work(system_long_wq, &c->journal.reclaim_work); } /** @@ -909,8 +908,7 @@ static void journal_next_bucket(struct cache_set *c) BUG_ON(c->journal.u64s_remaining); BUG_ON(c->journal.cur->data->u64s); - if (journal_reclaim_fast(c)) - queue_work(system_long_wq, &c->journal.reclaim_work); + journal_reclaim_fast(c); rcu_read_lock(); @@ -930,7 +928,7 @@ static void journal_next_bucket(struct cache_set *c) */ group_for_each_cache_rcu(ca, &c->cache_tiers[0], iter) { struct journal_device *ja = &ca->journal; - unsigned next = (ja->cur_idx + 1) % + unsigned next, remaining, nr_buckets = bch_nr_journal_buckets(&ca->sb); if (bch_extent_ptrs(e) == CACHE_SET_META_REPLICAS_WANT(&c->sb)) @@ -944,8 +942,18 @@ static void journal_next_bucket(struct cache_set *c) ca->sb.nr_this_dev)) continue; - /* No journal buckets available for writing on this device */ - if (next == ja->discard_idx) + next = (ja->cur_idx + 1) % nr_buckets; + remaining = (ja->discard_idx + nr_buckets - next) % nr_buckets; + + if (!remaining) + continue; + + /* + * Don't use the last bucket unless writing the new last_seq + * will make another bucket available: + */ + if (remaining == 1 && + ja->seq[(next + 1) % nr_buckets] >= last_seq(&c->journal)) continue; BUG_ON(bch_extent_ptrs(e) >= BKEY_EXTENT_PTRS_MAX); @@ -1018,6 +1026,8 @@ static void journal_write_done(struct closure *cl) ? &j->w[1] : &j->w[0]; + j->last_seq_ondisk = w->data->last_seq; + __closure_wake_up(&w->wait); atomic_set(&j->in_flight, 0); @@ -1294,6 +1304,7 @@ static bool __journal_res_get(struct cache_set *c, struct journal_res *res, /* Still no room, we have to wait */ spin_unlock(&c->journal.lock); trace_bcache_journal_full(c); + queue_work(system_long_wq, &c->journal.reclaim_work); return false; } } diff --git a/drivers/md/bcache/journal_types.h b/drivers/md/bcache/journal_types.h index e7a425d4e1fe..971af1e043ca 100644 --- a/drivers/md/bcache/journal_types.h +++ b/drivers/md/bcache/journal_types.h @@ -44,6 +44,9 @@ struct journal { /* Sequence number of most recent journal entry (last entry in @pin) */ u64 seq; + /* last_seq from the most recent journal entry written */ + u64 last_seq_ondisk; + /* * FIFO of journal entries whose btree updates have not yet been * written out. |