aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bcache/request.c
diff options
context:
space:
mode:
authorColy Li <colyli@suse.de>2018-03-18 20:36:25 -0400
committerJens Axboe <axboe@kernel.dk>2018-03-18 22:15:20 -0400
commitc7b7bd07404c52d8b9c6fd2fe794052ac367a818 (patch)
treef1030fd28b6c26fe397de72a8b7c8e5e7077d36d /drivers/md/bcache/request.c
parent27a40ab9269e79b55672312b324f8f29d94463d4 (diff)
bcache: add io_disable to struct cached_dev
If a bcache device is configured to writeback mode, current code does not handle write I/O errors on backing devices properly. In writeback mode, write request is written to cache device, and latter being flushed to backing device. If I/O failed when writing from cache device to the backing device, bcache code just ignores the error and upper layer code is NOT noticed that the backing device is broken. This patch tries to handle backing device failure like how the cache device failure is handled, - Add a error counter 'io_errors' and error limit 'error_limit' in struct cached_dev. Add another io_disable to struct cached_dev to disable I/Os on the problematic backing device. - When I/O error happens on backing device, increase io_errors counter. And if io_errors reaches error_limit, set cache_dev->io_disable to true, and stop the bcache device. The result is, if backing device is broken of disconnected, and I/O errors reach its error limit, backing device will be disabled and the associated bcache device will be removed from system. Changelog: v2: remove "bcache: " prefix in pr_error(), and use correct name string to print out bcache device gendisk name. v1: indeed this is new added in v2 patch set. Signed-off-by: Coly Li <colyli@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Michael Lyle <mlyle@lyle.org> Cc: Michael Lyle <mlyle@lyle.org> Cc: Junhui Tang <tang.junhui@zte.com.cn> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/md/bcache/request.c')
-rw-r--r--drivers/md/bcache/request.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index b4a5768afbe9..5a82237c7025 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -637,6 +637,8 @@ static void backing_request_endio(struct bio *bio)
637 637
638 if (bio->bi_status) { 638 if (bio->bi_status) {
639 struct search *s = container_of(cl, struct search, cl); 639 struct search *s = container_of(cl, struct search, cl);
640 struct cached_dev *dc = container_of(s->d,
641 struct cached_dev, disk);
640 /* 642 /*
641 * If a bio has REQ_PREFLUSH for writeback mode, it is 643 * If a bio has REQ_PREFLUSH for writeback mode, it is
642 * speically assembled in cached_dev_write() for a non-zero 644 * speically assembled in cached_dev_write() for a non-zero
@@ -657,6 +659,7 @@ static void backing_request_endio(struct bio *bio)
657 } 659 }
658 s->recoverable = false; 660 s->recoverable = false;
659 /* should count I/O error for backing device here */ 661 /* should count I/O error for backing device here */
662 bch_count_backing_io_errors(dc, bio);
660 } 663 }
661 664
662 bio_put(bio); 665 bio_put(bio);
@@ -1065,8 +1068,14 @@ static void detached_dev_end_io(struct bio *bio)
1065 bio_data_dir(bio), 1068 bio_data_dir(bio),
1066 &ddip->d->disk->part0, ddip->start_time); 1069 &ddip->d->disk->part0, ddip->start_time);
1067 1070
1068 kfree(ddip); 1071 if (bio->bi_status) {
1072 struct cached_dev *dc = container_of(ddip->d,
1073 struct cached_dev, disk);
1074 /* should count I/O error for backing device here */
1075 bch_count_backing_io_errors(dc, bio);
1076 }
1069 1077
1078 kfree(ddip);
1070 bio->bi_end_io(bio); 1079 bio->bi_end_io(bio);
1071} 1080}
1072 1081
@@ -1105,7 +1114,8 @@ static blk_qc_t cached_dev_make_request(struct request_queue *q,
1105 struct cached_dev *dc = container_of(d, struct cached_dev, disk); 1114 struct cached_dev *dc = container_of(d, struct cached_dev, disk);
1106 int rw = bio_data_dir(bio); 1115 int rw = bio_data_dir(bio);
1107 1116
1108 if (unlikely(d->c && test_bit(CACHE_SET_IO_DISABLE, &d->c->flags))) { 1117 if (unlikely((d->c && test_bit(CACHE_SET_IO_DISABLE, &d->c->flags)) ||
1118 dc->io_disable)) {
1109 bio->bi_status = BLK_STS_IOERR; 1119 bio->bi_status = BLK_STS_IOERR;
1110 bio_endio(bio); 1120 bio_endio(bio);
1111 return BLK_QC_T_NONE; 1121 return BLK_QC_T_NONE;