diff options
Diffstat (limited to 'block/blk-mq.c')
| -rw-r--r-- | block/blk-mq.c | 114 |
1 files changed, 77 insertions, 37 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c index a4546f060e80..c7836a1ded97 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
| @@ -321,7 +321,6 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q, int rw, | |||
| 321 | 321 | ||
| 322 | rq = blk_mq_sched_get_request(q, NULL, rw, &alloc_data); | 322 | rq = blk_mq_sched_get_request(q, NULL, rw, &alloc_data); |
| 323 | 323 | ||
| 324 | blk_mq_put_ctx(alloc_data.ctx); | ||
| 325 | blk_queue_exit(q); | 324 | blk_queue_exit(q); |
| 326 | 325 | ||
| 327 | if (!rq) | 326 | if (!rq) |
| @@ -349,7 +348,7 @@ void __blk_mq_finish_request(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, | |||
| 349 | blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag); | 348 | blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag); |
| 350 | if (sched_tag != -1) | 349 | if (sched_tag != -1) |
| 351 | blk_mq_sched_completed_request(hctx, rq); | 350 | blk_mq_sched_completed_request(hctx, rq); |
| 352 | blk_mq_sched_restart_queues(hctx); | 351 | blk_mq_sched_restart(hctx); |
| 353 | blk_queue_exit(q); | 352 | blk_queue_exit(q); |
| 354 | } | 353 | } |
| 355 | 354 | ||
| @@ -697,17 +696,8 @@ static void blk_mq_check_expired(struct blk_mq_hw_ctx *hctx, | |||
| 697 | { | 696 | { |
| 698 | struct blk_mq_timeout_data *data = priv; | 697 | struct blk_mq_timeout_data *data = priv; |
| 699 | 698 | ||
| 700 | if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) { | 699 | if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) |
| 701 | /* | ||
| 702 | * If a request wasn't started before the queue was | ||
| 703 | * marked dying, kill it here or it'll go unnoticed. | ||
| 704 | */ | ||
| 705 | if (unlikely(blk_queue_dying(rq->q))) { | ||
| 706 | rq->errors = -EIO; | ||
| 707 | blk_mq_end_request(rq, rq->errors); | ||
| 708 | } | ||
| 709 | return; | 700 | return; |
| 710 | } | ||
| 711 | 701 | ||
| 712 | if (time_after_eq(jiffies, rq->deadline)) { | 702 | if (time_after_eq(jiffies, rq->deadline)) { |
| 713 | if (!blk_mark_rq_complete(rq)) | 703 | if (!blk_mark_rq_complete(rq)) |
| @@ -855,12 +845,8 @@ bool blk_mq_get_driver_tag(struct request *rq, struct blk_mq_hw_ctx **hctx, | |||
| 855 | .flags = wait ? 0 : BLK_MQ_REQ_NOWAIT, | 845 | .flags = wait ? 0 : BLK_MQ_REQ_NOWAIT, |
| 856 | }; | 846 | }; |
| 857 | 847 | ||
| 858 | if (rq->tag != -1) { | 848 | if (rq->tag != -1) |
| 859 | done: | 849 | goto done; |
| 860 | if (hctx) | ||
| 861 | *hctx = data.hctx; | ||
| 862 | return true; | ||
| 863 | } | ||
| 864 | 850 | ||
| 865 | if (blk_mq_tag_is_reserved(data.hctx->sched_tags, rq->internal_tag)) | 851 | if (blk_mq_tag_is_reserved(data.hctx->sched_tags, rq->internal_tag)) |
| 866 | data.flags |= BLK_MQ_REQ_RESERVED; | 852 | data.flags |= BLK_MQ_REQ_RESERVED; |
| @@ -872,10 +858,12 @@ done: | |||
| 872 | atomic_inc(&data.hctx->nr_active); | 858 | atomic_inc(&data.hctx->nr_active); |
| 873 | } | 859 | } |
| 874 | data.hctx->tags->rqs[rq->tag] = rq; | 860 | data.hctx->tags->rqs[rq->tag] = rq; |
| 875 | goto done; | ||
| 876 | } | 861 | } |
| 877 | 862 | ||
| 878 | return false; | 863 | done: |
| 864 | if (hctx) | ||
| 865 | *hctx = data.hctx; | ||
| 866 | return rq->tag != -1; | ||
| 879 | } | 867 | } |
| 880 | 868 | ||
| 881 | static void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx, | 869 | static void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx, |
| @@ -972,13 +960,16 @@ static bool blk_mq_dispatch_wait_add(struct blk_mq_hw_ctx *hctx) | |||
| 972 | return true; | 960 | return true; |
| 973 | } | 961 | } |
| 974 | 962 | ||
| 975 | bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list) | 963 | bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list) |
| 976 | { | 964 | { |
| 977 | struct request_queue *q = hctx->queue; | 965 | struct blk_mq_hw_ctx *hctx; |
| 978 | struct request *rq; | 966 | struct request *rq; |
| 979 | LIST_HEAD(driver_list); | 967 | LIST_HEAD(driver_list); |
| 980 | struct list_head *dptr; | 968 | struct list_head *dptr; |
| 981 | int queued, ret = BLK_MQ_RQ_QUEUE_OK; | 969 | int errors, queued, ret = BLK_MQ_RQ_QUEUE_OK; |
| 970 | |||
| 971 | if (list_empty(list)) | ||
| 972 | return false; | ||
| 982 | 973 | ||
| 983 | /* | 974 | /* |
| 984 | * Start off with dptr being NULL, so we start the first request | 975 | * Start off with dptr being NULL, so we start the first request |
| @@ -989,8 +980,8 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list) | |||
| 989 | /* | 980 | /* |
| 990 | * Now process all the entries, sending them to the driver. | 981 | * Now process all the entries, sending them to the driver. |
| 991 | */ | 982 | */ |
| 992 | queued = 0; | 983 | errors = queued = 0; |
| 993 | while (!list_empty(list)) { | 984 | do { |
| 994 | struct blk_mq_queue_data bd; | 985 | struct blk_mq_queue_data bd; |
| 995 | 986 | ||
| 996 | rq = list_first_entry(list, struct request, queuelist); | 987 | rq = list_first_entry(list, struct request, queuelist); |
| @@ -1046,6 +1037,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list) | |||
| 1046 | default: | 1037 | default: |
| 1047 | pr_err("blk-mq: bad return on queue: %d\n", ret); | 1038 | pr_err("blk-mq: bad return on queue: %d\n", ret); |
| 1048 | case BLK_MQ_RQ_QUEUE_ERROR: | 1039 | case BLK_MQ_RQ_QUEUE_ERROR: |
| 1040 | errors++; | ||
| 1049 | rq->errors = -EIO; | 1041 | rq->errors = -EIO; |
| 1050 | blk_mq_end_request(rq, rq->errors); | 1042 | blk_mq_end_request(rq, rq->errors); |
| 1051 | break; | 1043 | break; |
| @@ -1060,7 +1052,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list) | |||
| 1060 | */ | 1052 | */ |
| 1061 | if (!dptr && list->next != list->prev) | 1053 | if (!dptr && list->next != list->prev) |
| 1062 | dptr = &driver_list; | 1054 | dptr = &driver_list; |
| 1063 | } | 1055 | } while (!list_empty(list)); |
| 1064 | 1056 | ||
| 1065 | hctx->dispatched[queued_to_index(queued)]++; | 1057 | hctx->dispatched[queued_to_index(queued)]++; |
| 1066 | 1058 | ||
| @@ -1097,7 +1089,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list) | |||
| 1097 | blk_mq_run_hw_queue(hctx, true); | 1089 | blk_mq_run_hw_queue(hctx, true); |
| 1098 | } | 1090 | } |
| 1099 | 1091 | ||
| 1100 | return queued != 0; | 1092 | return (queued + errors) != 0; |
| 1101 | } | 1093 | } |
| 1102 | 1094 | ||
| 1103 | static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) | 1095 | static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) |
| @@ -1143,7 +1135,8 @@ static int blk_mq_hctx_next_cpu(struct blk_mq_hw_ctx *hctx) | |||
| 1143 | return hctx->next_cpu; | 1135 | return hctx->next_cpu; |
| 1144 | } | 1136 | } |
| 1145 | 1137 | ||
| 1146 | void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async) | 1138 | static void __blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async, |
| 1139 | unsigned long msecs) | ||
| 1147 | { | 1140 | { |
| 1148 | if (unlikely(blk_mq_hctx_stopped(hctx) || | 1141 | if (unlikely(blk_mq_hctx_stopped(hctx) || |
| 1149 | !blk_mq_hw_queue_mapped(hctx))) | 1142 | !blk_mq_hw_queue_mapped(hctx))) |
| @@ -1160,7 +1153,24 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async) | |||
| 1160 | put_cpu(); | 1153 | put_cpu(); |
| 1161 | } | 1154 | } |
| 1162 | 1155 | ||
| 1163 | kblockd_schedule_work_on(blk_mq_hctx_next_cpu(hctx), &hctx->run_work); | 1156 | if (msecs == 0) |
| 1157 | kblockd_schedule_work_on(blk_mq_hctx_next_cpu(hctx), | ||
| 1158 | &hctx->run_work); | ||
| 1159 | else | ||
| 1160 | kblockd_schedule_delayed_work_on(blk_mq_hctx_next_cpu(hctx), | ||
| 1161 | &hctx->delayed_run_work, | ||
| 1162 | msecs_to_jiffies(msecs)); | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | void blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs) | ||
| 1166 | { | ||
| 1167 | __blk_mq_delay_run_hw_queue(hctx, true, msecs); | ||
| 1168 | } | ||
| 1169 | EXPORT_SYMBOL(blk_mq_delay_run_hw_queue); | ||
| 1170 | |||
| 1171 | void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async) | ||
| 1172 | { | ||
| 1173 | __blk_mq_delay_run_hw_queue(hctx, async, 0); | ||
| 1164 | } | 1174 | } |
| 1165 | 1175 | ||
| 1166 | void blk_mq_run_hw_queues(struct request_queue *q, bool async) | 1176 | void blk_mq_run_hw_queues(struct request_queue *q, bool async) |
| @@ -1263,6 +1273,15 @@ static void blk_mq_run_work_fn(struct work_struct *work) | |||
| 1263 | __blk_mq_run_hw_queue(hctx); | 1273 | __blk_mq_run_hw_queue(hctx); |
| 1264 | } | 1274 | } |
| 1265 | 1275 | ||
| 1276 | static void blk_mq_delayed_run_work_fn(struct work_struct *work) | ||
| 1277 | { | ||
| 1278 | struct blk_mq_hw_ctx *hctx; | ||
| 1279 | |||
| 1280 | hctx = container_of(work, struct blk_mq_hw_ctx, delayed_run_work.work); | ||
| 1281 | |||
| 1282 | __blk_mq_run_hw_queue(hctx); | ||
| 1283 | } | ||
| 1284 | |||
| 1266 | static void blk_mq_delay_work_fn(struct work_struct *work) | 1285 | static void blk_mq_delay_work_fn(struct work_struct *work) |
| 1267 | { | 1286 | { |
| 1268 | struct blk_mq_hw_ctx *hctx; | 1287 | struct blk_mq_hw_ctx *hctx; |
| @@ -1932,6 +1951,8 @@ static void blk_mq_exit_hctx(struct request_queue *q, | |||
| 1932 | hctx->fq->flush_rq, hctx_idx, | 1951 | hctx->fq->flush_rq, hctx_idx, |
| 1933 | flush_start_tag + hctx_idx); | 1952 | flush_start_tag + hctx_idx); |
| 1934 | 1953 | ||
| 1954 | blk_mq_sched_exit_hctx(q, hctx, hctx_idx); | ||
| 1955 | |||
| 1935 | if (set->ops->exit_hctx) | 1956 | if (set->ops->exit_hctx) |
| 1936 | set->ops->exit_hctx(hctx, hctx_idx); | 1957 | set->ops->exit_hctx(hctx, hctx_idx); |
| 1937 | 1958 | ||
| @@ -1968,6 +1989,7 @@ static int blk_mq_init_hctx(struct request_queue *q, | |||
| 1968 | node = hctx->numa_node = set->numa_node; | 1989 | node = hctx->numa_node = set->numa_node; |
| 1969 | 1990 | ||
| 1970 | INIT_WORK(&hctx->run_work, blk_mq_run_work_fn); | 1991 | INIT_WORK(&hctx->run_work, blk_mq_run_work_fn); |
| 1992 | INIT_DELAYED_WORK(&hctx->delayed_run_work, blk_mq_delayed_run_work_fn); | ||
| 1971 | INIT_DELAYED_WORK(&hctx->delay_work, blk_mq_delay_work_fn); | 1993 | INIT_DELAYED_WORK(&hctx->delay_work, blk_mq_delay_work_fn); |
| 1972 | spin_lock_init(&hctx->lock); | 1994 | spin_lock_init(&hctx->lock); |
| 1973 | INIT_LIST_HEAD(&hctx->dispatch); | 1995 | INIT_LIST_HEAD(&hctx->dispatch); |
| @@ -1998,9 +2020,12 @@ static int blk_mq_init_hctx(struct request_queue *q, | |||
| 1998 | set->ops->init_hctx(hctx, set->driver_data, hctx_idx)) | 2020 | set->ops->init_hctx(hctx, set->driver_data, hctx_idx)) |
| 1999 | goto free_bitmap; | 2021 | goto free_bitmap; |
| 2000 | 2022 | ||
| 2023 | if (blk_mq_sched_init_hctx(q, hctx, hctx_idx)) | ||
| 2024 | goto exit_hctx; | ||
| 2025 | |||
| 2001 | hctx->fq = blk_alloc_flush_queue(q, hctx->numa_node, set->cmd_size); | 2026 | hctx->fq = blk_alloc_flush_queue(q, hctx->numa_node, set->cmd_size); |
| 2002 | if (!hctx->fq) | 2027 | if (!hctx->fq) |
| 2003 | goto exit_hctx; | 2028 | goto sched_exit_hctx; |
| 2004 | 2029 | ||
| 2005 | if (set->ops->init_request && | 2030 | if (set->ops->init_request && |
| 2006 | set->ops->init_request(set->driver_data, | 2031 | set->ops->init_request(set->driver_data, |
| @@ -2015,6 +2040,8 @@ static int blk_mq_init_hctx(struct request_queue *q, | |||
| 2015 | 2040 | ||
| 2016 | free_fq: | 2041 | free_fq: |
| 2017 | kfree(hctx->fq); | 2042 | kfree(hctx->fq); |
| 2043 | sched_exit_hctx: | ||
| 2044 | blk_mq_sched_exit_hctx(q, hctx, hctx_idx); | ||
| 2018 | exit_hctx: | 2045 | exit_hctx: |
| 2019 | if (set->ops->exit_hctx) | 2046 | if (set->ops->exit_hctx) |
| 2020 | set->ops->exit_hctx(hctx, hctx_idx); | 2047 | set->ops->exit_hctx(hctx, hctx_idx); |
| @@ -2241,8 +2268,6 @@ void blk_mq_release(struct request_queue *q) | |||
| 2241 | struct blk_mq_hw_ctx *hctx; | 2268 | struct blk_mq_hw_ctx *hctx; |
| 2242 | unsigned int i; | 2269 | unsigned int i; |
| 2243 | 2270 | ||
| 2244 | blk_mq_sched_teardown(q); | ||
| 2245 | |||
| 2246 | /* hctx kobj stays in hctx */ | 2271 | /* hctx kobj stays in hctx */ |
| 2247 | queue_for_each_hw_ctx(q, hctx, i) { | 2272 | queue_for_each_hw_ctx(q, hctx, i) { |
| 2248 | if (!hctx) | 2273 | if (!hctx) |
| @@ -2573,6 +2598,14 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set) | |||
| 2573 | return 0; | 2598 | return 0; |
| 2574 | } | 2599 | } |
| 2575 | 2600 | ||
| 2601 | static int blk_mq_update_queue_map(struct blk_mq_tag_set *set) | ||
| 2602 | { | ||
| 2603 | if (set->ops->map_queues) | ||
| 2604 | return set->ops->map_queues(set); | ||
| 2605 | else | ||
| 2606 | return blk_mq_map_queues(set); | ||
| 2607 | } | ||
| 2608 | |||
| 2576 | /* | 2609 | /* |
| 2577 | * Alloc a tag set to be associated with one or more request queues. | 2610 | * Alloc a tag set to be associated with one or more request queues. |
| 2578 | * May fail with EINVAL for various error conditions. May adjust the | 2611 | * May fail with EINVAL for various error conditions. May adjust the |
| @@ -2627,10 +2660,7 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) | |||
| 2627 | if (!set->mq_map) | 2660 | if (!set->mq_map) |
| 2628 | goto out_free_tags; | 2661 | goto out_free_tags; |
| 2629 | 2662 | ||
| 2630 | if (set->ops->map_queues) | 2663 | ret = blk_mq_update_queue_map(set); |
| 2631 | ret = set->ops->map_queues(set); | ||
| 2632 | else | ||
| 2633 | ret = blk_mq_map_queues(set); | ||
| 2634 | if (ret) | 2664 | if (ret) |
| 2635 | goto out_free_mq_map; | 2665 | goto out_free_mq_map; |
| 2636 | 2666 | ||
| @@ -2722,6 +2752,7 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues) | |||
| 2722 | blk_mq_freeze_queue(q); | 2752 | blk_mq_freeze_queue(q); |
| 2723 | 2753 | ||
| 2724 | set->nr_hw_queues = nr_hw_queues; | 2754 | set->nr_hw_queues = nr_hw_queues; |
| 2755 | blk_mq_update_queue_map(set); | ||
| 2725 | list_for_each_entry(q, &set->tag_list, tag_set_list) { | 2756 | list_for_each_entry(q, &set->tag_list, tag_set_list) { |
| 2726 | blk_mq_realloc_hw_ctxs(set, q); | 2757 | blk_mq_realloc_hw_ctxs(set, q); |
| 2727 | 2758 | ||
| @@ -2897,8 +2928,17 @@ bool blk_mq_poll(struct request_queue *q, blk_qc_t cookie) | |||
| 2897 | hctx = q->queue_hw_ctx[blk_qc_t_to_queue_num(cookie)]; | 2928 | hctx = q->queue_hw_ctx[blk_qc_t_to_queue_num(cookie)]; |
| 2898 | if (!blk_qc_t_is_internal(cookie)) | 2929 | if (!blk_qc_t_is_internal(cookie)) |
| 2899 | rq = blk_mq_tag_to_rq(hctx->tags, blk_qc_t_to_tag(cookie)); | 2930 | rq = blk_mq_tag_to_rq(hctx->tags, blk_qc_t_to_tag(cookie)); |
| 2900 | else | 2931 | else { |
| 2901 | rq = blk_mq_tag_to_rq(hctx->sched_tags, blk_qc_t_to_tag(cookie)); | 2932 | rq = blk_mq_tag_to_rq(hctx->sched_tags, blk_qc_t_to_tag(cookie)); |
| 2933 | /* | ||
| 2934 | * With scheduling, if the request has completed, we'll | ||
| 2935 | * get a NULL return here, as we clear the sched tag when | ||
| 2936 | * that happens. The request still remains valid, like always, | ||
| 2937 | * so we should be safe with just the NULL check. | ||
| 2938 | */ | ||
| 2939 | if (!rq) | ||
| 2940 | return false; | ||
| 2941 | } | ||
| 2902 | 2942 | ||
| 2903 | return __blk_mq_poll(hctx, rq); | 2943 | return __blk_mq_poll(hctx, rq); |
| 2904 | } | 2944 | } |
