summaryrefslogtreecommitdiff
path: root/drivers/md/dm-thin-metadata.c
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2015-11-05 15:10:11 +0000
committerMike Snitzer <snitzer@redhat.com>2015-12-10 10:30:56 -0500
commit3d5f67332ad9a500857a45397b69a27198720410 (patch)
tree7911d33cd1cca2e65fefcc5b25141781b5a99693 /drivers/md/dm-thin-metadata.c
parented8b45a3679eb49069b094c0711b30833f27c734 (diff)
dm thin metadata: speed up discard of partially mapped volumes
Use dm_btree_lookup_next() to more quickly discard partially mapped volumes. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-thin-metadata.c')
-rw-r--r--drivers/md/dm-thin-metadata.c66
1 files changed, 41 insertions, 25 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index c219a053c7f6..7547315ff18a 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1395,6 +1395,19 @@ static bool __snapshotted_since(struct dm_thin_device *td, uint32_t time)
return td->snapshotted_time > time;
}
+static void unpack_lookup_result(struct dm_thin_device *td, __le64 value,
+ struct dm_thin_lookup_result *result)
+{
+ uint64_t block_time = 0;
+ dm_block_t exception_block;
+ uint32_t exception_time;
+
+ block_time = le64_to_cpu(value);
+ unpack_block_time(block_time, &exception_block, &exception_time);
+ result->block = exception_block;
+ result->shared = __snapshotted_since(td, exception_time);
+}
+
int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
int can_issue_io, struct dm_thin_lookup_result *result)
{
@@ -1416,23 +1429,36 @@ int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
info = &pmd->nb_info;
r = dm_btree_lookup(info, pmd->root, keys, &value);
- if (!r) {
- uint64_t block_time = 0;
- dm_block_t exception_block;
- uint32_t exception_time;
-
- block_time = le64_to_cpu(value);
- unpack_block_time(block_time, &exception_block,
- &exception_time);
- result->block = exception_block;
- result->shared = __snapshotted_since(td, exception_time);
+ 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 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) {
+ up_read(&pmd->root_lock);
+ return -EINVAL;
}
+ 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;
}
-/* FIXME: write a more efficient one in btree */
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,
@@ -1445,21 +1471,11 @@ int dm_thin_find_mapped_range(struct dm_thin_device *td,
if (end < begin)
return -ENODATA;
- /*
- * Find first mapped block.
- */
- while (begin < end) {
- r = dm_thin_find_block(td, begin, true, &lookup);
- if (r) {
- if (r != -ENODATA)
- return r;
- } else
- break;
-
- begin++;
- }
+ r = dm_thin_find_next_mapped_block(td, begin, &begin, &lookup);
+ if (r)
+ return r;
- if (begin == end)
+ if (begin >= end)
return -ENODATA;
*thin_begin = begin;