diff options
Diffstat (limited to 'drivers/md/persistent-data/dm-btree.c')
-rw-r--r-- | drivers/md/persistent-data/dm-btree.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index 0283d3c2b16f..b0ad1de7aa37 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -510,6 +510,7 @@ static void copy_entries(struct btree_node *dest, unsigned int dest_offset, unsigned int count) { size_t value_size = le32_to_cpu(dest->header.value_size); + memcpy(dest->keys + dest_offset, src->keys + src_offset, count * sizeof(uint64_t)); memcpy(value_ptr(dest, dest_offset), value_ptr(src, src_offset), count * value_size); } @@ -523,6 +524,7 @@ static void move_entries(struct btree_node *dest, unsigned int dest_offset, unsigned int count) { size_t value_size = le32_to_cpu(dest->header.value_size); + memmove(dest->keys + dest_offset, src->keys + src_offset, count * sizeof(uint64_t)); memmove(value_ptr(dest, dest_offset), value_ptr(src, src_offset), count * value_size); } @@ -559,10 +561,12 @@ static void redistribute2(struct btree_node *left, struct btree_node *right) if (nr_left < target_left) { unsigned int delta = target_left - nr_left; + copy_entries(left, nr_left, right, 0, delta); shift_down(right, delta); } else if (nr_left > target_left) { unsigned int delta = nr_left - target_left; + if (nr_right) shift_up(right, delta); copy_entries(right, 0, left, target_left, delta); @@ -593,18 +597,21 @@ static void redistribute3(struct btree_node *left, struct btree_node *center, if (nr_left < target_left) { unsigned int left_short = target_left - nr_left; + copy_entries(left, nr_left, right, 0, left_short); copy_entries(center, 0, right, left_short, target_center); shift_down(right, nr_right - target_right); } else if (nr_left < (target_left + target_center)) { unsigned int left_to_center = nr_left - target_left; + copy_entries(center, 0, left, target_left, left_to_center); copy_entries(center, left_to_center, right, 0, target_center - left_to_center); shift_down(right, nr_right - target_right); } else { unsigned int right_short = target_right - nr_right; + shift_up(right, right_short); copy_entries(right, 0, left, nr_left - right_short, right_short); copy_entries(center, 0, left, target_left, nr_left - target_left); @@ -1004,6 +1011,7 @@ static int rebalance_or_split(struct shadow_spine *s, struct dm_btree_value_type /* Should we move entries to the left sibling? */ if (parent_index > 0) { dm_block_t left_b = value64(parent, parent_index - 1); + r = dm_tm_block_is_shared(s->info->tm, left_b, &left_shared); if (r) return r; @@ -1021,6 +1029,7 @@ static int rebalance_or_split(struct shadow_spine *s, struct dm_btree_value_type /* Should we move entries to the right sibling? */ if (parent_index < (nr_parent - 1)) { dm_block_t right_b = value64(parent, parent_index + 1); + r = dm_tm_block_is_shared(s->info->tm, right_b, &right_shared); if (r) return r; @@ -1588,6 +1597,7 @@ EXPORT_SYMBOL_GPL(dm_btree_cursor_end); int dm_btree_cursor_next(struct dm_btree_cursor *c) { int r = inc_or_backtrack(c); + if (!r) { r = find_leaf(c); if (r) |