dm thin metadata: add dm_thin_remove_range()
authorJoe Thornber <ejt@redhat.com>
Mon, 13 Apr 2015 08:45:25 +0000 (09:45 +0100)
committerMike Snitzer <snitzer@redhat.com>
Thu, 11 Jun 2015 21:13:04 +0000 (17:13 -0400)
Removes a range of blocks from the btree.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h

index 94cf0db8a22ed59f000ac77d75b039330d4c6e7b..8b521e3e1e1b91e90e1821ddf70c37dd55a09d85 100644 (file)
@@ -1526,6 +1526,47 @@ static int __remove(struct dm_thin_device *td, dm_block_t block)
        return 0;
 }
 
+static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end)
+{
+       int r;
+       unsigned count;
+       struct dm_pool_metadata *pmd = td->pmd;
+       dm_block_t keys[1] = { td->id };
+       __le64 value;
+       dm_block_t mapping_root;
+
+       /*
+        * Find the mapping tree
+        */
+       r = dm_btree_lookup(&pmd->tl_info, pmd->root, keys, &value);
+       if (r)
+               return r;
+
+       /*
+        * Remove from the mapping tree, taking care to inc the
+        * ref count so it doesn't get deleted.
+        */
+       mapping_root = le64_to_cpu(value);
+       dm_tm_inc(pmd->tm, mapping_root);
+       r = dm_btree_remove(&pmd->tl_info, pmd->root, keys, &pmd->root);
+       if (r)
+               return r;
+
+       r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count);
+       if (r)
+               return r;
+
+       td->mapped_blocks -= count;
+       td->changed = 1;
+
+       /*
+        * Reinsert the mapping tree.
+        */
+       value = cpu_to_le64(mapping_root);
+       __dm_bless_for_disk(&value);
+       return dm_btree_insert(&pmd->tl_info, pmd->root, keys, &value, &pmd->root);
+}
+
 int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
 {
        int r = -EINVAL;
@@ -1538,6 +1579,19 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
        return r;
 }
 
+int dm_thin_remove_range(struct dm_thin_device *td,
+                        dm_block_t begin, dm_block_t end)
+{
+       int r = -EINVAL;
+
+       down_write(&td->pmd->root_lock);
+       if (!td->pmd->fail_io)
+               r = __remove_range(td, begin, end);
+       up_write(&td->pmd->root_lock);
+
+       return r;
+}
+
 int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
 {
        int r;
index f11f14095b93501ff64f275adbc44723cbee61f6..a938babe4258a79a5bec9f5af75e7c3ac1bb4c04 100644 (file)
@@ -167,6 +167,8 @@ int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
                         dm_block_t data_block);
 
 int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
+int dm_thin_remove_range(struct dm_thin_device *td,
+                        dm_block_t begin, dm_block_t end);
 
 /*
  * Queries.