| From decf498ad7beacad029e49685a44478e68e7a295 Mon Sep 17 00:00:00 2001 |
| From: Tang Junhui <tang.junhui.linux@gmail.com> |
| Date: Thu, 25 Apr 2019 00:48:41 +0800 |
| Subject: bcache: fix failure in journal relplay |
| |
| [ Upstream commit 631207314d88e9091be02fbdd1fdadb1ae2ed79a ] |
| |
| journal replay failed with messages: |
| Sep 10 19:10:43 ceph kernel: bcache: error on |
| bb379a64-e44e-4812-b91d-a5599871a3b1: bcache: journal entries |
| 2057493-2057567 missing! (replaying 2057493-2076601), disabling |
| caching |
| |
| The reason is in journal_reclaim(), when discard is enabled, we send |
| discard command and reclaim those journal buckets whose seq is old |
| than the last_seq_now, but before we write a journal with last_seq_now, |
| the machine is restarted, so the journal with the last_seq_now is not |
| written to the journal bucket, and the last_seq_wrote in the newest |
| journal is old than last_seq_now which we expect to be, so when we doing |
| replay, journals from last_seq_wrote to last_seq_now are missing. |
| |
| It's hard to write a journal immediately after journal_reclaim(), |
| and it harmless if those missed journal are caused by discarding |
| since those journals are already wrote to btree node. So, if miss |
| seqs are started from the beginning journal, we treat it as normal, |
| and only print a message to show the miss journal, and point out |
| it maybe caused by discarding. |
| |
| Patch v2 add a judgement condition to ignore the missed journal |
| only when discard enabled as Coly suggested. |
| |
| (Coly Li: rebase the patch with other changes in bch_journal_replay()) |
| |
| Signed-off-by: Tang Junhui <tang.junhui.linux@gmail.com> |
| Tested-by: Dennis Schridde <devurandom@gmx.net> |
| Signed-off-by: Coly Li <colyli@suse.de> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/md/bcache/journal.c | 25 +++++++++++++++++++++---- |
| 1 file changed, 21 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c |
| index 9e557164209c1..6c94fa0077968 100644 |
| --- a/drivers/md/bcache/journal.c |
| +++ b/drivers/md/bcache/journal.c |
| @@ -317,6 +317,18 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list) |
| } |
| } |
| |
| +bool is_discard_enabled(struct cache_set *s) |
| +{ |
| + struct cache *ca; |
| + unsigned int i; |
| + |
| + for_each_cache(ca, s, i) |
| + if (ca->discard) |
| + return true; |
| + |
| + return false; |
| +} |
| + |
| int bch_journal_replay(struct cache_set *s, struct list_head *list) |
| { |
| int ret = 0, keys = 0, entries = 0; |
| @@ -331,10 +343,15 @@ int bch_journal_replay(struct cache_set *s, struct list_head *list) |
| BUG_ON(i->pin && atomic_read(i->pin) != 1); |
| |
| if (n != i->j.seq) { |
| - pr_err("bcache: journal entries %llu-%llu missing! (replaying %llu-%llu)", |
| - n, i->j.seq - 1, start, end); |
| - ret = -EIO; |
| - goto err; |
| + if (n == start && is_discard_enabled(s)) |
| + pr_info("bcache: journal entries %llu-%llu may be discarded! (replaying %llu-%llu)", |
| + n, i->j.seq - 1, start, end); |
| + else { |
| + pr_err("bcache: journal entries %llu-%llu missing! (replaying %llu-%llu)", |
| + n, i->j.seq - 1, start, end); |
| + ret = -EIO; |
| + goto err; |
| + } |
| } |
| |
| for (k = i->j.start; |
| -- |
| 2.20.1 |
| |