| From ed9571f0cf1fe09d3506302610f3ccdfa1d22c4a Mon Sep 17 00:00:00 2001 |
| From: Joe Thornber <ejt@redhat.com> |
| Date: Fri, 13 Dec 2013 14:55:55 +0000 |
| Subject: dm array: fix a reference counting bug in shadow_ablock |
| |
| From: Joe Thornber <ejt@redhat.com> |
| |
| commit ed9571f0cf1fe09d3506302610f3ccdfa1d22c4a upstream. |
| |
| An old array block could have its reference count decremented below |
| zero when it is being replaced in the btree by a new array block. |
| |
| The fix is to increment the old ablock's reference count just before |
| inserting a new ablock into the btree. |
| |
| Signed-off-by: Joe Thornber <ejt@redhat.com> |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/md/persistent-data/dm-array.c | 10 +++++++++- |
| 1 file changed, 9 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/md/persistent-data/dm-array.c |
| +++ b/drivers/md/persistent-data/dm-array.c |
| @@ -317,8 +317,16 @@ static int shadow_ablock(struct dm_array |
| * The shadow op will often be a noop. Only insert if it really |
| * copied data. |
| */ |
| - if (dm_block_location(*block) != b) |
| + if (dm_block_location(*block) != b) { |
| + /* |
| + * dm_tm_shadow_block will have already decremented the old |
| + * block, but it is still referenced by the btree. We |
| + * increment to stop the insert decrementing it below zero |
| + * when overwriting the old value. |
| + */ |
| + dm_tm_inc(info->btree_info.tm, b); |
| r = insert_ablock(info, index, *block, root); |
| + } |
| |
| return r; |
| } |