diff options
author | Joe Thornber <ejt@redhat.com> | 2012-12-21 15:23:32 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2012-12-21 15:23:32 -0500 |
commit | e3cbf94513c21516fbb44561857b155d1c599625 (patch) | |
tree | fbcfb3427b34d8469e404d5b8f63c4dc9c0f98c8 /drivers | |
parent | 563af186df08002d2600c4e718ad8f3bde109f53 (diff) |
dm persistent data: fix nested btree deletion
When deleting nested btrees, the code forgets to delete the innermost
btree. The thin-metadata code serendipitously compensates for this by
claiming there is one extra layer in the tree.
This patch corrects both problems.
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/dm-thin-metadata.c | 2 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-btree.c | 9 |
2 files changed, 8 insertions, 3 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 693e149e9727..4d6e85367b84 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c | |||
@@ -408,7 +408,7 @@ static void __setup_btree_details(struct dm_pool_metadata *pmd) | |||
408 | 408 | ||
409 | pmd->tl_info.tm = pmd->tm; | 409 | pmd->tl_info.tm = pmd->tm; |
410 | pmd->tl_info.levels = 1; | 410 | pmd->tl_info.levels = 1; |
411 | pmd->tl_info.value_type.context = &pmd->info; | 411 | pmd->tl_info.value_type.context = &pmd->bl_info; |
412 | pmd->tl_info.value_type.size = sizeof(__le64); | 412 | pmd->tl_info.value_type.size = sizeof(__le64); |
413 | pmd->tl_info.value_type.inc = subtree_inc; | 413 | pmd->tl_info.value_type.inc = subtree_inc; |
414 | pmd->tl_info.value_type.dec = subtree_dec; | 414 | pmd->tl_info.value_type.dec = subtree_dec; |
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index 371f3d49d18e..4caf66918cdb 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c | |||
@@ -230,6 +230,11 @@ static void pop_frame(struct del_stack *s) | |||
230 | dm_tm_unlock(s->tm, f->b); | 230 | dm_tm_unlock(s->tm, f->b); |
231 | } | 231 | } |
232 | 232 | ||
233 | static bool is_internal_level(struct dm_btree_info *info, struct frame *f) | ||
234 | { | ||
235 | return f->level < (info->levels - 1); | ||
236 | } | ||
237 | |||
233 | int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | 238 | int dm_btree_del(struct dm_btree_info *info, dm_block_t root) |
234 | { | 239 | { |
235 | int r; | 240 | int r; |
@@ -241,7 +246,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | |||
241 | s->tm = info->tm; | 246 | s->tm = info->tm; |
242 | s->top = -1; | 247 | s->top = -1; |
243 | 248 | ||
244 | r = push_frame(s, root, 1); | 249 | r = push_frame(s, root, 0); |
245 | if (r) | 250 | if (r) |
246 | goto out; | 251 | goto out; |
247 | 252 | ||
@@ -267,7 +272,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | |||
267 | if (r) | 272 | if (r) |
268 | goto out; | 273 | goto out; |
269 | 274 | ||
270 | } else if (f->level != (info->levels - 1)) { | 275 | } else if (is_internal_level(info, f)) { |
271 | b = value64(f->n, f->current_child); | 276 | b = value64(f->n, f->current_child); |
272 | f->current_child++; | 277 | f->current_child++; |
273 | r = push_frame(s, b, f->level + 1); | 278 | r = push_frame(s, b, f->level + 1); |