summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe2017-03-24 19:04:19 +0100
committerJens Axboe2017-03-24 22:42:47 +0100
commit93efe9817e651607d83e5f100076ae62d0ce0b93 (patch)
treeb83b77bd955222ba6783df11bd3807aac5e43c9a
parentMerge tag 'vfio-v4.11-rc4' of git://github.com/awilliam/linux-vfio (diff)
downloadkernel-qcow2-linux-93efe9817e651607d83e5f100076ae62d0ce0b93.tar.gz
kernel-qcow2-linux-93efe9817e651607d83e5f100076ae62d0ce0b93.tar.xz
kernel-qcow2-linux-93efe9817e651607d83e5f100076ae62d0ce0b93.zip
blk-mq: include errors in did_work calculation
Currently we return true in blk_mq_dispatch_rq_list() if we queued IO successfully, but we really want to return whether or not the we made progress. Progress includes if we got an error return. If we don't, this can lead to a hang in blk_mq_sched_dispatch_requests() when a driver is draining IO by returning BLK_MQ_QUEUE_ERROR instead of manually ending the IO in error and return BLK_MQ_QUEUE_OK. Tested-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com> Reviewed-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-mq.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 08a49c69738b..6b6e7bc041db 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -969,7 +969,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
struct request *rq;
LIST_HEAD(driver_list);
struct list_head *dptr;
- int queued, ret = BLK_MQ_RQ_QUEUE_OK;
+ int errors, queued, ret = BLK_MQ_RQ_QUEUE_OK;
/*
* Start off with dptr being NULL, so we start the first request
@@ -980,7 +980,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
/*
* Now process all the entries, sending them to the driver.
*/
- queued = 0;
+ errors = queued = 0;
while (!list_empty(list)) {
struct blk_mq_queue_data bd;
@@ -1037,6 +1037,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
default:
pr_err("blk-mq: bad return on queue: %d\n", ret);
case BLK_MQ_RQ_QUEUE_ERROR:
+ errors++;
rq->errors = -EIO;
blk_mq_end_request(rq, rq->errors);
break;
@@ -1088,7 +1089,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
blk_mq_run_hw_queue(hctx, true);
}
- return queued != 0;
+ return (queued + errors) != 0;
}
static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)