diff options
author | Mike Snitzer <snitzer@redhat.com> | 2014-02-12 23:58:15 -0500 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2014-02-27 11:49:08 -0500 |
commit | 7d48935eff401bb7970e73e822871a10e3643df1 (patch) | |
tree | cc7523512553a162b66e37d022da2c2e8acfee22 /drivers/md/dm-thin.c | |
parent | a1989b330093578ea5470bea0a00f940c444c466 (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.c | 31 |
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 | ||
2003 | static sector_t get_metadata_dev_size(struct block_device *bdev) | 2003 | static sector_t get_dev_size(struct block_device *bdev) |
2004 | { | ||
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) | ||
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 | |
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 | 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); |