Re: 4.5.0+ panic when setup loop device

From: Jens Axboe
Date: Thu Mar 17 2016 - 14:26:31 EST


On 03/17/2016 09:42 AM, Jens Axboe wrote:
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.

This might be better, we need to start at -1 to not miss the first one... Still untested.

--
Jens Axboe

diff --git a/block/blk-mq.h b/block/blk-mq.h
index eaede8e45c9c..ce68ceda652c 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) = -1; (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