Skip to content

Commit 12161e0

Browse files
Mikulas Patockagregkh
authored andcommitted
dm-thin: fix metadata refcount underflow
commit 09a65ad upstream. There's a bug in dm-thin in the function rebalance_children. If the internal btree node has one entry, the code tries to copy all btree entries from the node's child to the node itself and then decrement the child's reference count. If the child node is shared (it has reference count > 1), we won't free it, so there would be two pointers to each of the grandchildren nodes. But the reference counts of the grandchildren is not increased, thus the reference count doesn't match the number of pointers that point to the grandchildren. This results in "device mapper: space map common: unable to decrement block" errors. Fix this bug by incrementing reference counts on the grandchildren if the btree node is shared. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Fixes: 3241b1d ("dm: add persistent data library") Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c2670ec commit 12161e0

1 file changed

Lines changed: 8 additions & 0 deletions

File tree

drivers/md/persistent-data/dm-btree-remove.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,12 +490,20 @@ static int rebalance_children(struct shadow_spine *s,
490490

491491
if (le32_to_cpu(n->header.nr_entries) == 1) {
492492
struct dm_block *child;
493+
int is_shared;
493494
dm_block_t b = value64(n, 0);
494495

496+
r = dm_tm_block_is_shared(info->tm, b, &is_shared);
497+
if (r)
498+
return r;
499+
495500
r = dm_tm_read_lock(info->tm, b, &btree_node_validator, &child);
496501
if (r)
497502
return r;
498503

504+
if (is_shared)
505+
inc_children(info->tm, dm_block_data(child), vt);
506+
499507
memcpy(n, dm_block_data(child),
500508
dm_bm_block_size(dm_tm_get_bm(info->tm)));
501509

0 commit comments

Comments
 (0)