Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm btree: add dm_btree_remove_leaves()

Removes a range of leaf values from the tree.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

authored by

Joe Thornber and committed by
Mike Snitzer
4ec331c3 0f24b79b

+136
+127
drivers/md/persistent-data/dm-btree-remove.c
··· 590 590 return r; 591 591 } 592 592 EXPORT_SYMBOL_GPL(dm_btree_remove); 593 + 594 + /*----------------------------------------------------------------*/ 595 + 596 + static int remove_nearest(struct shadow_spine *s, struct dm_btree_info *info, 597 + struct dm_btree_value_type *vt, dm_block_t root, 598 + uint64_t key, int *index) 599 + { 600 + int i = *index, r; 601 + struct btree_node *n; 602 + 603 + for (;;) { 604 + r = shadow_step(s, root, vt); 605 + if (r < 0) 606 + break; 607 + 608 + /* 609 + * We have to patch up the parent node, ugly, but I don't 610 + * see a way to do this automatically as part of the spine 611 + * op. 612 + */ 613 + if (shadow_has_parent(s)) { 614 + __le64 location = cpu_to_le64(dm_block_location(shadow_current(s))); 615 + memcpy(value_ptr(dm_block_data(shadow_parent(s)), i), 616 + &location, sizeof(__le64)); 617 + } 618 + 619 + n = dm_block_data(shadow_current(s)); 620 + 621 + if (le32_to_cpu(n->header.flags) & LEAF_NODE) { 622 + *index = lower_bound(n, key); 623 + return 0; 624 + } 625 + 626 + r = rebalance_children(s, info, vt, key); 627 + if (r) 628 + break; 629 + 630 + n = dm_block_data(shadow_current(s)); 631 + if (le32_to_cpu(n->header.flags) & LEAF_NODE) { 632 + *index = lower_bound(n, key); 633 + return 0; 634 + } 635 + 636 + i = lower_bound(n, key); 637 + 638 + /* 639 + * We know the key is present, or else 640 + * rebalance_children would have returned 641 + * -ENODATA 642 + */ 643 + root = value64(n, i); 644 + } 645 + 646 + return r; 647 + } 648 + 649 + static int remove_one(struct dm_btree_info *info, dm_block_t root, 650 + uint64_t *keys, uint64_t end_key, 651 + dm_block_t *new_root, unsigned *nr_removed) 652 + { 653 + unsigned level, last_level = info->levels - 1; 654 + int index = 0, r = 0; 655 + struct shadow_spine spine; 656 + struct btree_node *n; 657 + uint64_t k; 658 + 659 + init_shadow_spine(&spine, info); 660 + for (level = 0; level < last_level; level++) { 661 + r = remove_raw(&spine, info, &le64_type, 662 + root, keys[level], (unsigned *) &index); 663 + if (r < 0) 664 + goto out; 665 + 666 + n = dm_block_data(shadow_current(&spine)); 667 + root = value64(n, index); 668 + } 669 + 670 + r = remove_nearest(&spine, info, &info->value_type, 671 + root, keys[last_level], &index); 672 + if (r < 0) 673 + goto out; 674 + 675 + n = dm_block_data(shadow_current(&spine)); 676 + 677 + if (index < 0) 678 + index = 0; 679 + 680 + if (index >= le32_to_cpu(n->header.nr_entries)) { 681 + r = -ENODATA; 682 + goto out; 683 + } 684 + 685 + k = le64_to_cpu(n->keys[index]); 686 + if (k >= keys[last_level] && k < end_key) { 687 + if (info->value_type.dec) 688 + info->value_type.dec(info->value_type.context, 689 + value_ptr(n, index)); 690 + 691 + delete_at(n, index); 692 + 693 + } else 694 + r = -ENODATA; 695 + 696 + out: 697 + *new_root = shadow_root(&spine); 698 + exit_shadow_spine(&spine); 699 + 700 + return r; 701 + } 702 + 703 + int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root, 704 + uint64_t *first_key, uint64_t end_key, 705 + dm_block_t *new_root, unsigned *nr_removed) 706 + { 707 + int r; 708 + 709 + *nr_removed = 0; 710 + do { 711 + r = remove_one(info, root, first_key, end_key, &root, nr_removed); 712 + if (!r) 713 + (*nr_removed)++; 714 + } while (!r); 715 + 716 + *new_root = root; 717 + return r == -ENODATA ? 0 : r; 718 + } 719 + EXPORT_SYMBOL_GPL(dm_btree_remove_leaves);
+9
drivers/md/persistent-data/dm-btree.h
··· 135 135 uint64_t *keys, dm_block_t *new_root); 136 136 137 137 /* 138 + * Removes values between 'keys' and keys2, where keys2 is keys with the 139 + * final key replaced with 'end_key'. 'end_key' is the one-past-the-end 140 + * value. 'keys' may be altered. 141 + */ 142 + int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root, 143 + uint64_t *keys, uint64_t end_key, 144 + dm_block_t *new_root, unsigned *nr_removed); 145 + 146 + /* 138 147 * Returns < 0 on failure. Otherwise the number of key entries that have 139 148 * been filled out. Remember trees can have zero entries, and as such have 140 149 * no lowest key.