On 9/30/22 9:03 AM, Brian Foster wrote: > request_queue->queue_flags is an 8-byte field. Most queue flag > modifications occur through bit field helpers, but default flags can > be logically OR'd via the QUEUE_FLAG_MQ_DEFAULT mask. If this mask > happens to include bit 31, the assignment can sign extend the field > and set all upper 32 bits. > > This exact problem has been observed on a downstream kernel that > happens to use bit 31 for QUEUE_FLAG_NOWAIT. This is not an > immediate problem for current upstream because bit 31 is not > included in the default flag assignment (and is not used at all, > actually). Regardless, fix up the QUEUE_FLAG_MQ_DEFAULT mask > definition to avoid the landmine in the future. > > Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx> > --- > > Just to elaborate, I ran a quick test to change QUEUE_FLAG_NOWAIT to use > bit 31. With that change but without this patch, I see the following > queue state: > > # cat /sys/kernel/debug/block/vda/state > SAME_COMP|IO_STAT|INIT_DONE|WC|STATS|REGISTERED|30|NOWAIT|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63 > > And then with the patch applied: > > # cat /sys/kernel/debug/block/vda/state > SAME_COMP|IO_STAT|INIT_DONE|WC|STATS|REGISTERED|30|NOWAIT > > Thanks. > > Brian > > include/linux/blkdev.h | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > index 84b13fdd34a7..28c3037cb25c 100644 > --- a/include/linux/blkdev.h > +++ b/include/linux/blkdev.h > @@ -580,9 +580,9 @@ struct request_queue { > #define QUEUE_FLAG_NOWAIT 29 /* device supports NOWAIT */ > #define QUEUE_FLAG_SQ_SCHED 30 /* single queue style io dispatch */ > > -#define QUEUE_FLAG_MQ_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ > - (1 << QUEUE_FLAG_SAME_COMP) | \ > - (1 << QUEUE_FLAG_NOWAIT)) > +#define QUEUE_FLAG_MQ_DEFAULT ((1ULL << QUEUE_FLAG_IO_STAT) | \ > + (1ULL << QUEUE_FLAG_SAME_COMP) | \ > + (1ULL << QUEUE_FLAG_NOWAIT)) Shouldn't this just be 1UL << foo? The queue_flags are not 8-bytes, they are unsigned long. That happens to be 8-bytes on 64-bit archs, but it's 4-bytes on 32-bit archs. -- Jens Axboe