Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24347e95 authored by Joe Thornber's avatar Joe Thornber Committed by Alasdair G Kergon
Browse files

dm thin: detect metadata device resizing



Allow the dm thin pool metadata device to be extended.

Whenever a pool is resumed, detect whether the size of the metadata
device has increased, and if so, extend the metadata to use the new
space.

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 1921c56d
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1677,6 +1677,18 @@ int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
	return r;
}

int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
{
	int r = -EINVAL;

	down_write(&pmd->root_lock);
	if (!pmd->fail_io)
		r = __resize_space_map(pmd->metadata_sm, new_count);
	up_write(&pmd->root_lock);

	return r;
}

void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
{
	down_write(&pmd->root_lock);
+1 −0
Original line number Diff line number Diff line
@@ -185,6 +185,7 @@ int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
 * blocks would be lost.
 */
int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);

/*
 * Flicks the underlying block manager into read only mode, so you know
+51 −3
Original line number Diff line number Diff line
@@ -1923,6 +1923,15 @@ static sector_t get_metadata_dev_size(struct block_device *bdev)
	return metadata_dev_size;
}

static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
{
	sector_t metadata_dev_size = get_metadata_dev_size(bdev);

	sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);

	return metadata_dev_size;
}

/*
 * thin-pool <metadata dev> <data dev>
 *	     <data block size (sectors)>
@@ -2132,6 +2141,41 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
	return 0;
}

static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
{
	int r;
	struct pool_c *pt = ti->private;
	struct pool *pool = pt->pool;
	dm_block_t metadata_dev_size, sb_metadata_dev_size;

	*need_commit = false;

	metadata_dev_size = get_metadata_dev_size(pool->md_dev);

	r = dm_pool_get_metadata_dev_size(pool->pmd, &sb_metadata_dev_size);
	if (r) {
		DMERR("failed to retrieve data device size");
		return r;
	}

	if (metadata_dev_size < sb_metadata_dev_size) {
		DMERR("metadata device (%llu sectors) too small: expected %llu",
		      metadata_dev_size, sb_metadata_dev_size);
		return -EINVAL;

	} else if (metadata_dev_size > sb_metadata_dev_size) {
		r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size);
		if (r) {
			DMERR("failed to resize metadata device");
			return r;
		}

		*need_commit = true;
	}

	return 0;
}

/*
 * Retrieves the number of blocks of the data device from
 * the superblock and compares it to the actual device size,
@@ -2146,7 +2190,7 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
static int pool_preresume(struct dm_target *ti)
{
	int r;
	bool need_commit1;
	bool need_commit1, need_commit2;
	struct pool_c *pt = ti->private;
	struct pool *pool = pt->pool;

@@ -2161,7 +2205,11 @@ static int pool_preresume(struct dm_target *ti)
	if (r)
		return r;

	if (need_commit1)
	r = maybe_resize_metadata_dev(ti, &need_commit2);
	if (r)
		return r;

	if (need_commit1 || need_commit2)
		(void) commit_or_fallback(pool);

	return 0;
@@ -2583,7 +2631,7 @@ static struct target_type pool_target = {
	.name = "thin-pool",
	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
		    DM_TARGET_IMMUTABLE,
	.version = {1, 7, 0},
	.version = {1, 8, 0},
	.module = THIS_MODULE,
	.ctr = pool_ctr,
	.dtr = pool_dtr,