aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c131
1 files changed, 125 insertions, 6 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 19c0dd33b1e8..c0c95cccbb5b 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1512,7 +1512,8 @@ cow_done:
1512 if (ret && slot > 0) 1512 if (ret && slot > 0)
1513 slot -= 1; 1513 slot -= 1;
1514 p->slots[level] = slot; 1514 p->slots[level] = slot;
1515 if (ins_len > 0 && btrfs_header_nritems(b) >= 1515 if ((p->search_for_split || ins_len > 0) &&
1516 btrfs_header_nritems(b) >=
1516 BTRFS_NODEPTRS_PER_BLOCK(root) - 3) { 1517 BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
1517 int sret = split_node(trans, root, p, level); 1518 int sret = split_node(trans, root, p, level);
1518 BUG_ON(sret > 0); 1519 BUG_ON(sret > 0);
@@ -1596,7 +1597,8 @@ cow_done:
1596 goto done; 1597 goto done;
1597 } 1598 }
1598 } 1599 }
1599 unlock_up(p, level, lowest_unlock); 1600 if (!p->search_for_split)
1601 unlock_up(p, level, lowest_unlock);
1600 goto done; 1602 goto done;
1601 } 1603 }
1602 } 1604 }
@@ -2636,11 +2638,11 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
2636 int num_doubles = 0; 2638 int num_doubles = 0;
2637 struct btrfs_disk_key disk_key; 2639 struct btrfs_disk_key disk_key;
2638 2640
2639 if (extend) 2641 if (extend && data_size)
2640 space_needed = data_size; 2642 space_needed = data_size;
2641 2643
2642 /* first try to make some room by pushing left and right */ 2644 /* first try to make some room by pushing left and right */
2643 if (ins_key->type != BTRFS_DIR_ITEM_KEY) { 2645 if (data_size && ins_key->type != BTRFS_DIR_ITEM_KEY) {
2644 wret = push_leaf_right(trans, root, path, data_size, 0); 2646 wret = push_leaf_right(trans, root, path, data_size, 0);
2645 if (wret < 0) { 2647 if (wret < 0) {
2646 return wret; 2648 return wret;
@@ -2721,7 +2723,7 @@ again:
2721 } else { 2723 } else {
2722 if (leaf_space_used(l, 0, mid + 1) + space_needed > 2724 if (leaf_space_used(l, 0, mid + 1) + space_needed >
2723 BTRFS_LEAF_DATA_SIZE(root)) { 2725 BTRFS_LEAF_DATA_SIZE(root)) {
2724 if (!extend && slot == 0) { 2726 if (!extend && data_size && slot == 0) {
2725 btrfs_cpu_key_to_disk(&disk_key, ins_key); 2727 btrfs_cpu_key_to_disk(&disk_key, ins_key);
2726 btrfs_set_header_nritems(right, 0); 2728 btrfs_set_header_nritems(right, 0);
2727 wret = insert_ptr(trans, root, path, 2729 wret = insert_ptr(trans, root, path,
@@ -2742,7 +2744,7 @@ again:
2742 } 2744 }
2743 btrfs_mark_buffer_dirty(right); 2745 btrfs_mark_buffer_dirty(right);
2744 return ret; 2746 return ret;
2745 } else if (extend && slot == 0) { 2747 } else if ((extend || !data_size) && slot == 0) {
2746 mid = 1; 2748 mid = 1;
2747 } else { 2749 } else {
2748 mid = slot; 2750 mid = slot;
@@ -2828,6 +2830,123 @@ again:
2828} 2830}
2829 2831
2830/* 2832/*
2833 * This function splits a single item into two items,
2834 * giving 'new_key' to the new item and splitting the
2835 * old one at split_offset (from the start of the item).
2836 *
2837 * The path may be released by this operation. After
2838 * the split, the path is pointing to the old item. The
2839 * new item is going to be in the same node as the old one.
2840 *
2841 * Note, the item being split must be smaller enough to live alone on
2842 * a tree block with room for one extra struct btrfs_item
2843 *
2844 * This allows us to split the item in place, keeping a lock on the
2845 * leaf the entire time.
2846 */
2847int btrfs_split_item(struct btrfs_trans_handle *trans,
2848 struct btrfs_root *root,
2849 struct btrfs_path *path,
2850 struct btrfs_key *new_key,
2851 unsigned long split_offset)
2852{
2853 u32 item_size;
2854 struct extent_buffer *leaf;
2855 struct btrfs_key orig_key;
2856 struct btrfs_item *item;
2857 struct btrfs_item *new_item;
2858 int ret = 0;
2859 int slot;
2860 u32 nritems;
2861 u32 orig_offset;
2862 struct btrfs_disk_key disk_key;
2863 char *buf;
2864
2865 leaf = path->nodes[0];
2866 btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]);
2867 if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item))
2868 goto split;
2869
2870 item_size = btrfs_item_size_nr(leaf, path->slots[0]);
2871 btrfs_release_path(root, path);
2872
2873 path->search_for_split = 1;
2874 path->keep_locks = 1;
2875
2876 ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1);
2877 path->search_for_split = 0;
2878
2879 /* if our item isn't there or got smaller, return now */
2880 if (ret != 0 || item_size != btrfs_item_size_nr(path->nodes[0],
2881 path->slots[0])) {
2882 path->keep_locks = 0;
2883 return -EAGAIN;
2884 }
2885
2886 ret = split_leaf(trans, root, &orig_key, path, 0, 0);
2887 path->keep_locks = 0;
2888 BUG_ON(ret);
2889
2890 BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
2891 leaf = path->nodes[0];
2892
2893split:
2894 item = btrfs_item_nr(leaf, path->slots[0]);
2895 orig_offset = btrfs_item_offset(leaf, item);
2896 item_size = btrfs_item_size(leaf, item);
2897
2898
2899 buf = kmalloc(item_size, GFP_NOFS);
2900 read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
2901 path->slots[0]), item_size);
2902 slot = path->slots[0] + 1;
2903 leaf = path->nodes[0];
2904
2905 nritems = btrfs_header_nritems(leaf);
2906
2907 if (slot != nritems) {
2908 /* shift the items */
2909 memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
2910 btrfs_item_nr_offset(slot),
2911 (nritems - slot) * sizeof(struct btrfs_item));
2912
2913 }
2914
2915 btrfs_cpu_key_to_disk(&disk_key, new_key);
2916 btrfs_set_item_key(leaf, &disk_key, slot);
2917
2918 new_item = btrfs_item_nr(leaf, slot);
2919
2920 btrfs_set_item_offset(leaf, new_item, orig_offset);
2921 btrfs_set_item_size(leaf, new_item, item_size - split_offset);
2922
2923 btrfs_set_item_offset(leaf, item,
2924 orig_offset + item_size - split_offset);
2925 btrfs_set_item_size(leaf, item, split_offset);
2926
2927 btrfs_set_header_nritems(leaf, nritems + 1);
2928
2929 /* write the data for the start of the original item */
2930 write_extent_buffer(leaf, buf,
2931 btrfs_item_ptr_offset(leaf, path->slots[0]),
2932 split_offset);
2933
2934 /* write the data for the new item */
2935 write_extent_buffer(leaf, buf + split_offset,
2936 btrfs_item_ptr_offset(leaf, slot),
2937 item_size - split_offset);
2938 btrfs_mark_buffer_dirty(leaf);
2939
2940 ret = 0;
2941 if (btrfs_leaf_free_space(root, leaf) < 0) {
2942 btrfs_print_leaf(root, leaf);
2943 BUG();
2944 }
2945 kfree(buf);
2946 return ret;
2947}
2948
2949/*
2831 * make the item pointed to by the path smaller. new_size indicates 2950 * make the item pointed to by the path smaller. new_size indicates
2832 * how small to make it, and from_end tells us if we just chop bytes 2951 * how small to make it, and from_end tells us if we just chop bytes
2833 * off the end of the item or if we shift the item to chop bytes off 2952 * off the end of the item or if we shift the item to chop bytes off