Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm thin: allow metadata space larger than supported to go unused

It was always intended that a user could provide a thin metadata device
that is larger than the max supported by the on-disk format. The extra
space would just go unused.

Unfortunately that never worked. If the user attempted to use a larger
metadata device on creation they would get an error like the following:

device-mapper: space map common: space map too large
device-mapper: transaction manager: couldn't create metadata space map
device-mapper: thin metadata: tm_create_with_sm failed
device-mapper: table: 252:17: thin-pool: Error creating metadata object
device-mapper: ioctl: error adding target to table

Fix this by allowing the initial metadata space map creation to cap its
size at the max number of blocks supported (DM_SM_METADATA_MAX_BLOCKS).
get_metadata_dev_size() must also impose DM_SM_METADATA_MAX_BLOCKS (via
THIN_METADATA_MAX_SECTORS), otherwise extending metadata would cap at
THIN_METADATA_MAX_SECTORS_WARNING (which is larger than supported).

Also, the calculation for THIN_METADATA_MAX_SECTORS didn't account for
the sizeof the disk_bitmap_header. So the supported maximum metadata
size is a bit smaller (reduced from 33423360 to 33292800 sectors).

Lastly, remove the "excess space will not be used" warning message from
get_metadata_dev_size(); it resulted in printing the warning multiple
times. Factor out warn_if_metadata_device_too_big(), call it from
pool_ctr() and maybe_resize_metadata_dev().

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Acked-by: Joe Thornber <ejt@redhat.com>

+37 -19
+2 -2
drivers/md/dm-thin-metadata.c
··· 483 483 484 484 disk_super->data_mapping_root = cpu_to_le64(pmd->root); 485 485 disk_super->device_details_root = cpu_to_le64(pmd->details_root); 486 - disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); 486 + disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE); 487 487 disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT); 488 488 disk_super->data_block_size = cpu_to_le32(pmd->data_block_size); 489 489 ··· 651 651 { 652 652 int r; 653 653 654 - pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE, 654 + pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT, 655 655 THIN_METADATA_CACHE_SIZE, 656 656 THIN_MAX_CONCURRENT_LOCKS); 657 657 if (IS_ERR(pmd->bm)) {
+3 -5
drivers/md/dm-thin-metadata.h
··· 9 9 10 10 #include "persistent-data/dm-block-manager.h" 11 11 #include "persistent-data/dm-space-map.h" 12 + #include "persistent-data/dm-space-map-metadata.h" 12 13 13 - #define THIN_METADATA_BLOCK_SIZE 4096 14 + #define THIN_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE 14 15 15 16 /* 16 17 * The metadata device is currently limited in size. 17 - * 18 - * We have one block of index, which can hold 255 index entries. Each 19 - * index entry contains allocation info about 16k metadata blocks. 20 18 */ 21 - #define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT))) 19 + #define THIN_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS 22 20 23 21 /* 24 22 * A metadata device larger than 16GB triggers a warning.
+19 -12
drivers/md/dm-thin.c
··· 2000 2000 dm_table_event(pool->ti->table); 2001 2001 } 2002 2002 2003 - static sector_t get_metadata_dev_size(struct block_device *bdev) 2003 + static sector_t get_dev_size(struct block_device *bdev) 2004 2004 { 2005 - sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; 2005 + return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; 2006 + } 2007 + 2008 + static void warn_if_metadata_device_too_big(struct block_device *bdev) 2009 + { 2010 + sector_t metadata_dev_size = get_dev_size(bdev); 2006 2011 char buffer[BDEVNAME_SIZE]; 2007 2012 2008 - if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) { 2013 + if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) 2009 2014 DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.", 2010 2015 bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS); 2011 - metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING; 2012 - } 2016 + } 2017 + 2018 + static sector_t get_metadata_dev_size(struct block_device *bdev) 2019 + { 2020 + sector_t metadata_dev_size = get_dev_size(bdev); 2021 + 2022 + if (metadata_dev_size > THIN_METADATA_MAX_SECTORS) 2023 + metadata_dev_size = THIN_METADATA_MAX_SECTORS; 2013 2024 2014 2025 return metadata_dev_size; 2015 2026 } ··· 2029 2018 { 2030 2019 sector_t metadata_dev_size = get_metadata_dev_size(bdev); 2031 2020 2032 - sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); 2021 + sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE); 2033 2022 2034 2023 return metadata_dev_size; 2035 2024 } ··· 2107 2096 ti->error = "Error opening metadata block device"; 2108 2097 goto out_unlock; 2109 2098 } 2110 - 2111 - /* 2112 - * Run for the side-effect of possibly issuing a warning if the 2113 - * device is too big. 2114 - */ 2115 - (void) get_metadata_dev_size(metadata_dev->bdev); 2099 + warn_if_metadata_device_too_big(metadata_dev->bdev); 2116 2100 2117 2101 r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev); 2118 2102 if (r) { ··· 2294 2288 return -EINVAL; 2295 2289 2296 2290 } else if (metadata_dev_size > sb_metadata_dev_size) { 2291 + warn_if_metadata_device_too_big(pool->md_dev); 2297 2292 DMINFO("%s: growing the metadata device from %llu to %llu blocks", 2298 2293 dm_device_name(pool->pool_md), 2299 2294 sb_metadata_dev_size, metadata_dev_size);
+2
drivers/md/persistent-data/dm-space-map-metadata.c
··· 680 680 if (r) 681 681 return r; 682 682 683 + if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS) 684 + nr_blocks = DM_SM_METADATA_MAX_BLOCKS; 683 685 r = sm_ll_extend(&smm->ll, nr_blocks); 684 686 if (r) 685 687 return r;
+11
drivers/md/persistent-data/dm-space-map-metadata.h
··· 9 9 10 10 #include "dm-transaction-manager.h" 11 11 12 + #define DM_SM_METADATA_BLOCK_SIZE (4096 >> SECTOR_SHIFT) 13 + 14 + /* 15 + * The metadata device is currently limited in size. 16 + * 17 + * We have one block of index, which can hold 255 index entries. Each 18 + * index entry contains allocation info about ~16k metadata blocks. 19 + */ 20 + #define DM_SM_METADATA_MAX_BLOCKS (255 * ((1 << 14) - 64)) 21 + #define DM_SM_METADATA_MAX_SECTORS (DM_SM_METADATA_MAX_BLOCKS * DM_SM_METADATA_BLOCK_SIZE) 22 + 12 23 /* 13 24 * Unfortunately we have to use two-phase construction due to the cycle 14 25 * between the tm and sm.