dm thin: relax hard limit on the maximum size of a metadata device

The thin metadata format can only make use of a device that is <=
THIN_METADATA_MAX_SECTORS (currently 15.9375 GB).  Therefore, there is no
practical benefit to using a larger device.

However, it may be that other factors impose a certain granularity for
the space that is allocated to a device (E.g. lvm2 can impose a coarse
granularity through the use of large, >= 1 GB, physical extents).

Rather than reject a larger metadata device, during thin-pool device
construction, switch to allowing it but issue a warning if a device
larger than THIN_METADATA_MAX_SECTORS_WARNING (16 GB) is
provided.  Any space over 15.9375 GB will not be used.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
This commit is contained in:
Mike Snitzer 2012-03-28 18:41:28 +01:00 committed by Alasdair G Kergon
parent 71fd5ae25d
commit c4a69ecdb4
4 changed files with 25 additions and 18 deletions

View file

@ -75,10 +75,12 @@ less sharing than average you'll need a larger-than-average metadata device.
As a guide, we suggest you calculate the number of bytes to use in the As a guide, we suggest you calculate the number of bytes to use in the
metadata device as 48 * $data_dev_size / $data_block_size but round it up metadata device as 48 * $data_dev_size / $data_block_size but round it up
to 2MB if the answer is smaller. The largest size supported is 16GB. to 2MB if the answer is smaller. If you're creating large numbers of
snapshots which are recording large amounts of change, you may find you
need to increase this.
If you're creating large numbers of snapshots which are recording large The largest size supported is 16GB: If the device is larger,
amounts of change, you may need find you need to increase this. a warning will be issued and the excess space will not be used.
Reloading a pool table Reloading a pool table
---------------------- ----------------------

View file

@ -713,6 +713,9 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
if (r) if (r)
goto bad; goto bad;
if (bdev_size > THIN_METADATA_MAX_SECTORS)
bdev_size = THIN_METADATA_MAX_SECTORS;
disk_super = dm_block_data(sblock); disk_super = dm_block_data(sblock);
disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC); disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC);
disk_super->version = cpu_to_le32(THIN_VERSION); disk_super->version = cpu_to_le32(THIN_VERSION);

View file

@ -11,6 +11,19 @@
#define THIN_METADATA_BLOCK_SIZE 4096 #define THIN_METADATA_BLOCK_SIZE 4096
/*
* The metadata device is currently limited in size.
*
* We have one block of index, which can hold 255 index entries. Each
* index entry contains allocation info about 16k metadata blocks.
*/
#define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
/*
* A metadata device larger than 16GB triggers a warning.
*/
#define THIN_METADATA_MAX_SECTORS_WARNING (16 * (1024 * 1024 * 1024 >> SECTOR_SHIFT))
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
struct dm_pool_metadata; struct dm_pool_metadata;

View file

@ -32,16 +32,6 @@
#define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT) #define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
#define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT) #define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
/*
* The metadata device is currently limited in size. The limitation is
* checked lower down in dm-space-map-metadata, but we also check it here
* so we can fail early.
*
* We have one block of index, which can hold 255 index entries. Each
* index entry contains allocation info about 16k metadata blocks.
*/
#define METADATA_DEV_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
/* /*
* Device id is restricted to 24 bits. * Device id is restricted to 24 bits.
*/ */
@ -1736,6 +1726,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
dm_block_t low_water_blocks; dm_block_t low_water_blocks;
struct dm_dev *metadata_dev; struct dm_dev *metadata_dev;
sector_t metadata_dev_size; sector_t metadata_dev_size;
char b[BDEVNAME_SIZE];
/* /*
* FIXME Remove validation from scope of lock. * FIXME Remove validation from scope of lock.
@ -1757,11 +1748,9 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
} }
metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT; metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
if (metadata_dev_size > METADATA_DEV_MAX_SECTORS) { if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
ti->error = "Metadata device is too large"; DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
r = -EINVAL; bdevname(metadata_dev->bdev, b), THIN_METADATA_MAX_SECTORS);
goto out_metadata;
}
r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev); r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
if (r) { if (r) {