block: allow 'chunk_sectors' to be non-power-of-2
[linux-2.6-microblaze.git] / block / blk-settings.c
index 76a7e03..5ea3de4 100644 (file)
@@ -172,15 +172,13 @@ EXPORT_SYMBOL(blk_queue_max_hw_sectors);
  *
  * Description:
  *    If a driver doesn't want IOs to cross a given chunk size, it can set
- *    this limit and prevent merging across chunks. Note that the chunk size
- *    must currently be a power-of-2 in sectors. Also note that the block
- *    layer must accept a page worth of data at any offset. So if the
- *    crossing of chunks is a hard limitation in the driver, it must still be
- *    prepared to split single page bios.
+ *    this limit and prevent merging across chunks. Note that the block layer
+ *    must accept a page worth of data at any offset. So if the crossing of
+ *    chunks is a hard limitation in the driver, it must still be prepared
+ *    to split single page bios.
  **/
 void blk_queue_chunk_sectors(struct request_queue *q, unsigned int chunk_sectors)
 {
-       BUG_ON(!is_power_of_2(chunk_sectors));
        q->limits.chunk_sectors = chunk_sectors;
 }
 EXPORT_SYMBOL(blk_queue_chunk_sectors);
@@ -534,6 +532,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 +555,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 +600,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;
 }