OSDN Git Service

net/x25: Fix null-ptr-deref caused by x25_disconnect
[uclinux-h8/linux.git] / block / blk-mq.c
index 9a9185a..8e659dc 100644 (file)
@@ -71,7 +71,8 @@ static int blk_mq_poll_stats_bkt(const struct request *rq)
 static inline struct blk_mq_hw_ctx *blk_qc_to_hctx(struct request_queue *q,
                blk_qc_t qc)
 {
-       return q->queue_hw_ctx[(qc & ~BLK_QC_T_INTERNAL) >> BLK_QC_T_SHIFT];
+       return xa_load(&q->hctx_table,
+                       (qc & ~BLK_QC_T_INTERNAL) >> BLK_QC_T_SHIFT);
 }
 
 static inline struct request *blk_qc_to_rq(struct blk_mq_hw_ctx *hctx,
@@ -312,7 +313,7 @@ EXPORT_SYMBOL_GPL(blk_mq_unquiesce_queue);
 void blk_mq_wake_waiters(struct request_queue *q)
 {
        struct blk_mq_hw_ctx *hctx;
-       unsigned int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i)
                if (blk_mq_hw_queue_mapped(hctx))
@@ -573,7 +574,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
         * If not tell the caller that it should skip this queue.
         */
        ret = -EXDEV;
-       data.hctx = q->queue_hw_ctx[hctx_idx];
+       data.hctx = xa_load(&q->hctx_table, hctx_idx);
        if (!blk_mq_hw_queue_mapped(data.hctx))
                goto out_queue_exit;
        cpu = cpumask_first_and(data.hctx->cpumask, cpu_online_mask);
@@ -793,8 +794,10 @@ bool blk_update_request(struct request *req, blk_status_t error,
 #endif
 
        if (unlikely(error && !blk_rq_is_passthrough(req) &&
-                    !(req->rq_flags & RQF_QUIET)))
+                    !(req->rq_flags & RQF_QUIET))) {
                blk_print_req_error(req, error);
+               trace_block_rq_error(req, error, nr_bytes);
+       }
 
        blk_account_io_completion(req, nr_bytes);
 
@@ -885,10 +888,15 @@ static inline void blk_account_io_done(struct request *req, u64 now)
 
 static void __blk_account_io_start(struct request *rq)
 {
-       /* passthrough requests can hold bios that do not have ->bi_bdev set */
-       if (rq->bio && rq->bio->bi_bdev)
+       /*
+        * All non-passthrough requests are created from a bio with one
+        * exception: when a flush command that is part of a flush sequence
+        * generated by the state machine in blk-flush.c is cloned onto the
+        * lower device by dm-multipath we can get here without a bio.
+        */
+       if (rq->bio)
                rq->part = rq->bio->bi_bdev;
-       else if (rq->q->disk)
+       else
                rq->part = rq->q->disk->part0;
 
        part_stat_lock();
@@ -1444,7 +1452,7 @@ static void blk_mq_timeout_work(struct work_struct *work)
                container_of(work, struct request_queue, timeout_work);
        unsigned long next = 0;
        struct blk_mq_hw_ctx *hctx;
-       int i;
+       unsigned long i;
 
        /* A deadlock might occur if a request is stuck requiring a
         * timeout at the same time a queue freeze is waiting
@@ -2145,7 +2153,7 @@ static struct blk_mq_hw_ctx *blk_mq_get_sq_hctx(struct request_queue *q)
 void blk_mq_run_hw_queues(struct request_queue *q, bool async)
 {
        struct blk_mq_hw_ctx *hctx, *sq_hctx;
-       int i;
+       unsigned long i;
 
        sq_hctx = NULL;
        if (blk_mq_has_sqsched(q))
@@ -2173,7 +2181,7 @@ EXPORT_SYMBOL(blk_mq_run_hw_queues);
 void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs)
 {
        struct blk_mq_hw_ctx *hctx, *sq_hctx;
-       int i;
+       unsigned long i;
 
        sq_hctx = NULL;
        if (blk_mq_has_sqsched(q))
@@ -2182,6 +2190,14 @@ void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs)
                if (blk_mq_hctx_stopped(hctx))
                        continue;
                /*
+                * If there is already a run_work pending, leave the
+                * pending delay untouched. Otherwise, a hctx can stall
+                * if another hctx is re-delaying the other's work
+                * before the work executes.
+                */
+               if (delayed_work_pending(&hctx->run_work))
+                       continue;
+               /*
                 * Dispatch from this hctx either if there's no hctx preferred
                 * by IO scheduler or if it has requests that bypass the
                 * scheduler.
@@ -2203,7 +2219,7 @@ EXPORT_SYMBOL(blk_mq_delay_run_hw_queues);
 bool blk_mq_queue_stopped(struct request_queue *q)
 {
        struct blk_mq_hw_ctx *hctx;
-       int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i)
                if (blk_mq_hctx_stopped(hctx))
@@ -2242,7 +2258,7 @@ EXPORT_SYMBOL(blk_mq_stop_hw_queue);
 void blk_mq_stop_hw_queues(struct request_queue *q)
 {
        struct blk_mq_hw_ctx *hctx;
-       int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i)
                blk_mq_stop_hw_queue(hctx);
@@ -2260,7 +2276,7 @@ EXPORT_SYMBOL(blk_mq_start_hw_queue);
 void blk_mq_start_hw_queues(struct request_queue *q)
 {
        struct blk_mq_hw_ctx *hctx;
-       int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i)
                blk_mq_start_hw_queue(hctx);
@@ -2280,7 +2296,7 @@ EXPORT_SYMBOL_GPL(blk_mq_start_stopped_hw_queue);
 void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async)
 {
        struct blk_mq_hw_ctx *hctx;
-       int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i)
                blk_mq_start_stopped_hw_queue(hctx, async);
@@ -2561,13 +2577,36 @@ static void __blk_mq_flush_plug_list(struct request_queue *q,
        q->mq_ops->queue_rqs(&plug->mq_list);
 }
 
+static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
+{
+       struct blk_mq_hw_ctx *this_hctx = NULL;
+       struct blk_mq_ctx *this_ctx = NULL;
+       struct request *requeue_list = NULL;
+       unsigned int depth = 0;
+       LIST_HEAD(list);
+
+       do {
+               struct request *rq = rq_list_pop(&plug->mq_list);
+
+               if (!this_hctx) {
+                       this_hctx = rq->mq_hctx;
+                       this_ctx = rq->mq_ctx;
+               } else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) {
+                       rq_list_add(&requeue_list, rq);
+                       continue;
+               }
+               list_add_tail(&rq->queuelist, &list);
+               depth++;
+       } while (!rq_list_empty(plug->mq_list));
+
+       plug->mq_list = requeue_list;
+       trace_block_unplug(this_hctx->queue, depth, !from_sched);
+       blk_mq_sched_insert_requests(this_hctx, this_ctx, &list, from_sched);
+}
+
 void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 {
-       struct blk_mq_hw_ctx *this_hctx;
-       struct blk_mq_ctx *this_ctx;
        struct request *rq;
-       unsigned int depth;
-       LIST_HEAD(list);
 
        if (rq_list_empty(plug->mq_list))
                return;
@@ -2603,35 +2642,9 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
                        return;
        }
 
-       this_hctx = NULL;
-       this_ctx = NULL;
-       depth = 0;
        do {
-               rq = rq_list_pop(&plug->mq_list);
-
-               if (!this_hctx) {
-                       this_hctx = rq->mq_hctx;
-                       this_ctx = rq->mq_ctx;
-               } else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) {
-                       trace_block_unplug(this_hctx->queue, depth,
-                                               !from_schedule);
-                       blk_mq_sched_insert_requests(this_hctx, this_ctx,
-                                               &list, from_schedule);
-                       depth = 0;
-                       this_hctx = rq->mq_hctx;
-                       this_ctx = rq->mq_ctx;
-
-               }
-
-               list_add(&rq->queuelist, &list);
-               depth++;
+               blk_mq_dispatch_plug_list(plug, from_schedule);
        } while (!rq_list_empty(plug->mq_list));
-
-       if (!list_empty(&list)) {
-               trace_block_unplug(this_hctx->queue, depth, !from_schedule);
-               blk_mq_sched_insert_requests(this_hctx, this_ctx, &list,
-                                               from_schedule);
-       }
 }
 
 void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
@@ -2804,9 +2817,6 @@ void blk_mq_submit_bio(struct bio *bio)
        unsigned int nr_segs = 1;
        blk_status_t ret;
 
-       if (unlikely(!blk_crypto_bio_prep(&bio)))
-               return;
-
        blk_queue_bounce(q, &bio);
        if (blk_may_split(q, bio))
                __blk_queue_split(q, &bio, &nr_segs);
@@ -2853,27 +2863,16 @@ void blk_mq_submit_bio(struct bio *bio)
                                blk_mq_try_issue_directly(rq->mq_hctx, rq));
 }
 
+#ifdef CONFIG_BLK_MQ_STACKING
 /**
- * blk_cloned_rq_check_limits - Helper function to check a cloned request
- *                              for the new queue limits
- * @q:  the queue
- * @rq: the request being checked
- *
- * Description:
- *    @rq may have been made based on weaker limitations of upper-level queues
- *    in request stacking drivers, and it may violate the limitation of @q.
- *    Since the block layer and the underlying device driver trust @rq
- *    after it is inserted to @q, it should be checked against @q before
- *    the insertion using this generic function.
- *
- *    Request stacking drivers like request-based dm may change the queue
- *    limits when retrying requests on other queues. Those requests need
- *    to be checked against the new queue limits again during dispatch.
+ * blk_insert_cloned_request - Helper for stacking drivers to submit a request
+ * @rq: the request being queued
  */
-static blk_status_t blk_cloned_rq_check_limits(struct request_queue *q,
-                                     struct request *rq)
+blk_status_t blk_insert_cloned_request(struct request *rq)
 {
+       struct request_queue *q = rq->q;
        unsigned int max_sectors = blk_queue_get_max_sectors(q, req_op(rq));
+       blk_status_t ret;
 
        if (blk_rq_sectors(rq) > max_sectors) {
                /*
@@ -2905,24 +2904,7 @@ static blk_status_t blk_cloned_rq_check_limits(struct request_queue *q,
                return BLK_STS_IOERR;
        }
 
-       return BLK_STS_OK;
-}
-
-/**
- * blk_insert_cloned_request - Helper for stacking drivers to submit a request
- * @q:  the queue to submit the request
- * @rq: the request being queued
- */
-blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *rq)
-{
-       blk_status_t ret;
-
-       ret = blk_cloned_rq_check_limits(q, rq);
-       if (ret != BLK_STS_OK)
-               return ret;
-
-       if (rq->q->disk &&
-           should_fail_request(rq->q->disk->part0, blk_rq_bytes(rq)))
+       if (q->disk && should_fail_request(q->disk->part0, blk_rq_bytes(rq)))
                return BLK_STS_IOERR;
 
        if (blk_crypto_insert_cloned_request(rq))
@@ -2935,7 +2917,7 @@ blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *
         * bypass a potential scheduler on the bottom device for
         * insert.
         */
-       blk_mq_run_dispatch_ops(rq->q,
+       blk_mq_run_dispatch_ops(q,
                        ret = blk_mq_request_issue_directly(rq, true));
        if (ret)
                blk_account_io_done(rq, ktime_get_ns());
@@ -2990,10 +2972,10 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
                bs = &fs_bio_set;
 
        __rq_for_each_bio(bio_src, rq_src) {
-               bio = bio_clone_fast(bio_src, gfp_mask, bs);
+               bio = bio_alloc_clone(rq->q->disk->part0, bio_src, gfp_mask,
+                                     bs);
                if (!bio)
                        goto free_and_out;
-               bio->bi_bdev = rq->q->disk->part0;
 
                if (bio_ctr && bio_ctr(bio, bio_src, data))
                        goto free_and_out;
@@ -3030,6 +3012,7 @@ free_and_out:
        return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(blk_rq_prep_clone);
+#endif /* CONFIG_BLK_MQ_STACKING */
 
 /*
  * Steal bios from a request and add them to a bio list.
@@ -3100,6 +3083,9 @@ void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
        struct blk_mq_tags *drv_tags;
        struct page *page;
 
+       if (list_empty(&tags->page_list))
+               return;
+
        if (blk_mq_is_shared_tags(set->flags))
                drv_tags = set->shared_tags;
        else
@@ -3142,15 +3128,41 @@ void blk_mq_free_rq_map(struct blk_mq_tags *tags)
        blk_mq_free_tags(tags);
 }
 
+static enum hctx_type hctx_idx_to_type(struct blk_mq_tag_set *set,
+               unsigned int hctx_idx)
+{
+       int i;
+
+       for (i = 0; i < set->nr_maps; i++) {
+               unsigned int start = set->map[i].queue_offset;
+               unsigned int end = start + set->map[i].nr_queues;
+
+               if (hctx_idx >= start && hctx_idx < end)
+                       break;
+       }
+
+       if (i >= set->nr_maps)
+               i = HCTX_TYPE_DEFAULT;
+
+       return i;
+}
+
+static int blk_mq_get_hctx_node(struct blk_mq_tag_set *set,
+               unsigned int hctx_idx)
+{
+       enum hctx_type type = hctx_idx_to_type(set, hctx_idx);
+
+       return blk_mq_hw_queue_to_node(&set->map[type], hctx_idx);
+}
+
 static struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set,
                                               unsigned int hctx_idx,
                                               unsigned int nr_tags,
                                               unsigned int reserved_tags)
 {
+       int node = blk_mq_get_hctx_node(set, hctx_idx);
        struct blk_mq_tags *tags;
-       int node;
 
-       node = blk_mq_hw_queue_to_node(&set->map[HCTX_TYPE_DEFAULT], hctx_idx);
        if (node == NUMA_NO_NODE)
                node = set->numa_node;
 
@@ -3199,10 +3211,9 @@ static int blk_mq_alloc_rqs(struct blk_mq_tag_set *set,
                            unsigned int hctx_idx, unsigned int depth)
 {
        unsigned int i, j, entries_per_page, max_order = 4;
+       int node = blk_mq_get_hctx_node(set, hctx_idx);
        size_t rq_size, left;
-       int node;
 
-       node = blk_mq_hw_queue_to_node(&set->map[HCTX_TYPE_DEFAULT], hctx_idx);
        if (node == NUMA_NO_NODE)
                node = set->numa_node;
 
@@ -3447,6 +3458,8 @@ static void blk_mq_exit_hctx(struct request_queue *q,
 
        blk_mq_remove_cpuhp(hctx);
 
+       xa_erase(&q->hctx_table, hctx_idx);
+
        spin_lock(&q->unused_hctx_lock);
        list_add(&hctx->hctx_list, &q->unused_hctx_list);
        spin_unlock(&q->unused_hctx_lock);
@@ -3456,12 +3469,11 @@ static void blk_mq_exit_hw_queues(struct request_queue *q,
                struct blk_mq_tag_set *set, int nr_queue)
 {
        struct blk_mq_hw_ctx *hctx;
-       unsigned int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i) {
                if (i == nr_queue)
                        break;
-               blk_mq_debugfs_unregister_hctx(hctx);
                blk_mq_exit_hctx(q, set, hctx, i);
        }
 }
@@ -3486,8 +3498,15 @@ static int blk_mq_init_hctx(struct request_queue *q,
        if (blk_mq_init_request(set, hctx->fq->flush_rq, hctx_idx,
                                hctx->numa_node))
                goto exit_hctx;
+
+       if (xa_insert(&q->hctx_table, hctx_idx, hctx, GFP_KERNEL))
+               goto exit_flush_rq;
+
        return 0;
 
+ exit_flush_rq:
+       if (set->ops->exit_request)
+               set->ops->exit_request(set, hctx->fq->flush_rq, hctx_idx);
  exit_hctx:
        if (set->ops->exit_hctx)
                set->ops->exit_hctx(hctx, hctx_idx);
@@ -3647,7 +3666,8 @@ static void __blk_mq_free_map_and_rqs(struct blk_mq_tag_set *set,
 
 static void blk_mq_map_swqueue(struct request_queue *q)
 {
-       unsigned int i, j, hctx_idx;
+       unsigned int j, hctx_idx;
+       unsigned long i;
        struct blk_mq_hw_ctx *hctx;
        struct blk_mq_ctx *ctx;
        struct blk_mq_tag_set *set = q->tag_set;
@@ -3754,7 +3774,7 @@ static void blk_mq_map_swqueue(struct request_queue *q)
 static void queue_set_hctx_shared(struct request_queue *q, bool shared)
 {
        struct blk_mq_hw_ctx *hctx;
-       int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i) {
                if (shared) {
@@ -3854,7 +3874,7 @@ static int blk_mq_alloc_ctxs(struct request_queue *q)
 void blk_mq_release(struct request_queue *q)
 {
        struct blk_mq_hw_ctx *hctx, *next;
-       int i;
+       unsigned long i;
 
        queue_for_each_hw_ctx(q, hctx, i)
                WARN_ON_ONCE(hctx && list_empty(&hctx->hctx_list));
@@ -3865,7 +3885,7 @@ void blk_mq_release(struct request_queue *q)
                kobject_put(&hctx->kobj);
        }
 
-       kfree(q->queue_hw_ctx);
+       xa_destroy(&q->hctx_table);
 
        /*
         * release .mq_kobj and sw queue's kobject now because
@@ -3954,52 +3974,28 @@ static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
 static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
                                                struct request_queue *q)
 {
-       int i, j, end;
-       struct blk_mq_hw_ctx **hctxs = q->queue_hw_ctx;
-
-       if (q->nr_hw_queues < set->nr_hw_queues) {
-               struct blk_mq_hw_ctx **new_hctxs;
-
-               new_hctxs = kcalloc_node(set->nr_hw_queues,
-                                      sizeof(*new_hctxs), GFP_KERNEL,
-                                      set->numa_node);
-               if (!new_hctxs)
-                       return;
-               if (hctxs)
-                       memcpy(new_hctxs, hctxs, q->nr_hw_queues *
-                              sizeof(*hctxs));
-               q->queue_hw_ctx = new_hctxs;
-               kfree(hctxs);
-               hctxs = new_hctxs;
-       }
+       struct blk_mq_hw_ctx *hctx;
+       unsigned long i, j;
 
        /* protect against switching io scheduler  */
        mutex_lock(&q->sysfs_lock);
        for (i = 0; i < set->nr_hw_queues; i++) {
-               int node;
-               struct blk_mq_hw_ctx *hctx;
+               int old_node;
+               int node = blk_mq_get_hctx_node(set, i);
+               struct blk_mq_hw_ctx *old_hctx = xa_load(&q->hctx_table, i);
 
-               node = blk_mq_hw_queue_to_node(&set->map[HCTX_TYPE_DEFAULT], i);
-               /*
-                * If the hw queue has been mapped to another numa node,
-                * we need to realloc the hctx. If allocation fails, fallback
-                * to use the previous one.
-                */
-               if (hctxs[i] && (hctxs[i]->numa_node == node))
-                       continue;
+               if (old_hctx) {
+                       old_node = old_hctx->numa_node;
+                       blk_mq_exit_hctx(q, set, old_hctx, i);
+               }
 
-               hctx = blk_mq_alloc_and_init_hctx(set, q, i, node);
-               if (hctx) {
-                       if (hctxs[i])
-                               blk_mq_exit_hctx(q, set, hctxs[i], i);
-                       hctxs[i] = hctx;
-               } else {
-                       if (hctxs[i])
-                               pr_warn("Allocate new hctx on node %d fails,\
-                                               fallback to previous one on node %d\n",
-                                               node, hctxs[i]->numa_node);
-                       else
+               if (!blk_mq_alloc_and_init_hctx(set, q, i, node)) {
+                       if (!old_hctx)
                                break;
+                       pr_warn("Allocate new hctx on node %d fails, fallback to previous one on node %d\n",
+                                       node, old_node);
+                       hctx = blk_mq_alloc_and_init_hctx(set, q, i, old_node);
+                       WARN_ON_ONCE(!hctx);
                }
        }
        /*
@@ -4008,24 +4004,27 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
         */
        if (i != set->nr_hw_queues) {
                j = q->nr_hw_queues;
-               end = i;
        } else {
                j = i;
-               end = q->nr_hw_queues;
                q->nr_hw_queues = set->nr_hw_queues;
        }
 
-       for (; j < end; j++) {
-               struct blk_mq_hw_ctx *hctx = hctxs[j];
-
-               if (hctx) {
-                       blk_mq_exit_hctx(q, set, hctx, j);
-                       hctxs[j] = NULL;
-               }
-       }
+       xa_for_each_start(&q->hctx_table, j, hctx, j)
+               blk_mq_exit_hctx(q, set, hctx, j);
        mutex_unlock(&q->sysfs_lock);
 }
 
+static void blk_mq_update_poll_flag(struct request_queue *q)
+{
+       struct blk_mq_tag_set *set = q->tag_set;
+
+       if (set->nr_maps > HCTX_TYPE_POLL &&
+           set->map[HCTX_TYPE_POLL].nr_queues)
+               blk_queue_flag_set(QUEUE_FLAG_POLL, q);
+       else
+               blk_queue_flag_clear(QUEUE_FLAG_POLL, q);
+}
+
 int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
                struct request_queue *q)
 {
@@ -4050,6 +4049,8 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        INIT_LIST_HEAD(&q->unused_hctx_list);
        spin_lock_init(&q->unused_hctx_lock);
 
+       xa_init(&q->hctx_table);
+
        blk_mq_realloc_hw_ctxs(set, q);
        if (!q->nr_hw_queues)
                goto err_hctxs;
@@ -4060,9 +4061,7 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        q->tag_set = set;
 
        q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;
-       if (set->nr_maps > HCTX_TYPE_POLL &&
-           set->map[HCTX_TYPE_POLL].nr_queues)
-               blk_queue_flag_set(QUEUE_FLAG_POLL, q);
+       blk_mq_update_poll_flag(q);
 
        INIT_DELAYED_WORK(&q->requeue_work, blk_mq_requeue_work);
        INIT_LIST_HEAD(&q->requeue_list);
@@ -4081,7 +4080,7 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        return 0;
 
 err_hctxs:
-       kfree(q->queue_hw_ctx);
+       xa_destroy(&q->hctx_table);
        q->nr_hw_queues = 0;
        blk_mq_sysfs_deinit(q);
 err_poll:
@@ -4369,7 +4368,8 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
 {
        struct blk_mq_tag_set *set = q->tag_set;
        struct blk_mq_hw_ctx *hctx;
-       int i, ret;
+       int ret;
+       unsigned long i;
 
        if (!set)
                return -EINVAL;
@@ -4528,6 +4528,7 @@ fallback:
        blk_mq_update_queue_map(set);
        list_for_each_entry(q, &set->tag_list, tag_set_list) {
                blk_mq_realloc_hw_ctxs(set, q);
+               blk_mq_update_poll_flag(q);
                if (q->nr_hw_queues != set->nr_hw_queues) {
                        int i = prev_nr_hw_queues;
 
@@ -4744,7 +4745,7 @@ void blk_mq_cancel_work_sync(struct request_queue *q)
 {
        if (queue_is_mq(q)) {
                struct blk_mq_hw_ctx *hctx;
-               int i;
+               unsigned long i;
 
                cancel_delayed_work_sync(&q->requeue_work);