| From b0dc3c8bc157c60b1d470163882be8c13e1950af Mon Sep 17 00:00:00 2001 |
| From: Joe Thornber <ejt@redhat.com> |
| Date: Wed, 12 Aug 2015 15:12:09 +0100 |
| Subject: dm btree: add ref counting ops for the leaves of top level btrees |
| |
| commit b0dc3c8bc157c60b1d470163882be8c13e1950af upstream. |
| |
| When using nested btrees, the top leaves of the top levels contain |
| block addresses for the root of the next tree down. If we shadow a |
| shared leaf node the leaf values (sub tree roots) should be incremented |
| accordingly. |
| |
| This is only an issue if there is metadata sharing in the top levels. |
| Which only occurs if metadata snapshots are being used (as is possible |
| with dm-thinp). And could result in a block from the thinp metadata |
| snap being reused early, thus corrupting the thinp metadata snap. |
| |
| Signed-off-by: Joe Thornber <ejt@redhat.com> |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| [lizf: Backported to 3.4: |
| - drop const |
| - drop changes to remove_one()] |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/md/persistent-data/dm-btree-internal.h | 6 ++++ |
| drivers/md/persistent-data/dm-btree-remove.c | 12 ++------ |
| drivers/md/persistent-data/dm-btree-spine.c | 37 +++++++++++++++++++++++++ |
| drivers/md/persistent-data/dm-btree.c | 7 ---- |
| 4 files changed, 47 insertions(+), 15 deletions(-) |
| |
| --- a/drivers/md/persistent-data/dm-btree-internal.h |
| +++ b/drivers/md/persistent-data/dm-btree-internal.h |
| @@ -131,4 +131,10 @@ int lower_bound(struct btree_node *n, ui |
| |
| extern struct dm_block_validator btree_node_validator; |
| |
| +/* |
| + * Value type for upper levels of multi-level btrees. |
| + */ |
| +extern void init_le64_type(struct dm_transaction_manager *tm, |
| + struct dm_btree_value_type *vt); |
| + |
| #endif /* DM_BTREE_INTERNAL_H */ |
| --- a/drivers/md/persistent-data/dm-btree-remove.c |
| +++ b/drivers/md/persistent-data/dm-btree-remove.c |
| @@ -544,14 +544,6 @@ static int remove_raw(struct shadow_spin |
| return r; |
| } |
| |
| -static struct dm_btree_value_type le64_type = { |
| - .context = NULL, |
| - .size = sizeof(__le64), |
| - .inc = NULL, |
| - .dec = NULL, |
| - .equal = NULL |
| -}; |
| - |
| int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, |
| uint64_t *keys, dm_block_t *new_root) |
| { |
| @@ -559,12 +551,14 @@ int dm_btree_remove(struct dm_btree_info |
| int index = 0, r = 0; |
| struct shadow_spine spine; |
| struct btree_node *n; |
| + struct dm_btree_value_type le64_vt; |
| |
| + init_le64_type(info->tm, &le64_vt); |
| init_shadow_spine(&spine, info); |
| for (level = 0; level < info->levels; level++) { |
| r = remove_raw(&spine, info, |
| (level == last_level ? |
| - &info->value_type : &le64_type), |
| + &info->value_type : &le64_vt), |
| root, keys[level], (unsigned *)&index); |
| if (r < 0) |
| break; |
| --- a/drivers/md/persistent-data/dm-btree-spine.c |
| +++ b/drivers/md/persistent-data/dm-btree-spine.c |
| @@ -242,3 +242,40 @@ int shadow_root(struct shadow_spine *s) |
| { |
| return s->root; |
| } |
| + |
| +static void le64_inc(void *context, void *value_le) |
| +{ |
| + struct dm_transaction_manager *tm = context; |
| + __le64 v_le; |
| + |
| + memcpy(&v_le, value_le, sizeof(v_le)); |
| + dm_tm_inc(tm, le64_to_cpu(v_le)); |
| +} |
| + |
| +static void le64_dec(void *context, void *value_le) |
| +{ |
| + struct dm_transaction_manager *tm = context; |
| + __le64 v_le; |
| + |
| + memcpy(&v_le, value_le, sizeof(v_le)); |
| + dm_tm_dec(tm, le64_to_cpu(v_le)); |
| +} |
| + |
| +static int le64_equal(void *context, void *value1_le, void *value2_le) |
| +{ |
| + __le64 v1_le, v2_le; |
| + |
| + memcpy(&v1_le, value1_le, sizeof(v1_le)); |
| + memcpy(&v2_le, value2_le, sizeof(v2_le)); |
| + return v1_le == v2_le; |
| +} |
| + |
| +void init_le64_type(struct dm_transaction_manager *tm, |
| + struct dm_btree_value_type *vt) |
| +{ |
| + vt->context = tm; |
| + vt->size = sizeof(__le64); |
| + vt->inc = le64_inc; |
| + vt->dec = le64_dec; |
| + vt->equal = le64_equal; |
| +} |
| --- a/drivers/md/persistent-data/dm-btree.c |
| +++ b/drivers/md/persistent-data/dm-btree.c |
| @@ -646,12 +646,7 @@ static int insert(struct dm_btree_info * |
| struct btree_node *n; |
| struct dm_btree_value_type le64_type; |
| |
| - le64_type.context = NULL; |
| - le64_type.size = sizeof(__le64); |
| - le64_type.inc = NULL; |
| - le64_type.dec = NULL; |
| - le64_type.equal = NULL; |
| - |
| + init_le64_type(info->tm, &le64_type); |
| init_shadow_spine(&spine, info); |
| |
| for (level = 0; level < (info->levels - 1); level++) { |