diff options
author | Joe Thornber <ejt@redhat.com> | 2012-12-21 20:23:32 +0000 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2012-12-21 20:23:32 +0000 |
commit | e3cbf94513c21516fbb44561857b155d1c599625 (patch) | |
tree | fbcfb3427b34d8469e404d5b8f63c4dc9c0f98c8 /drivers/md/persistent-data/dm-btree.c | |
parent | 563af186df08002d2600c4e718ad8f3bde109f53 (diff) | |
download | linux-stable-e3cbf94513c21516fbb44561857b155d1c599625.tar.gz linux-stable-e3cbf94513c21516fbb44561857b155d1c599625.tar.bz2 linux-stable-e3cbf94513c21516fbb44561857b155d1c599625.zip |
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/md/persistent-data/dm-btree.c')
-rw-r--r-- | drivers/md/persistent-data/dm-btree.c | 9 |
1 files changed, 7 insertions, 2 deletions
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) dm_tm_unlock(s->tm, f->b); } +static bool is_internal_level(struct dm_btree_info *info, struct frame *f) +{ + return f->level < (info->levels - 1); +} + int dm_btree_del(struct dm_btree_info *info, dm_block_t root) { int r; @@ -241,7 +246,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) s->tm = info->tm; s->top = -1; - r = push_frame(s, root, 1); + r = push_frame(s, root, 0); if (r) goto out; @@ -267,7 +272,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) if (r) goto out; - } else if (f->level != (info->levels - 1)) { + } else if (is_internal_level(info, f)) { b = value64(f->n, f->current_child); f->current_child++; r = push_frame(s, b, f->level + 1); |