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

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

dm thin: refactor data dev resize



Refactor device size functions in preparation for similar metadata
device resizing functions.

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 8c5008fa
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -1645,12 +1645,12 @@ int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
	return r;
}

static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
static int __resize_space_map(struct dm_space_map *sm, dm_block_t new_count)
{
	int r;
	dm_block_t old_count;

	r = dm_sm_get_nr_blocks(pmd->data_sm, &old_count);
	r = dm_sm_get_nr_blocks(sm, &old_count);
	if (r)
		return r;

@@ -1658,11 +1658,11 @@ static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
		return 0;

	if (new_count < old_count) {
		DMERR("cannot reduce size of data device");
		DMERR("cannot reduce size of space map");
		return -EINVAL;
	}

	return dm_sm_extend(pmd->data_sm, new_count - old_count);
	return dm_sm_extend(sm, new_count - old_count);
}

int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
@@ -1671,7 +1671,7 @@ int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)

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

	return r;
+59 −28
Original line number Diff line number Diff line
@@ -922,7 +922,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
		return r;

	if (free_blocks <= pool->low_water_blocks && !pool->low_water_triggered) {
		DMWARN("%s: reached low water mark, sending event.",
		DMWARN("%s: reached low water mark for data device: sending event.",
		       dm_device_name(pool->pool_md));
		spin_lock_irqsave(&pool->lock, flags);
		pool->low_water_triggered = 1;
@@ -1909,6 +1909,20 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
	return r;
}

static sector_t get_metadata_dev_size(struct block_device *bdev)
{
	sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
	char buffer[BDEVNAME_SIZE];

	if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) {
		DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
		       bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS);
		metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING;
	}

	return metadata_dev_size;
}

/*
 * thin-pool <metadata dev> <data dev>
 *	     <data block size (sectors)>
@@ -1931,8 +1945,6 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
	unsigned long block_size;
	dm_block_t low_water_blocks;
	struct dm_dev *metadata_dev;
	sector_t metadata_dev_size;
	char b[BDEVNAME_SIZE];

	/*
	 * FIXME Remove validation from scope of lock.
@@ -1953,10 +1965,11 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
		goto out_unlock;
	}

	metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
	if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
		DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
		       bdevname(metadata_dev->bdev, b), THIN_METADATA_MAX_SECTORS);
	/*
	 * Run for the side-effect of possibly issuing a warning if the
	 * device is too big.
	 */
	(void) get_metadata_dev_size(metadata_dev->bdev);

	r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
	if (r) {
@@ -2079,18 +2092,7 @@ static int pool_map(struct dm_target *ti, struct bio *bio)
	return r;
}

/*
 * Retrieves the number of blocks of the data device from
 * the superblock and compares it to the actual device size,
 * thus resizing the data device in case it has grown.
 *
 * This both copes with opening preallocated data devices in the ctr
 * being followed by a resume
 * -and-
 * calling the resume method individually after userspace has
 * grown the data device in reaction to a table event.
 */
static int pool_preresume(struct dm_target *ti)
static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
{
	int r;
	struct pool_c *pt = ti->private;
@@ -2098,12 +2100,7 @@ static int pool_preresume(struct dm_target *ti)
	sector_t data_size = ti->len;
	dm_block_t sb_data_size;

	/*
	 * Take control of the pool object.
	 */
	r = bind_control_target(pool, ti);
	if (r)
		return r;
	*need_commit = false;

	(void) sector_div(data_size, pool->sectors_per_block);

@@ -2114,7 +2111,7 @@ static int pool_preresume(struct dm_target *ti)
	}

	if (data_size < sb_data_size) {
		DMERR("pool target too small, is %llu blocks (expected %llu)",
		DMERR("pool target (%llu blocks) too small: expected %llu",
		      (unsigned long long)data_size, sb_data_size);
		return -EINVAL;

@@ -2122,17 +2119,51 @@ static int pool_preresume(struct dm_target *ti)
		r = dm_pool_resize_data_dev(pool->pmd, data_size);
		if (r) {
			DMERR("failed to resize data device");
			/* FIXME Stricter than necessary: Rollback transaction instead here */
			set_pool_mode(pool, PM_READ_ONLY);
			return r;
		}

		(void) commit_or_fallback(pool);
		*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,
 * thus resizing the data device in case it has grown.
 *
 * This both copes with opening preallocated data devices in the ctr
 * being followed by a resume
 * -and-
 * calling the resume method individually after userspace has
 * grown the data device in reaction to a table event.
 */
static int pool_preresume(struct dm_target *ti)
{
	int r;
	bool need_commit1;
	struct pool_c *pt = ti->private;
	struct pool *pool = pt->pool;

	/*
	 * Take control of the pool object.
	 */
	r = bind_control_target(pool, ti);
	if (r)
		return r;

	r = maybe_resize_data_dev(ti, &need_commit1);
	if (r)
		return r;

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

	return 0;
}

static void pool_resume(struct dm_target *ti)
{
	struct pool_c *pt = ti->private;