| .. | .. |
|---|
| 7 | 7 | |
|---|
| 8 | 8 | struct blk_mq_tag_set; |
|---|
| 9 | 9 | |
|---|
| 10 | +struct blk_mq_ctxs { |
|---|
| 11 | + struct kobject kobj; |
|---|
| 12 | + struct blk_mq_ctx __percpu *queue_ctx; |
|---|
| 13 | +}; |
|---|
| 14 | + |
|---|
| 10 | 15 | /** |
|---|
| 11 | 16 | * struct blk_mq_ctx - State for a software queue facing the submitting CPUs |
|---|
| 12 | 17 | */ |
|---|
| 13 | 18 | struct blk_mq_ctx { |
|---|
| 14 | 19 | struct { |
|---|
| 15 | 20 | spinlock_t lock; |
|---|
| 16 | | - struct list_head rq_list; |
|---|
| 17 | | - } ____cacheline_aligned_in_smp; |
|---|
| 21 | + struct list_head rq_lists[HCTX_MAX_TYPES]; |
|---|
| 22 | + } ____cacheline_aligned_in_smp; |
|---|
| 18 | 23 | |
|---|
| 19 | 24 | unsigned int cpu; |
|---|
| 20 | | - unsigned int index_hw; |
|---|
| 25 | + unsigned short index_hw[HCTX_MAX_TYPES]; |
|---|
| 26 | + struct blk_mq_hw_ctx *hctxs[HCTX_MAX_TYPES]; |
|---|
| 21 | 27 | |
|---|
| 22 | 28 | /* incremented at dispatch time */ |
|---|
| 23 | 29 | unsigned long rq_dispatched[2]; |
|---|
| .. | .. |
|---|
| 27 | 33 | unsigned long ____cacheline_aligned_in_smp rq_completed[2]; |
|---|
| 28 | 34 | |
|---|
| 29 | 35 | struct request_queue *queue; |
|---|
| 36 | + struct blk_mq_ctxs *ctxs; |
|---|
| 30 | 37 | struct kobject kobj; |
|---|
| 38 | + |
|---|
| 39 | + ANDROID_OEM_DATA_ARRAY(1, 2); |
|---|
| 31 | 40 | } ____cacheline_aligned_in_smp; |
|---|
| 32 | 41 | |
|---|
| 33 | | -void blk_mq_freeze_queue(struct request_queue *q); |
|---|
| 34 | 42 | void blk_mq_exit_queue(struct request_queue *q); |
|---|
| 35 | 43 | int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr); |
|---|
| 36 | 44 | void blk_mq_wake_waiters(struct request_queue *q); |
|---|
| 37 | | -bool blk_mq_dispatch_rq_list(struct request_queue *, struct list_head *, bool); |
|---|
| 45 | +bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *, |
|---|
| 46 | + unsigned int); |
|---|
| 47 | +void blk_mq_add_to_requeue_list(struct request *rq, bool at_head, |
|---|
| 48 | + bool kick_requeue_list); |
|---|
| 38 | 49 | void blk_mq_flush_busy_ctxs(struct blk_mq_hw_ctx *hctx, struct list_head *list); |
|---|
| 39 | | -bool blk_mq_get_driver_tag(struct request *rq); |
|---|
| 40 | 50 | struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx, |
|---|
| 41 | 51 | struct blk_mq_ctx *start); |
|---|
| 52 | +void blk_mq_put_rq_ref(struct request *rq); |
|---|
| 42 | 53 | |
|---|
| 43 | 54 | /* |
|---|
| 44 | 55 | * Internal helpers for allocating/freeing the request map |
|---|
| 45 | 56 | */ |
|---|
| 46 | 57 | void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, |
|---|
| 47 | 58 | unsigned int hctx_idx); |
|---|
| 48 | | -void blk_mq_free_rq_map(struct blk_mq_tags *tags); |
|---|
| 59 | +void blk_mq_free_rq_map(struct blk_mq_tags *tags, unsigned int flags); |
|---|
| 49 | 60 | struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, |
|---|
| 50 | 61 | unsigned int hctx_idx, |
|---|
| 51 | 62 | unsigned int nr_tags, |
|---|
| 52 | | - unsigned int reserved_tags); |
|---|
| 63 | + unsigned int reserved_tags, |
|---|
| 64 | + unsigned int flags); |
|---|
| 53 | 65 | int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, |
|---|
| 54 | 66 | unsigned int hctx_idx, unsigned int depth); |
|---|
| 55 | 67 | |
|---|
| .. | .. |
|---|
| 58 | 70 | */ |
|---|
| 59 | 71 | void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, |
|---|
| 60 | 72 | bool at_head); |
|---|
| 61 | | -void blk_mq_request_bypass_insert(struct request *rq, bool run_queue); |
|---|
| 73 | +void blk_mq_request_bypass_insert(struct request *rq, bool at_head, |
|---|
| 74 | + bool run_queue); |
|---|
| 62 | 75 | void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, |
|---|
| 63 | 76 | struct list_head *list); |
|---|
| 64 | 77 | |
|---|
| 65 | 78 | /* Used by blk_insert_cloned_request() to issue request directly */ |
|---|
| 66 | | -blk_status_t blk_mq_request_issue_directly(struct request *rq); |
|---|
| 79 | +blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last); |
|---|
| 67 | 80 | void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, |
|---|
| 68 | 81 | struct list_head *list); |
|---|
| 69 | 82 | |
|---|
| 70 | 83 | /* |
|---|
| 71 | 84 | * CPU -> queue mappings |
|---|
| 72 | 85 | */ |
|---|
| 73 | | -extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int); |
|---|
| 86 | +extern int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int); |
|---|
| 74 | 87 | |
|---|
| 75 | | -static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, |
|---|
| 76 | | - int cpu) |
|---|
| 88 | +/* |
|---|
| 89 | + * blk_mq_map_queue_type() - map (hctx_type,cpu) to hardware queue |
|---|
| 90 | + * @q: request queue |
|---|
| 91 | + * @type: the hctx type index |
|---|
| 92 | + * @cpu: CPU |
|---|
| 93 | + */ |
|---|
| 94 | +static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *q, |
|---|
| 95 | + enum hctx_type type, |
|---|
| 96 | + unsigned int cpu) |
|---|
| 77 | 97 | { |
|---|
| 78 | | - return q->queue_hw_ctx[q->mq_map[cpu]]; |
|---|
| 98 | + return q->queue_hw_ctx[q->tag_set->map[type].mq_map[cpu]]; |
|---|
| 99 | +} |
|---|
| 100 | + |
|---|
| 101 | +/* |
|---|
| 102 | + * blk_mq_map_queue() - map (cmd_flags,type) to hardware queue |
|---|
| 103 | + * @q: request queue |
|---|
| 104 | + * @flags: request command flags |
|---|
| 105 | + * @cpu: cpu ctx |
|---|
| 106 | + */ |
|---|
| 107 | +static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, |
|---|
| 108 | + unsigned int flags, |
|---|
| 109 | + struct blk_mq_ctx *ctx) |
|---|
| 110 | +{ |
|---|
| 111 | + enum hctx_type type = HCTX_TYPE_DEFAULT; |
|---|
| 112 | + |
|---|
| 113 | + /* |
|---|
| 114 | + * The caller ensure that if REQ_HIPRI, poll must be enabled. |
|---|
| 115 | + */ |
|---|
| 116 | + if (flags & REQ_HIPRI) |
|---|
| 117 | + type = HCTX_TYPE_POLL; |
|---|
| 118 | + else if ((flags & REQ_OP_MASK) == REQ_OP_READ) |
|---|
| 119 | + type = HCTX_TYPE_READ; |
|---|
| 120 | + |
|---|
| 121 | + return ctx->hctxs[type]; |
|---|
| 79 | 122 | } |
|---|
| 80 | 123 | |
|---|
| 81 | 124 | /* |
|---|
| .. | .. |
|---|
| 89 | 132 | extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx); |
|---|
| 90 | 133 | |
|---|
| 91 | 134 | void blk_mq_release(struct request_queue *q); |
|---|
| 92 | | - |
|---|
| 93 | | -/** |
|---|
| 94 | | - * blk_mq_rq_state() - read the current MQ_RQ_* state of a request |
|---|
| 95 | | - * @rq: target request. |
|---|
| 96 | | - */ |
|---|
| 97 | | -static inline enum mq_rq_state blk_mq_rq_state(struct request *rq) |
|---|
| 98 | | -{ |
|---|
| 99 | | - return READ_ONCE(rq->state); |
|---|
| 100 | | -} |
|---|
| 101 | 135 | |
|---|
| 102 | 136 | static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q, |
|---|
| 103 | 137 | unsigned int cpu) |
|---|
| .. | .. |
|---|
| 113 | 147 | */ |
|---|
| 114 | 148 | static inline struct blk_mq_ctx *blk_mq_get_ctx(struct request_queue *q) |
|---|
| 115 | 149 | { |
|---|
| 116 | | - return __blk_mq_get_ctx(q, get_cpu()); |
|---|
| 117 | | -} |
|---|
| 118 | | - |
|---|
| 119 | | -static inline void blk_mq_put_ctx(struct blk_mq_ctx *ctx) |
|---|
| 120 | | -{ |
|---|
| 121 | | - put_cpu(); |
|---|
| 150 | + return __blk_mq_get_ctx(q, raw_smp_processor_id()); |
|---|
| 122 | 151 | } |
|---|
| 123 | 152 | |
|---|
| 124 | 153 | struct blk_mq_alloc_data { |
|---|
| .. | .. |
|---|
| 126 | 155 | struct request_queue *q; |
|---|
| 127 | 156 | blk_mq_req_flags_t flags; |
|---|
| 128 | 157 | unsigned int shallow_depth; |
|---|
| 158 | + unsigned int cmd_flags; |
|---|
| 129 | 159 | |
|---|
| 130 | 160 | /* input & output parameter */ |
|---|
| 131 | 161 | struct blk_mq_ctx *ctx; |
|---|
| 132 | 162 | struct blk_mq_hw_ctx *hctx; |
|---|
| 133 | 163 | }; |
|---|
| 134 | 164 | |
|---|
| 165 | +static inline bool blk_mq_is_sbitmap_shared(unsigned int flags) |
|---|
| 166 | +{ |
|---|
| 167 | + return flags & BLK_MQ_F_TAG_HCTX_SHARED; |
|---|
| 168 | +} |
|---|
| 169 | + |
|---|
| 135 | 170 | static inline struct blk_mq_tags *blk_mq_tags_from_data(struct blk_mq_alloc_data *data) |
|---|
| 136 | 171 | { |
|---|
| 137 | | - if (data->flags & BLK_MQ_REQ_INTERNAL) |
|---|
| 172 | + if (data->q->elevator) |
|---|
| 138 | 173 | return data->hctx->sched_tags; |
|---|
| 139 | 174 | |
|---|
| 140 | 175 | return data->hctx->tags; |
|---|
| .. | .. |
|---|
| 150 | 185 | return hctx->nr_ctx && hctx->tags; |
|---|
| 151 | 186 | } |
|---|
| 152 | 187 | |
|---|
| 153 | | -void blk_mq_in_flight(struct request_queue *q, struct hd_struct *part, |
|---|
| 154 | | - unsigned int inflight[2]); |
|---|
| 188 | +unsigned int blk_mq_in_flight(struct request_queue *q, struct hd_struct *part); |
|---|
| 155 | 189 | void blk_mq_in_flight_rw(struct request_queue *q, struct hd_struct *part, |
|---|
| 156 | 190 | unsigned int inflight[2]); |
|---|
| 157 | 191 | |
|---|
| 158 | | -static inline void blk_mq_put_dispatch_budget(struct blk_mq_hw_ctx *hctx) |
|---|
| 192 | +static inline void blk_mq_put_dispatch_budget(struct request_queue *q) |
|---|
| 159 | 193 | { |
|---|
| 160 | | - struct request_queue *q = hctx->queue; |
|---|
| 161 | | - |
|---|
| 162 | 194 | if (q->mq_ops->put_budget) |
|---|
| 163 | | - q->mq_ops->put_budget(hctx); |
|---|
| 195 | + q->mq_ops->put_budget(q); |
|---|
| 164 | 196 | } |
|---|
| 165 | 197 | |
|---|
| 166 | | -static inline bool blk_mq_get_dispatch_budget(struct blk_mq_hw_ctx *hctx) |
|---|
| 198 | +static inline bool blk_mq_get_dispatch_budget(struct request_queue *q) |
|---|
| 167 | 199 | { |
|---|
| 168 | | - struct request_queue *q = hctx->queue; |
|---|
| 169 | | - |
|---|
| 170 | 200 | if (q->mq_ops->get_budget) |
|---|
| 171 | | - return q->mq_ops->get_budget(hctx); |
|---|
| 201 | + return q->mq_ops->get_budget(q); |
|---|
| 172 | 202 | return true; |
|---|
| 173 | 203 | } |
|---|
| 174 | 204 | |
|---|
| 205 | +static inline void __blk_mq_inc_active_requests(struct blk_mq_hw_ctx *hctx) |
|---|
| 206 | +{ |
|---|
| 207 | + if (blk_mq_is_sbitmap_shared(hctx->flags)) |
|---|
| 208 | + atomic_inc(&hctx->queue->nr_active_requests_shared_sbitmap); |
|---|
| 209 | + else |
|---|
| 210 | + atomic_inc(&hctx->nr_active); |
|---|
| 211 | +} |
|---|
| 212 | + |
|---|
| 213 | +static inline void __blk_mq_dec_active_requests(struct blk_mq_hw_ctx *hctx) |
|---|
| 214 | +{ |
|---|
| 215 | + if (blk_mq_is_sbitmap_shared(hctx->flags)) |
|---|
| 216 | + atomic_dec(&hctx->queue->nr_active_requests_shared_sbitmap); |
|---|
| 217 | + else |
|---|
| 218 | + atomic_dec(&hctx->nr_active); |
|---|
| 219 | +} |
|---|
| 220 | + |
|---|
| 221 | +static inline int __blk_mq_active_requests(struct blk_mq_hw_ctx *hctx) |
|---|
| 222 | +{ |
|---|
| 223 | + if (blk_mq_is_sbitmap_shared(hctx->flags)) |
|---|
| 224 | + return atomic_read(&hctx->queue->nr_active_requests_shared_sbitmap); |
|---|
| 225 | + return atomic_read(&hctx->nr_active); |
|---|
| 226 | +} |
|---|
| 175 | 227 | static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx, |
|---|
| 176 | 228 | struct request *rq) |
|---|
| 177 | 229 | { |
|---|
| 178 | | - blk_mq_put_tag(hctx, hctx->tags, rq->mq_ctx, rq->tag); |
|---|
| 179 | | - rq->tag = -1; |
|---|
| 230 | + blk_mq_put_tag(hctx->tags, rq->mq_ctx, rq->tag); |
|---|
| 231 | + rq->tag = BLK_MQ_NO_TAG; |
|---|
| 180 | 232 | |
|---|
| 181 | 233 | if (rq->rq_flags & RQF_MQ_INFLIGHT) { |
|---|
| 182 | 234 | rq->rq_flags &= ~RQF_MQ_INFLIGHT; |
|---|
| 183 | | - atomic_dec(&hctx->nr_active); |
|---|
| 235 | + __blk_mq_dec_active_requests(hctx); |
|---|
| 184 | 236 | } |
|---|
| 185 | | -} |
|---|
| 186 | | - |
|---|
| 187 | | -static inline void blk_mq_put_driver_tag_hctx(struct blk_mq_hw_ctx *hctx, |
|---|
| 188 | | - struct request *rq) |
|---|
| 189 | | -{ |
|---|
| 190 | | - if (rq->tag == -1 || rq->internal_tag == -1) |
|---|
| 191 | | - return; |
|---|
| 192 | | - |
|---|
| 193 | | - __blk_mq_put_driver_tag(hctx, rq); |
|---|
| 194 | 237 | } |
|---|
| 195 | 238 | |
|---|
| 196 | 239 | static inline void blk_mq_put_driver_tag(struct request *rq) |
|---|
| 197 | 240 | { |
|---|
| 198 | | - struct blk_mq_hw_ctx *hctx; |
|---|
| 199 | | - |
|---|
| 200 | | - if (rq->tag == -1 || rq->internal_tag == -1) |
|---|
| 241 | + if (rq->tag == BLK_MQ_NO_TAG || rq->internal_tag == BLK_MQ_NO_TAG) |
|---|
| 201 | 242 | return; |
|---|
| 202 | 243 | |
|---|
| 203 | | - hctx = blk_mq_map_queue(rq->q, rq->mq_ctx->cpu); |
|---|
| 204 | | - __blk_mq_put_driver_tag(hctx, rq); |
|---|
| 244 | + __blk_mq_put_driver_tag(rq->mq_hctx, rq); |
|---|
| 205 | 245 | } |
|---|
| 206 | 246 | |
|---|
| 207 | | -static inline void blk_mq_clear_mq_map(struct blk_mq_tag_set *set) |
|---|
| 247 | +static inline void blk_mq_clear_mq_map(struct blk_mq_queue_map *qmap) |
|---|
| 208 | 248 | { |
|---|
| 209 | 249 | int cpu; |
|---|
| 210 | 250 | |
|---|
| 211 | 251 | for_each_possible_cpu(cpu) |
|---|
| 212 | | - set->mq_map[cpu] = 0; |
|---|
| 252 | + qmap->mq_map[cpu] = 0; |
|---|
| 213 | 253 | } |
|---|
| 214 | 254 | |
|---|
| 255 | +/* |
|---|
| 256 | + * blk_mq_plug() - Get caller context plug |
|---|
| 257 | + * @q: request queue |
|---|
| 258 | + * @bio : the bio being submitted by the caller context |
|---|
| 259 | + * |
|---|
| 260 | + * Plugging, by design, may delay the insertion of BIOs into the elevator in |
|---|
| 261 | + * order to increase BIO merging opportunities. This however can cause BIO |
|---|
| 262 | + * insertion order to change from the order in which submit_bio() is being |
|---|
| 263 | + * executed in the case of multiple contexts concurrently issuing BIOs to a |
|---|
| 264 | + * device, even if these context are synchronized to tightly control BIO issuing |
|---|
| 265 | + * order. While this is not a problem with regular block devices, this ordering |
|---|
| 266 | + * change can cause write BIO failures with zoned block devices as these |
|---|
| 267 | + * require sequential write patterns to zones. Prevent this from happening by |
|---|
| 268 | + * ignoring the plug state of a BIO issuing context if the target request queue |
|---|
| 269 | + * is for a zoned block device and the BIO to plug is a write operation. |
|---|
| 270 | + * |
|---|
| 271 | + * Return current->plug if the bio can be plugged and NULL otherwise |
|---|
| 272 | + */ |
|---|
| 273 | +static inline struct blk_plug *blk_mq_plug(struct request_queue *q, |
|---|
| 274 | + struct bio *bio) |
|---|
| 275 | +{ |
|---|
| 276 | + /* |
|---|
| 277 | + * For regular block devices or read operations, use the context plug |
|---|
| 278 | + * which may be NULL if blk_start_plug() was not executed. |
|---|
| 279 | + */ |
|---|
| 280 | + if (!blk_queue_is_zoned(q) || !op_is_write(bio_op(bio))) |
|---|
| 281 | + return current->plug; |
|---|
| 282 | + |
|---|
| 283 | + /* Zoned block device write operation case: do not plug the BIO */ |
|---|
| 284 | + return NULL; |
|---|
| 285 | +} |
|---|
| 286 | + |
|---|
| 287 | +/* |
|---|
| 288 | + * For shared tag users, we track the number of currently active users |
|---|
| 289 | + * and attempt to provide a fair share of the tag depth for each of them. |
|---|
| 290 | + */ |
|---|
| 291 | +static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, |
|---|
| 292 | + struct sbitmap_queue *bt) |
|---|
| 293 | +{ |
|---|
| 294 | + unsigned int depth, users; |
|---|
| 295 | + |
|---|
| 296 | + if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) |
|---|
| 297 | + return true; |
|---|
| 298 | + |
|---|
| 299 | + /* |
|---|
| 300 | + * Don't try dividing an ant |
|---|
| 301 | + */ |
|---|
| 302 | + if (bt->sb.depth == 1) |
|---|
| 303 | + return true; |
|---|
| 304 | + |
|---|
| 305 | + if (blk_mq_is_sbitmap_shared(hctx->flags)) { |
|---|
| 306 | + struct request_queue *q = hctx->queue; |
|---|
| 307 | + struct blk_mq_tag_set *set = q->tag_set; |
|---|
| 308 | + |
|---|
| 309 | + if (!test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags)) |
|---|
| 310 | + return true; |
|---|
| 311 | + users = atomic_read(&set->active_queues_shared_sbitmap); |
|---|
| 312 | + } else { |
|---|
| 313 | + if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) |
|---|
| 314 | + return true; |
|---|
| 315 | + users = atomic_read(&hctx->tags->active_queues); |
|---|
| 316 | + } |
|---|
| 317 | + |
|---|
| 318 | + if (!users) |
|---|
| 319 | + return true; |
|---|
| 320 | + |
|---|
| 321 | + /* |
|---|
| 322 | + * Allow at least some tags |
|---|
| 323 | + */ |
|---|
| 324 | + depth = max((bt->sb.depth + users - 1) / users, 4U); |
|---|
| 325 | + return __blk_mq_active_requests(hctx) < depth; |
|---|
| 326 | +} |
|---|
| 327 | + |
|---|
| 328 | + |
|---|
| 215 | 329 | #endif |
|---|