blk-mq: fix and simplify tag iteration for the timeout handler
[linux-2.6-block.git] / block / blk-mq-tag.c
index c1b92426c95e28139134e51a68de2f724f8979f5..b08788086414fca765daa1b16be78c8367e6fac0 100644 (file)
@@ -392,45 +392,37 @@ void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, unsigned int tag,
                __blk_mq_put_reserved_tag(tags, tag);
 }
 
-static void bt_for_each_free(struct blk_mq_bitmap_tags *bt,
-                            unsigned long *free_map, unsigned int off)
+static void bt_for_each(struct blk_mq_hw_ctx *hctx,
+               struct blk_mq_bitmap_tags *bt, unsigned int off,
+               busy_iter_fn *fn, void *data, bool reserved)
 {
-       int i;
+       struct request *rq;
+       int bit, i;
 
        for (i = 0; i < bt->map_nr; i++) {
                struct blk_align_bitmap *bm = &bt->map[i];
-               int bit = 0;
-
-               do {
-                       bit = find_next_zero_bit(&bm->word, bm->depth, bit);
-                       if (bit >= bm->depth)
-                               break;
 
-                       __set_bit(bit + off, free_map);
-                       bit++;
-               } while (1);
+               for (bit = find_first_bit(&bm->word, bm->depth);
+                    bit < bm->depth;
+                    bit = find_next_bit(&bm->word, bm->depth, bit + 1)) {
+                       rq = blk_mq_tag_to_rq(hctx->tags, off + bit);
+                       if (rq->q == hctx->queue)
+                               fn(hctx, rq, data, reserved);
+               }
 
                off += (1 << bt->bits_per_word);
        }
 }
 
-void blk_mq_tag_busy_iter(struct blk_mq_tags *tags,
-                         void (*fn)(void *, unsigned long *), void *data)
+void blk_mq_tag_busy_iter(struct blk_mq_hw_ctx *hctx, busy_iter_fn *fn,
+               void *priv)
 {
-       unsigned long *tag_map;
-       size_t map_size;
-
-       map_size = ALIGN(tags->nr_tags, BITS_PER_LONG) / BITS_PER_LONG;
-       tag_map = kzalloc(map_size * sizeof(unsigned long), GFP_ATOMIC);
-       if (!tag_map)
-               return;
+       struct blk_mq_tags *tags = hctx->tags;
 
-       bt_for_each_free(&tags->bitmap_tags, tag_map, tags->nr_reserved_tags);
        if (tags->nr_reserved_tags)
-               bt_for_each_free(&tags->breserved_tags, tag_map, 0);
-
-       fn(data, tag_map);
-       kfree(tag_map);
+               bt_for_each(hctx, &tags->breserved_tags, 0, fn, priv, true);
+       bt_for_each(hctx, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
+                       false);
 }
 EXPORT_SYMBOL(blk_mq_tag_busy_iter);