summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-bufio.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2018-03-26 14:29:46 -0400
committerMike Snitzer <snitzer@redhat.com>2018-04-03 15:04:28 -0400
commitf51f2e0a7fb17af57634c65687c985c9b3449263 (patch)
tree16bc63fe23e61bb154d566ebd23f02051ab95ed0 /drivers/md/dm-bufio.c
parent359dbf19ab524652a2208a2a2cddccec2eede2ad (diff)
dm bufio: support non-power-of-two block sizes
Support block sizes that are not a power-of-two (but they must be a multiple of 512b). As always, a slab cache is used for allocations. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-bufio.c')
-rw-r--r--drivers/md/dm-bufio.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 4a216926ee19..e88797e04fcc 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -57,12 +57,6 @@
57#define DM_BUFIO_INLINE_VECS 16 57#define DM_BUFIO_INLINE_VECS 16
58 58
59/* 59/*
60 * Don't try to use alloc_pages for blocks larger than this.
61 * For explanation, see alloc_buffer_data below.
62 */
63#define DM_BUFIO_BLOCK_SIZE_GFP_LIMIT (PAGE_SIZE << (MAX_ORDER - 1))
64
65/*
66 * Align buffer writes to this boundary. 60 * Align buffer writes to this boundary.
67 * Tests show that SSDs have the highest IOPS when using 4k writes. 61 * Tests show that SSDs have the highest IOPS when using 4k writes.
68 */ 62 */
@@ -98,8 +92,7 @@ struct dm_bufio_client {
98 92
99 struct block_device *bdev; 93 struct block_device *bdev;
100 unsigned block_size; 94 unsigned block_size;
101 unsigned char sectors_per_block_bits; 95 s8 sectors_per_block_bits;
102 unsigned char pages_per_block_bits;
103 void (*alloc_callback)(struct dm_buffer *); 96 void (*alloc_callback)(struct dm_buffer *);
104 void (*write_callback)(struct dm_buffer *); 97 void (*write_callback)(struct dm_buffer *);
105 98
@@ -375,11 +368,11 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
375 return kmem_cache_alloc(c->slab_cache, gfp_mask); 368 return kmem_cache_alloc(c->slab_cache, gfp_mask);
376 } 369 }
377 370
378 if (c->block_size <= DM_BUFIO_BLOCK_SIZE_GFP_LIMIT && 371 if (c->block_size <= KMALLOC_MAX_SIZE &&
379 gfp_mask & __GFP_NORETRY) { 372 gfp_mask & __GFP_NORETRY) {
380 *data_mode = DATA_MODE_GET_FREE_PAGES; 373 *data_mode = DATA_MODE_GET_FREE_PAGES;
381 return (void *)__get_free_pages(gfp_mask, 374 return (void *)__get_free_pages(gfp_mask,
382 c->pages_per_block_bits); 375 c->sectors_per_block_bits - (PAGE_SHIFT - SECTOR_SHIFT));
383 } 376 }
384 377
385 *data_mode = DATA_MODE_VMALLOC; 378 *data_mode = DATA_MODE_VMALLOC;
@@ -416,7 +409,8 @@ static void free_buffer_data(struct dm_bufio_client *c,
416 break; 409 break;
417 410
418 case DATA_MODE_GET_FREE_PAGES: 411 case DATA_MODE_GET_FREE_PAGES:
419 free_pages((unsigned long)data, c->pages_per_block_bits); 412 free_pages((unsigned long)data,
413 c->sectors_per_block_bits - (PAGE_SHIFT - SECTOR_SHIFT));
420 break; 414 break;
421 415
422 case DATA_MODE_VMALLOC: 416 case DATA_MODE_VMALLOC:
@@ -634,10 +628,14 @@ static void submit_io(struct dm_buffer *b, int rw, bio_end_io_t *end_io)
634 sector_t sector; 628 sector_t sector;
635 unsigned offset, end; 629 unsigned offset, end;
636 630
637 sector = (b->block << b->c->sectors_per_block_bits) + b->c->start; 631 if (likely(b->c->sectors_per_block_bits >= 0))
632 sector = b->block << b->c->sectors_per_block_bits;
633 else
634 sector = b->block * (b->c->block_size >> SECTOR_SHIFT);
635 sector += b->c->start;
638 636
639 if (rw != REQ_OP_WRITE) { 637 if (rw != REQ_OP_WRITE) {
640 n_sectors = 1 << b->c->sectors_per_block_bits; 638 n_sectors = b->c->block_size >> SECTOR_SHIFT;
641 offset = 0; 639 offset = 0;
642 } else { 640 } else {
643 if (b->c->write_callback) 641 if (b->c->write_callback)
@@ -941,8 +939,11 @@ static void __get_memory_limit(struct dm_bufio_client *c,
941 } 939 }
942 } 940 }
943 941
944 buffers = dm_bufio_cache_size_per_client >> 942 buffers = dm_bufio_cache_size_per_client;
945 (c->sectors_per_block_bits + SECTOR_SHIFT); 943 if (likely(c->sectors_per_block_bits >= 0))
944 buffers >>= c->sectors_per_block_bits + SECTOR_SHIFT;
945 else
946 buffers /= c->block_size;
946 947
947 if (buffers < c->minimum_buffers) 948 if (buffers < c->minimum_buffers)
948 buffers = c->minimum_buffers; 949 buffers = c->minimum_buffers;
@@ -1476,8 +1477,12 @@ EXPORT_SYMBOL_GPL(dm_bufio_get_block_size);
1476 1477
1477sector_t dm_bufio_get_device_size(struct dm_bufio_client *c) 1478sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
1478{ 1479{
1479 return i_size_read(c->bdev->bd_inode) >> 1480 sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT;
1480 (SECTOR_SHIFT + c->sectors_per_block_bits); 1481 if (likely(c->sectors_per_block_bits >= 0))
1482 s >>= c->sectors_per_block_bits;
1483 else
1484 sector_div(s, c->block_size >> SECTOR_SHIFT);
1485 return s;
1481} 1486}
1482EXPORT_SYMBOL_GPL(dm_bufio_get_device_size); 1487EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
1483 1488
@@ -1575,8 +1580,12 @@ static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp)
1575 1580
1576static unsigned long get_retain_buffers(struct dm_bufio_client *c) 1581static unsigned long get_retain_buffers(struct dm_bufio_client *c)
1577{ 1582{
1578 unsigned long retain_bytes = READ_ONCE(dm_bufio_retain_bytes); 1583 unsigned long retain_bytes = READ_ONCE(dm_bufio_retain_bytes);
1579 return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT); 1584 if (likely(c->sectors_per_block_bits >= 0))
1585 retain_bytes >>= c->sectors_per_block_bits + SECTOR_SHIFT;
1586 else
1587 retain_bytes /= c->block_size;
1588 return retain_bytes;
1580} 1589}
1581 1590
1582static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, 1591static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
@@ -1642,8 +1651,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
1642 unsigned i; 1651 unsigned i;
1643 char slab_name[27]; 1652 char slab_name[27];
1644 1653
1645 BUG_ON(block_size < 1 << SECTOR_SHIFT || 1654 if (!block_size || block_size & ((1 << SECTOR_SHIFT) - 1)) {
1646 (block_size & (block_size - 1))); 1655 DMERR("%s: block size not specified or is not multiple of 512b", __func__);
1656 r = -EINVAL;
1657 goto bad_client;
1658 }
1647 1659
1648 c = kzalloc(sizeof(*c), GFP_KERNEL); 1660 c = kzalloc(sizeof(*c), GFP_KERNEL);
1649 if (!c) { 1661 if (!c) {
@@ -1654,9 +1666,10 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
1654 1666
1655 c->bdev = bdev; 1667 c->bdev = bdev;
1656 c->block_size = block_size; 1668 c->block_size = block_size;
1657 c->sectors_per_block_bits = __ffs(block_size) - SECTOR_SHIFT; 1669 if (is_power_of_2(block_size))
1658 c->pages_per_block_bits = (__ffs(block_size) >= PAGE_SHIFT) ? 1670 c->sectors_per_block_bits = __ffs(block_size) - SECTOR_SHIFT;
1659 __ffs(block_size) - PAGE_SHIFT : 0; 1671 else
1672 c->sectors_per_block_bits = -1;
1660 1673
1661 c->alloc_callback = alloc_callback; 1674 c->alloc_callback = alloc_callback;
1662 c->write_callback = write_callback; 1675 c->write_callback = write_callback;
@@ -1681,7 +1694,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
1681 goto bad_dm_io; 1694 goto bad_dm_io;
1682 } 1695 }
1683 1696
1684 if (block_size < PAGE_SIZE) { 1697 if (block_size <= KMALLOC_MAX_SIZE &&
1698 (block_size < PAGE_SIZE || !is_power_of_2(block_size))) {
1685 snprintf(slab_name, sizeof slab_name, "dm_bufio_cache-%u", c->block_size); 1699 snprintf(slab_name, sizeof slab_name, "dm_bufio_cache-%u", c->block_size);
1686 c->slab_cache = kmem_cache_create(slab_name, c->block_size, ARCH_KMALLOC_MINALIGN, 1700 c->slab_cache = kmem_cache_create(slab_name, c->block_size, ARCH_KMALLOC_MINALIGN,
1687 SLAB_RECLAIM_ACCOUNT, NULL); 1701 SLAB_RECLAIM_ACCOUNT, NULL);