Commit f9a8e0cd261fc05820539b0ea613686a32795406
Committed by
Alasdair G Kergon
1 parent
4929630901
Exists in
master
and in
20 other branches
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 a 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@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Showing 1 changed file with 16 additions and 7 deletions Side-by-side Diff
drivers/md/dm-thin.c
... | ... | @@ -512,6 +512,7 @@ |
512 | 512 | |
513 | 513 | dm_block_t low_water_blocks; |
514 | 514 | uint32_t sectors_per_block; |
515 | + int sectors_per_block_shift; | |
515 | 516 | |
516 | 517 | struct pool_features pf; |
517 | 518 | unsigned low_water_triggered:1; /* A dm event has been sent */ |
... | ... | @@ -679,7 +680,10 @@ |
679 | 680 | { |
680 | 681 | sector_t block_nr = bio->bi_sector; |
681 | 682 | |
682 | - (void) sector_div(block_nr, tc->pool->sectors_per_block); | |
683 | + if (tc->pool->sectors_per_block_shift < 0) | |
684 | + (void) sector_div(block_nr, tc->pool->sectors_per_block); | |
685 | + else | |
686 | + block_nr >>= tc->pool->sectors_per_block_shift; | |
683 | 687 | |
684 | 688 | return block_nr; |
685 | 689 | } |
... | ... | @@ -690,8 +694,12 @@ |
690 | 694 | sector_t bi_sector = bio->bi_sector; |
691 | 695 | |
692 | 696 | bio->bi_bdev = tc->pool_dev->bdev; |
693 | - bio->bi_sector = (block * pool->sectors_per_block) + | |
694 | - sector_div(bi_sector, pool->sectors_per_block); | |
697 | + if (tc->pool->sectors_per_block_shift < 0) | |
698 | + bio->bi_sector = (block * pool->sectors_per_block) + | |
699 | + sector_div(bi_sector, pool->sectors_per_block); | |
700 | + else | |
701 | + bio->bi_sector = (block << pool->sectors_per_block_shift) | | |
702 | + (bi_sector & (pool->sectors_per_block - 1)); | |
695 | 703 | } |
696 | 704 | |
697 | 705 | static void remap_to_origin(struct thin_c *tc, struct bio *bio) |
... | ... | @@ -936,10 +944,7 @@ |
936 | 944 | */ |
937 | 945 | static int io_overlaps_block(struct pool *pool, struct bio *bio) |
938 | 946 | { |
939 | - sector_t bi_sector = bio->bi_sector; | |
940 | - | |
941 | - return !sector_div(bi_sector, pool->sectors_per_block) && | |
942 | - (bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT)); | |
947 | + return bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT); | |
943 | 948 | } |
944 | 949 | |
945 | 950 | static int io_overwrites_block(struct pool *pool, struct bio *bio) |
... | ... | @@ -1721,6 +1726,10 @@ |
1721 | 1726 | |
1722 | 1727 | pool->pmd = pmd; |
1723 | 1728 | pool->sectors_per_block = block_size; |
1729 | + if (block_size & (block_size - 1)) | |
1730 | + pool->sectors_per_block_shift = -1; | |
1731 | + else | |
1732 | + pool->sectors_per_block_shift = __ffs(block_size); | |
1724 | 1733 | pool->low_water_blocks = 0; |
1725 | 1734 | pool_features_init(&pool->pf); |
1726 | 1735 | pool->prison = prison_create(PRISON_CELLS); |