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

Commit 086fbbbd authored by Joe Thornber's avatar Joe Thornber Committed by Mike Snitzer
Browse files

dm thin metadata: make dm_thin_find_mapped_range() atomic



Refactor dm_thin_find_mapped_range() so that it takes the read lock on
the metadata's lock; rather than relying on finer grained locking that
is pushed down inside dm_thin_find_next_mapped_block() and
dm_thin_find_block().

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 3d5f6733
Loading
Loading
Loading
Loading
+43 −21
Original line number Diff line number Diff line
@@ -1408,7 +1408,7 @@ static void unpack_lookup_result(struct dm_thin_device *td, __le64 value,
	result->shared = __snapshotted_since(td, exception_time);
}

int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
static int __find_block(struct dm_thin_device *td, dm_block_t block,
			int can_issue_io, struct dm_thin_lookup_result *result)
{
	int r;
@@ -1417,12 +1417,6 @@ int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
	dm_block_t keys[2] = { td->id, block };
	struct dm_btree_info *info;

	down_read(&pmd->root_lock);
	if (pmd->fail_io) {
		up_read(&pmd->root_lock);
		return -EINVAL;
	}

	if (can_issue_io) {
		info = &pmd->info;
	} else
@@ -1432,18 +1426,14 @@ int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
	if (!r)
		unpack_lookup_result(td, value, result);

	up_read(&pmd->root_lock);
	return r;
}

static int dm_thin_find_next_mapped_block(struct dm_thin_device *td, dm_block_t block,
					  dm_block_t *vblock,
					  struct dm_thin_lookup_result *result)
int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
		       int can_issue_io, struct dm_thin_lookup_result *result)
{
	int r;
	__le64 value;
	struct dm_pool_metadata *pmd = td->pmd;
	dm_block_t keys[2] = { td->id, block };

	down_read(&pmd->root_lock);
	if (pmd->fail_io) {
@@ -1451,15 +1441,29 @@ static int dm_thin_find_next_mapped_block(struct dm_thin_device *td, dm_block_t
		return -EINVAL;
	}

	r = __find_block(td, block, can_issue_io, result);

	up_read(&pmd->root_lock);
	return r;
}

static int __find_next_mapped_block(struct dm_thin_device *td, dm_block_t block,
					  dm_block_t *vblock,
					  struct dm_thin_lookup_result *result)
{
	int r;
	__le64 value;
	struct dm_pool_metadata *pmd = td->pmd;
	dm_block_t keys[2] = { td->id, block };

	r = dm_btree_lookup_next(&pmd->info, pmd->root, keys, vblock, &value);
	if (!r)
		unpack_lookup_result(td, value, result);

	up_read(&pmd->root_lock);
	return r;
}

int dm_thin_find_mapped_range(struct dm_thin_device *td,
static int __find_mapped_range(struct dm_thin_device *td,
			       dm_block_t begin, dm_block_t end,
			       dm_block_t *thin_begin, dm_block_t *thin_end,
			       dm_block_t *pool_begin, bool *maybe_shared)
@@ -1471,7 +1475,7 @@ int dm_thin_find_mapped_range(struct dm_thin_device *td,
	if (end < begin)
		return -ENODATA;

	r = dm_thin_find_next_mapped_block(td, begin, &begin, &lookup);
	r = __find_next_mapped_block(td, begin, &begin, &lookup);
	if (r)
		return r;

@@ -1485,7 +1489,7 @@ int dm_thin_find_mapped_range(struct dm_thin_device *td,
	begin++;
	pool_end = *pool_begin + 1;
	while (begin != end) {
		r = dm_thin_find_block(td, begin, true, &lookup);
		r = __find_block(td, begin, true, &lookup);
		if (r) {
			if (r == -ENODATA)
				break;
@@ -1505,6 +1509,24 @@ int dm_thin_find_mapped_range(struct dm_thin_device *td,
	return 0;
}

int dm_thin_find_mapped_range(struct dm_thin_device *td,
			      dm_block_t begin, dm_block_t end,
			      dm_block_t *thin_begin, dm_block_t *thin_end,
			      dm_block_t *pool_begin, bool *maybe_shared)
{
	int r = -EINVAL;
	struct dm_pool_metadata *pmd = td->pmd;

	down_read(&pmd->root_lock);
	if (!pmd->fail_io) {
		r = __find_mapped_range(td, begin, end, thin_begin, thin_end,
					pool_begin, maybe_shared);
	}
	up_read(&pmd->root_lock);

	return r;
}

static int __insert(struct dm_thin_device *td, dm_block_t block,
		    dm_block_t data_block)
{