Re: 4.5.0+ panic when setup loop device

From: Jens Axboe
Date: Thu Mar 17 2016 - 12:42:15 EST


On 03/17/2016 05:01 AM, Thomas Gleixner wrote:
On Thu, 17 Mar 2016, Peter Zijlstra wrote:
On Thu, Mar 17, 2016 at 12:39:46PM +0100, Thomas Gleixner wrote:
But we have to clarify and document whether holes in cpu_possible_mask are not
allowed at all or if code like the above is simply broken.

So the general rule is that cpumasks can have holes, and exempting one
just muddles the water.

Therefore I'd call the code just plain broken.

Agreed.

That macro is not really helping the readability of the code at all. So a
simple for_each_possible_cpu() loop would have avoided that wreckage.

Does the attached work? The rest of blk-mq should deal with holes just fine, we found some of those issues on sparc. Not sure why this one slipped through the cracks.

--
Jens Axboe

diff --git a/block/blk-mq.h b/block/blk-mq.h
index eaede8e45c9c..5a8ab6c2abe5 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -118,4 +118,22 @@ static inline bool blk_mq_hw_queue_mapped(struct blk_mq_hw_ctx *hctx)
return hctx->nr_ctx && hctx->tags;
}

+static inline struct blk_mq_ctx *next_ctx(struct request_queue *q, int *i)
+{
+ do {
+ (*i)++;
+ if (*i < q->nr_queues) {
+ if (cpu_possible(*i))
+ return per_cpu_ptr(q->queue_ctx, *i);
+ continue;
+ }
+ break;
+ } while (1);
+
+ return NULL;
+}
+
+#define queue_for_each_ctx(q, ctx, i) \
+ for ((i) = 0; (ctx = next_ctx((q), &(i))) != NULL;)
+
#endif
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 7fc9296b5742..a8756cd00767 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -261,22 +261,8 @@ static inline void *blk_mq_rq_to_pdu(struct request *rq)
for ((i) = 0; (i) < (q)->nr_hw_queues && \
({ hctx = (q)->queue_hw_ctx[i]; 1; }); (i)++)

-#define queue_for_each_ctx(q, ctx, i) \
- for ((i) = 0; (i) < (q)->nr_queues && \
- ({ ctx = per_cpu_ptr((q)->queue_ctx, (i)); 1; }); (i)++)
-
#define hctx_for_each_ctx(hctx, ctx, i) \
for ((i) = 0; (i) < (hctx)->nr_ctx && \
({ ctx = (hctx)->ctxs[(i)]; 1; }); (i)++)

-#define blk_ctx_sum(q, sum) \
-({ \
- struct blk_mq_ctx *__x; \
- unsigned int __ret = 0, __i; \
- \
- queue_for_each_ctx((q), __x, __i) \
- __ret += sum; \
- __ret; \
-})
-
#endif