diff options
author | Ming Lei <ming.lei@redhat.com> | 2017-11-04 14:21:12 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2017-11-04 14:31:08 -0400 |
commit | 88022d7201e96b43f1754b0358fc6bcd8dbdcde1 (patch) | |
tree | ec0b9e2d1227a7101040f954aef16511a5b6fa46 | |
parent | 826a70a08b1210bbfdbda812ab43eb986e25b5c2 (diff) |
blk-mq: don't handle failure in .get_budget
It is enough to just check if we can get the budget via .get_budget().
And we don't need to deal with device state change in .get_budget().
For SCSI, one issue to be fixed is that we have to call
scsi_mq_uninit_cmd() to free allocated ressources if SCSI device fails
to handle the request. And it isn't enough to simply call
blk_mq_end_request() to do that if this request is marked as
RQF_DONTPREP.
Fixes: 0df21c86bdbf(scsi: implement .get_budget and .put_budget for blk-mq)
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | block/blk-mq-sched.c | 14 | ||||
-rw-r--r-- | block/blk-mq.c | 17 | ||||
-rw-r--r-- | block/blk-mq.h | 5 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 11 | ||||
-rw-r--r-- | include/linux/blk-mq.h | 2 |
5 files changed, 12 insertions, 37 deletions
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 7775f6b12fa9..13a27d4d1671 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c | |||
@@ -94,23 +94,18 @@ static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx) | |||
94 | 94 | ||
95 | do { | 95 | do { |
96 | struct request *rq; | 96 | struct request *rq; |
97 | blk_status_t ret; | ||
98 | 97 | ||
99 | if (e->type->ops.mq.has_work && | 98 | if (e->type->ops.mq.has_work && |
100 | !e->type->ops.mq.has_work(hctx)) | 99 | !e->type->ops.mq.has_work(hctx)) |
101 | break; | 100 | break; |
102 | 101 | ||
103 | ret = blk_mq_get_dispatch_budget(hctx); | 102 | if (!blk_mq_get_dispatch_budget(hctx)) |
104 | if (ret == BLK_STS_RESOURCE) | ||
105 | break; | 103 | break; |
106 | 104 | ||
107 | rq = e->type->ops.mq.dispatch_request(hctx); | 105 | rq = e->type->ops.mq.dispatch_request(hctx); |
108 | if (!rq) { | 106 | if (!rq) { |
109 | blk_mq_put_dispatch_budget(hctx); | 107 | blk_mq_put_dispatch_budget(hctx); |
110 | break; | 108 | break; |
111 | } else if (ret != BLK_STS_OK) { | ||
112 | blk_mq_end_request(rq, ret); | ||
113 | continue; | ||
114 | } | 109 | } |
115 | 110 | ||
116 | /* | 111 | /* |
@@ -146,22 +141,17 @@ static void blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx) | |||
146 | 141 | ||
147 | do { | 142 | do { |
148 | struct request *rq; | 143 | struct request *rq; |
149 | blk_status_t ret; | ||
150 | 144 | ||
151 | if (!sbitmap_any_bit_set(&hctx->ctx_map)) | 145 | if (!sbitmap_any_bit_set(&hctx->ctx_map)) |
152 | break; | 146 | break; |
153 | 147 | ||
154 | ret = blk_mq_get_dispatch_budget(hctx); | 148 | if (!blk_mq_get_dispatch_budget(hctx)) |
155 | if (ret == BLK_STS_RESOURCE) | ||
156 | break; | 149 | break; |
157 | 150 | ||
158 | rq = blk_mq_dequeue_from_ctx(hctx, ctx); | 151 | rq = blk_mq_dequeue_from_ctx(hctx, ctx); |
159 | if (!rq) { | 152 | if (!rq) { |
160 | blk_mq_put_dispatch_budget(hctx); | 153 | blk_mq_put_dispatch_budget(hctx); |
161 | break; | 154 | break; |
162 | } else if (ret != BLK_STS_OK) { | ||
163 | blk_mq_end_request(rq, ret); | ||
164 | continue; | ||
165 | } | 155 | } |
166 | 156 | ||
167 | /* | 157 | /* |
diff --git a/block/blk-mq.c b/block/blk-mq.c index 13cdccef543c..c9fa4b294664 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
@@ -1137,13 +1137,8 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, | |||
1137 | } | 1137 | } |
1138 | } | 1138 | } |
1139 | 1139 | ||
1140 | if (!got_budget) { | 1140 | if (!got_budget && !blk_mq_get_dispatch_budget(hctx)) |
1141 | ret = blk_mq_get_dispatch_budget(hctx); | 1141 | break; |
1142 | if (ret == BLK_STS_RESOURCE) | ||
1143 | break; | ||
1144 | if (ret != BLK_STS_OK) | ||
1145 | goto fail_rq; | ||
1146 | } | ||
1147 | 1142 | ||
1148 | list_del_init(&rq->queuelist); | 1143 | list_del_init(&rq->queuelist); |
1149 | 1144 | ||
@@ -1170,7 +1165,6 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, | |||
1170 | break; | 1165 | break; |
1171 | } | 1166 | } |
1172 | 1167 | ||
1173 | fail_rq: | ||
1174 | if (unlikely(ret != BLK_STS_OK)) { | 1168 | if (unlikely(ret != BLK_STS_OK)) { |
1175 | errors++; | 1169 | errors++; |
1176 | blk_mq_end_request(rq, BLK_STS_IOERR); | 1170 | blk_mq_end_request(rq, BLK_STS_IOERR); |
@@ -1642,12 +1636,10 @@ static void __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, | |||
1642 | if (!blk_mq_get_driver_tag(rq, NULL, false)) | 1636 | if (!blk_mq_get_driver_tag(rq, NULL, false)) |
1643 | goto insert; | 1637 | goto insert; |
1644 | 1638 | ||
1645 | ret = blk_mq_get_dispatch_budget(hctx); | 1639 | if (!blk_mq_get_dispatch_budget(hctx)) { |
1646 | if (ret == BLK_STS_RESOURCE) { | ||
1647 | blk_mq_put_driver_tag(rq); | 1640 | blk_mq_put_driver_tag(rq); |
1648 | goto insert; | 1641 | goto insert; |
1649 | } else if (ret != BLK_STS_OK) | 1642 | } |
1650 | goto fail_rq; | ||
1651 | 1643 | ||
1652 | new_cookie = request_to_qc_t(hctx, rq); | 1644 | new_cookie = request_to_qc_t(hctx, rq); |
1653 | 1645 | ||
@@ -1665,7 +1657,6 @@ static void __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, | |||
1665 | __blk_mq_requeue_request(rq); | 1657 | __blk_mq_requeue_request(rq); |
1666 | goto insert; | 1658 | goto insert; |
1667 | default: | 1659 | default: |
1668 | fail_rq: | ||
1669 | *cookie = BLK_QC_T_NONE; | 1660 | *cookie = BLK_QC_T_NONE; |
1670 | blk_mq_end_request(rq, ret); | 1661 | blk_mq_end_request(rq, ret); |
1671 | return; | 1662 | return; |
diff --git a/block/blk-mq.h b/block/blk-mq.h index 522b420dedc0..f97aceff76e9 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h | |||
@@ -147,14 +147,13 @@ static inline void blk_mq_put_dispatch_budget(struct blk_mq_hw_ctx *hctx) | |||
147 | q->mq_ops->put_budget(hctx); | 147 | q->mq_ops->put_budget(hctx); |
148 | } | 148 | } |
149 | 149 | ||
150 | static inline blk_status_t blk_mq_get_dispatch_budget( | 150 | static inline bool blk_mq_get_dispatch_budget(struct blk_mq_hw_ctx *hctx) |
151 | struct blk_mq_hw_ctx *hctx) | ||
152 | { | 151 | { |
153 | struct request_queue *q = hctx->queue; | 152 | struct request_queue *q = hctx->queue; |
154 | 153 | ||
155 | if (q->mq_ops->get_budget) | 154 | if (q->mq_ops->get_budget) |
156 | return q->mq_ops->get_budget(hctx); | 155 | return q->mq_ops->get_budget(hctx); |
157 | return BLK_STS_OK; | 156 | return true; |
158 | } | 157 | } |
159 | 158 | ||
160 | #endif | 159 | #endif |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 22a7e4c47207..286ea983c9e3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1955,27 +1955,22 @@ static void scsi_mq_put_budget(struct blk_mq_hw_ctx *hctx) | |||
1955 | put_device(&sdev->sdev_gendev); | 1955 | put_device(&sdev->sdev_gendev); |
1956 | } | 1956 | } |
1957 | 1957 | ||
1958 | static blk_status_t scsi_mq_get_budget(struct blk_mq_hw_ctx *hctx) | 1958 | static bool scsi_mq_get_budget(struct blk_mq_hw_ctx *hctx) |
1959 | { | 1959 | { |
1960 | struct request_queue *q = hctx->queue; | 1960 | struct request_queue *q = hctx->queue; |
1961 | struct scsi_device *sdev = q->queuedata; | 1961 | struct scsi_device *sdev = q->queuedata; |
1962 | blk_status_t ret; | ||
1963 | |||
1964 | ret = prep_to_mq(scsi_prep_state_check(sdev, NULL)); | ||
1965 | if (ret == BLK_STS_RESOURCE || ret != BLK_STS_OK) | ||
1966 | return ret; | ||
1967 | 1962 | ||
1968 | if (!get_device(&sdev->sdev_gendev)) | 1963 | if (!get_device(&sdev->sdev_gendev)) |
1969 | goto out; | 1964 | goto out; |
1970 | if (!scsi_dev_queue_ready(q, sdev)) | 1965 | if (!scsi_dev_queue_ready(q, sdev)) |
1971 | goto out_put_device; | 1966 | goto out_put_device; |
1972 | 1967 | ||
1973 | return BLK_STS_OK; | 1968 | return true; |
1974 | 1969 | ||
1975 | out_put_device: | 1970 | out_put_device: |
1976 | put_device(&sdev->sdev_gendev); | 1971 | put_device(&sdev->sdev_gendev); |
1977 | out: | 1972 | out: |
1978 | return BLK_STS_RESOURCE; | 1973 | return false; |
1979 | } | 1974 | } |
1980 | 1975 | ||
1981 | static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, | 1976 | static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, |
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index f2e3079eecdd..674641527da7 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h | |||
@@ -92,7 +92,7 @@ struct blk_mq_queue_data { | |||
92 | 92 | ||
93 | typedef blk_status_t (queue_rq_fn)(struct blk_mq_hw_ctx *, | 93 | typedef blk_status_t (queue_rq_fn)(struct blk_mq_hw_ctx *, |
94 | const struct blk_mq_queue_data *); | 94 | const struct blk_mq_queue_data *); |
95 | typedef blk_status_t (get_budget_fn)(struct blk_mq_hw_ctx *); | 95 | typedef bool (get_budget_fn)(struct blk_mq_hw_ctx *); |
96 | typedef void (put_budget_fn)(struct blk_mq_hw_ctx *); | 96 | typedef void (put_budget_fn)(struct blk_mq_hw_ctx *); |
97 | typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool); | 97 | typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool); |
98 | typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int); | 98 | typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int); |