block: use lcm_not_zero() when stacking chunk_sectors
authorMike Snitzer <snitzer@redhat.com>
Tue, 22 Sep 2020 02:32:48 +0000 (22:32 -0400)
committerJens Axboe <axboe@kernel.dk>
Wed, 23 Sep 2020 16:38:12 +0000 (10:38 -0600)
Like 'io_opt', blk_stack_limits() should stack 'chunk_sectors' using
lcm_not_zero() rather than min_not_zero() -- otherwise the final
'chunk_sectors' could result in sub-optimal alignment of IO to
component devices in the IO stack.

Also, if 'chunk_sectors' isn't a multiple of 'physical_block_size'
then it is a bug in the driver and the device should be flagged as
'misaligned'.

Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-settings.c

index 76a7e03..b2e1a92 100644 (file)
@@ -534,6 +534,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
 
        t->io_min = max(t->io_min, b->io_min);
        t->io_opt = lcm_not_zero(t->io_opt, b->io_opt);
+       t->chunk_sectors = lcm_not_zero(t->chunk_sectors, b->chunk_sectors);
 
        /* Physical block size a multiple of the logical block size? */
        if (t->physical_block_size & (t->logical_block_size - 1)) {
@@ -556,6 +557,13 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
                ret = -1;
        }
 
+       /* chunk_sectors a multiple of the physical block size? */
+       if ((t->chunk_sectors << 9) & (t->physical_block_size - 1)) {
+               t->chunk_sectors = 0;
+               t->misaligned = 1;
+               ret = -1;
+       }
+
        t->raid_partial_stripes_expensive =
                max(t->raid_partial_stripes_expensive,
                    b->raid_partial_stripes_expensive);
@@ -594,10 +602,6 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
                        t->discard_granularity;
        }
 
-       if (b->chunk_sectors)
-               t->chunk_sectors = min_not_zero(t->chunk_sectors,
-                                               b->chunk_sectors);
-
        t->zoned = max(t->zoned, b->zoned);
        return ret;
 }