aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-thin.c
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2014-02-12 23:58:15 -0500
committerMike Snitzer <snitzer@redhat.com>2014-02-27 11:49:08 -0500
commit7d48935eff401bb7970e73e822871a10e3643df1 (patch)
treecc7523512553a162b66e37d022da2c2e8acfee22 /drivers/md/dm-thin.c
parenta1989b330093578ea5470bea0a00f940c444c466 (diff)
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>
Diffstat (limited to 'drivers/md/dm-thin.c')
-rw-r--r--drivers/md/dm-thin.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 4cf4b198cb60..7e84baccf0ad 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2000,16 +2000,27 @@ static void metadata_low_callback(void *context)
2000 dm_table_event(pool->ti->table); 2000 dm_table_event(pool->ti->table);
2001} 2001}
2002 2002
2003static sector_t get_metadata_dev_size(struct block_device *bdev) 2003static sector_t get_dev_size(struct block_device *bdev)
2004{
2005 return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
2006}
2007
2008static void warn_if_metadata_device_too_big(struct block_device *bdev)
2004{ 2009{
2005 sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; 2010 sector_t metadata_dev_size = get_dev_size(bdev);
2006 char buffer[BDEVNAME_SIZE]; 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 DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.", 2014 DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
2010 bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS); 2015 bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS);
2011 metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING; 2016}
2012 } 2017
2018static 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 return metadata_dev_size; 2025 return metadata_dev_size;
2015} 2026}
@@ -2018,7 +2029,7 @@ static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
2018{ 2029{
2019 sector_t metadata_dev_size = get_metadata_dev_size(bdev); 2030 sector_t metadata_dev_size = get_metadata_dev_size(bdev);
2020 2031
2021 sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); 2032 sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE);
2022 2033
2023 return metadata_dev_size; 2034 return metadata_dev_size;
2024} 2035}
@@ -2096,12 +2107,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
2096 ti->error = "Error opening metadata block device"; 2107 ti->error = "Error opening metadata block device";
2097 goto out_unlock; 2108 goto out_unlock;
2098 } 2109 }
2099 2110 warn_if_metadata_device_too_big(metadata_dev->bdev);
2100 /*
2101 * Run for the side-effect of possibly issuing a warning if the
2102 * device is too big.
2103 */
2104 (void) get_metadata_dev_size(metadata_dev->bdev);
2105 2111
2106 r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev); 2112 r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
2107 if (r) { 2113 if (r) {
@@ -2288,6 +2294,7 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
2288 return -EINVAL; 2294 return -EINVAL;
2289 2295
2290 } else if (metadata_dev_size > sb_metadata_dev_size) { 2296 } else if (metadata_dev_size > sb_metadata_dev_size) {
2297 warn_if_metadata_device_too_big(pool->md_dev);
2291 DMINFO("%s: growing the metadata device from %llu to %llu blocks", 2298 DMINFO("%s: growing the metadata device from %llu to %llu blocks",
2292 dm_device_name(pool->pool_md), 2299 dm_device_name(pool->pool_md),
2293 sb_metadata_dev_size, metadata_dev_size); 2300 sb_metadata_dev_size, metadata_dev_size);