aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2012-12-21 15:23:32 -0500
committerAlasdair G Kergon <agk@redhat.com>2012-12-21 15:23:32 -0500
commite3cbf94513c21516fbb44561857b155d1c599625 (patch)
treefbcfb3427b34d8469e404d5b8f63c4dc9c0f98c8
parent563af186df08002d2600c4e718ad8f3bde109f53 (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>
-rw-r--r--drivers/md/dm-thin-metadata.c2
-rw-r--r--drivers/md/persistent-data/dm-btree.c9
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
233static bool is_internal_level(struct dm_btree_info *info, struct frame *f)
234{
235 return f->level < (info->levels - 1);
236}
237
233int dm_btree_del(struct dm_btree_info *info, dm_block_t root) 238int 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);