[dm-devel] [PATCH] dm-thin: optimize power of two block size
Mikulas Patocka
mpatocka at redhat.com
Mon Jun 18 14:09:56 UTC 2012
Hi
This patch should be applied after
dm-thin-support-for-non-power-of-2-pool-blocksize.patch. It optimizes
power-of-two blocksize.
Mikulas
---
dm-thin: optimize power of two block size
dm-thin will be most likely used with a block size that is a power of
two. So it should be optimized for this case.
This patch changes division and modulo operations to shifts and bit
masks if block size is a power of two.
A test that bi_sector is divisible by a block size is removed from
io_overlaps_block. Device mapper never sends bios that span block
boundary. Consequently, if we tested that bi_size is equivalent to block
size, bi_sector must already be on a block boundary.
Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
---
drivers/md/dm-thin.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
Index: linux-3.4.2-fast/drivers/md/dm-thin.c
===================================================================
--- linux-3.4.2-fast.orig/drivers/md/dm-thin.c 2012-06-18 15:38:53.000000000 +0200
+++ linux-3.4.2-fast/drivers/md/dm-thin.c 2012-06-18 16:06:15.000000000 +0200
@@ -512,6 +512,7 @@ struct pool {
dm_block_t low_water_blocks;
uint32_t sectors_per_block;
+ int sectors_per_block_shift;
struct pool_features pf;
unsigned low_water_triggered:1; /* A dm event has been sent */
@@ -678,7 +679,10 @@ static dm_block_t get_bio_block(struct t
{
sector_t block_nr = bio->bi_sector;
- (void) sector_div(block_nr, tc->pool->sectors_per_block);
+ if (tc->pool->sectors_per_block_shift < 0)
+ (void) sector_div(block_nr, tc->pool->sectors_per_block);
+ else
+ block_nr >>= tc->pool->sectors_per_block_shift;
return block_nr;
}
@@ -689,8 +693,12 @@ static void remap(struct thin_c *tc, str
sector_t bi_sector = bio->bi_sector;
bio->bi_bdev = tc->pool_dev->bdev;
- bio->bi_sector = (block * pool->sectors_per_block) +
- sector_div(bi_sector, pool->sectors_per_block);
+ if (tc->pool->sectors_per_block_shift < 0)
+ bio->bi_sector = (block * pool->sectors_per_block) +
+ sector_div(bi_sector, pool->sectors_per_block);
+ else
+ bio->bi_sector = (block << pool->sectors_per_block_shift) |
+ (bi_sector & (pool->sectors_per_block - 1));
}
static void remap_to_origin(struct thin_c *tc, struct bio *bio)
@@ -935,10 +943,7 @@ static void process_prepared(struct pool
*/
static int io_overlaps_block(struct pool *pool, struct bio *bio)
{
- sector_t bi_sector = bio->bi_sector;
-
- return !sector_div(bi_sector, pool->sectors_per_block) &&
- (bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
+ return bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT);
}
static int io_overwrites_block(struct pool *pool, struct bio *bio)
@@ -1241,7 +1246,9 @@ static void process_discard(struct thin_
* part of the discard that is in a subsequent
* block.
*/
- sector_t offset = bio->bi_sector - (block * pool->sectors_per_block);
+ sector_t offset = pool->sectors_per_block_shift >= 0 ?
+ bio->bi_sector & (pool->sectors_per_block - 1) :
+ bio->bi_sector - block * pool->sectors_per_block;
unsigned remaining = (pool->sectors_per_block - offset) << SECTOR_SHIFT;
bio->bi_size = min(bio->bi_size, remaining);
@@ -1718,6 +1725,10 @@ static struct pool *pool_create(struct m
pool->pmd = pmd;
pool->sectors_per_block = block_size;
+ if (block_size & (block_size - 1))
+ pool->sectors_per_block_shift = -1;
+ else
+ pool->sectors_per_block_shift = __ffs(block_size);
pool->low_water_blocks = 0;
pool_features_init(&pool->pf);
pool->prison = prison_create(PRISON_CELLS);
More information about the dm-devel
mailing list