aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bcache/request.c
diff options
context:
space:
mode:
authorRui Hua <huarui.dev@gmail.com>2018-01-08 15:21:18 -0500
committerJens Axboe <axboe@kernel.dk>2018-01-08 15:29:00 -0500
commitb221fc130c49c50f4c2250d22e873420765a9fa2 (patch)
tree1994ccd3584b94ca9b0f726c7fa18dc14fffbcde /drivers/md/bcache/request.c
parent550203e64c2f4b330211955a1c581b631fd2ebe4 (diff)
bcache: ret IOERR when read meets metadata error
The read request might meet error when searching the btree, but the error was not handled in cache_lookup(), and this kind of metadata failure will not go into cached_dev_read_error(), finally, the upper layer will receive bi_status=0. In this patch we judge the metadata error by the return value of bch_btree_map_keys(), there are two potential paths give rise to the error: 1. Because the btree is not totally cached in memery, we maybe get error when read btree node from cache device (see bch_btree_node_get()), the likely errno is -EIO, -ENOMEM 2. When read miss happens, bch_btree_insert_check_key() will be called to insert a "replace_key" to btree(see cached_dev_cache_miss(), just for doing preparatory work before insert the missed data to cache device), a failure can also happen in this situation, the likely errno is -ENOMEM bch_btree_map_keys() will return MAP_DONE in normal scenario, but we will get either -EIO or -ENOMEM in above two cases. if this happened, we should NOT recover data from backing device (when cache device is dirty) because we don't know whether bkeys the read request covered are all clean. And after that happened, s->iop.status is still its initially value(0) before we submit s->bio.bio, we set it to BLK_STS_IOERR, so it can go into cached_dev_read_error(), and finally it can be passed to upper layer, or recovered by reread from backing device. [edit by mlyle: patch formatting, word-wrap, comment spelling, commit log format] Signed-off-by: Hua Rui <huarui.dev@gmail.com> Reviewed-by: Michael Lyle <mlyle@lyle.org> Signed-off-by: Michael Lyle <mlyle@lyle.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/md/bcache/request.c')
-rw-r--r--drivers/md/bcache/request.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index c493fb947dc9..52b4ce24f9e2 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -576,6 +576,7 @@ static void cache_lookup(struct closure *cl)
576{ 576{
577 struct search *s = container_of(cl, struct search, iop.cl); 577 struct search *s = container_of(cl, struct search, iop.cl);
578 struct bio *bio = &s->bio.bio; 578 struct bio *bio = &s->bio.bio;
579 struct cached_dev *dc;
579 int ret; 580 int ret;
580 581
581 bch_btree_op_init(&s->op, -1); 582 bch_btree_op_init(&s->op, -1);
@@ -588,6 +589,27 @@ static void cache_lookup(struct closure *cl)
588 return; 589 return;
589 } 590 }
590 591
592 /*
593 * We might meet err when searching the btree, If that happens, we will
594 * get negative ret, in this scenario we should not recover data from
595 * backing device (when cache device is dirty) because we don't know
596 * whether bkeys the read request covered are all clean.
597 *
598 * And after that happened, s->iop.status is still its initial value
599 * before we submit s->bio.bio
600 */
601 if (ret < 0) {
602 BUG_ON(ret == -EINTR);
603 if (s->d && s->d->c &&
604 !UUID_FLASH_ONLY(&s->d->c->uuids[s->d->id])) {
605 dc = container_of(s->d, struct cached_dev, disk);
606 if (dc && atomic_read(&dc->has_dirty))
607 s->recoverable = false;
608 }
609 if (!s->iop.status)
610 s->iop.status = BLK_STS_IOERR;
611 }
612
591 closure_return(cl); 613 closure_return(cl);
592} 614}
593 615