aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c198
-rw-r--r--fs/btrfs/ctree.h4
2 files changed, 143 insertions, 59 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index ec96f3a6d536..9d4ba3470c17 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -37,6 +37,11 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
37 struct extent_buffer *src_buf); 37 struct extent_buffer *src_buf);
38static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 38static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
39 struct btrfs_path *path, int level, int slot); 39 struct btrfs_path *path, int level, int slot);
40static int setup_items_for_insert(struct btrfs_trans_handle *trans,
41 struct btrfs_root *root, struct btrfs_path *path,
42 struct btrfs_key *cpu_key, u32 *data_size,
43 u32 total_data, u32 total_size, int nr);
44
40 45
41struct btrfs_path *btrfs_alloc_path(void) 46struct btrfs_path *btrfs_alloc_path(void)
42{ 47{
@@ -2997,75 +3002,85 @@ again:
2997 return ret; 3002 return ret;
2998} 3003}
2999 3004
3000/* 3005static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
3001 * This function splits a single item into two items, 3006 struct btrfs_root *root,
3002 * giving 'new_key' to the new item and splitting the 3007 struct btrfs_path *path, int ins_len)
3003 * old one at split_offset (from the start of the item).
3004 *
3005 * The path may be released by this operation. After
3006 * the split, the path is pointing to the old item. The
3007 * new item is going to be in the same node as the old one.
3008 *
3009 * Note, the item being split must be smaller enough to live alone on
3010 * a tree block with room for one extra struct btrfs_item
3011 *
3012 * This allows us to split the item in place, keeping a lock on the
3013 * leaf the entire time.
3014 */
3015int btrfs_split_item(struct btrfs_trans_handle *trans,
3016 struct btrfs_root *root,
3017 struct btrfs_path *path,
3018 struct btrfs_key *new_key,
3019 unsigned long split_offset)
3020{ 3008{
3021 u32 item_size; 3009 struct btrfs_key key;
3022 struct extent_buffer *leaf; 3010 struct extent_buffer *leaf;
3023 struct btrfs_key orig_key; 3011 struct btrfs_file_extent_item *fi;
3024 struct btrfs_item *item; 3012 u64 extent_len = 0;
3025 struct btrfs_item *new_item; 3013 u32 item_size;
3026 int ret = 0; 3014 int ret;
3027 int slot;
3028 u32 nritems;
3029 u32 orig_offset;
3030 struct btrfs_disk_key disk_key;
3031 char *buf;
3032 3015
3033 leaf = path->nodes[0]; 3016 leaf = path->nodes[0];
3034 btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]); 3017 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
3035 if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item)) 3018
3036 goto split; 3019 BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY &&
3020 key.type != BTRFS_EXTENT_CSUM_KEY);
3021
3022 if (btrfs_leaf_free_space(root, leaf) >= ins_len)
3023 return 0;
3037 3024
3038 item_size = btrfs_item_size_nr(leaf, path->slots[0]); 3025 item_size = btrfs_item_size_nr(leaf, path->slots[0]);
3026 if (key.type == BTRFS_EXTENT_DATA_KEY) {
3027 fi = btrfs_item_ptr(leaf, path->slots[0],
3028 struct btrfs_file_extent_item);
3029 extent_len = btrfs_file_extent_num_bytes(leaf, fi);
3030 }
3039 btrfs_release_path(root, path); 3031 btrfs_release_path(root, path);
3040 3032
3041 path->search_for_split = 1;
3042 path->keep_locks = 1; 3033 path->keep_locks = 1;
3043 3034 path->search_for_split = 1;
3044 ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1); 3035 ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
3045 path->search_for_split = 0; 3036 path->search_for_split = 0;
3037 if (ret < 0)
3038 goto err;
3046 3039
3040 ret = -EAGAIN;
3041 leaf = path->nodes[0];
3047 /* if our item isn't there or got smaller, return now */ 3042 /* if our item isn't there or got smaller, return now */
3048 if (ret != 0 || item_size != btrfs_item_size_nr(path->nodes[0], 3043 if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0]))
3049 path->slots[0])) { 3044 goto err;
3050 path->keep_locks = 0; 3045
3051 return -EAGAIN; 3046 if (key.type == BTRFS_EXTENT_DATA_KEY) {
3047 fi = btrfs_item_ptr(leaf, path->slots[0],
3048 struct btrfs_file_extent_item);
3049 if (extent_len != btrfs_file_extent_num_bytes(leaf, fi))
3050 goto err;
3052 } 3051 }
3053 3052
3054 btrfs_set_path_blocking(path); 3053 btrfs_set_path_blocking(path);
3055 ret = split_leaf(trans, root, &orig_key, path, 3054 ret = split_leaf(trans, root, &key, path, ins_len, 1);
3056 sizeof(struct btrfs_item), 1);
3057 path->keep_locks = 0;
3058 BUG_ON(ret); 3055 BUG_ON(ret);
3059 3056
3057 path->keep_locks = 0;
3060 btrfs_unlock_up_safe(path, 1); 3058 btrfs_unlock_up_safe(path, 1);
3059 return 0;
3060err:
3061 path->keep_locks = 0;
3062 return ret;
3063}
3064
3065static noinline int split_item(struct btrfs_trans_handle *trans,
3066 struct btrfs_root *root,
3067 struct btrfs_path *path,
3068 struct btrfs_key *new_key,
3069 unsigned long split_offset)
3070{
3071 struct extent_buffer *leaf;
3072 struct btrfs_item *item;
3073 struct btrfs_item *new_item;
3074 int slot;
3075 char *buf;
3076 u32 nritems;
3077 u32 item_size;
3078 u32 orig_offset;
3079 struct btrfs_disk_key disk_key;
3080
3061 leaf = path->nodes[0]; 3081 leaf = path->nodes[0];
3062 BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item)); 3082 BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
3063 3083
3064split:
3065 /*
3066 * make sure any changes to the path from split_leaf leave it
3067 * in a blocking state
3068 */
3069 btrfs_set_path_blocking(path); 3084 btrfs_set_path_blocking(path);
3070 3085
3071 item = btrfs_item_nr(leaf, path->slots[0]); 3086 item = btrfs_item_nr(leaf, path->slots[0]);
@@ -3073,19 +3088,19 @@ split:
3073 item_size = btrfs_item_size(leaf, item); 3088 item_size = btrfs_item_size(leaf, item);
3074 3089
3075 buf = kmalloc(item_size, GFP_NOFS); 3090 buf = kmalloc(item_size, GFP_NOFS);
3091 if (!buf)
3092 return -ENOMEM;
3093
3076 read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, 3094 read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
3077 path->slots[0]), item_size); 3095 path->slots[0]), item_size);
3078 slot = path->slots[0] + 1;
3079 leaf = path->nodes[0];
3080 3096
3097 slot = path->slots[0] + 1;
3081 nritems = btrfs_header_nritems(leaf); 3098 nritems = btrfs_header_nritems(leaf);
3082
3083 if (slot != nritems) { 3099 if (slot != nritems) {
3084 /* shift the items */ 3100 /* shift the items */
3085 memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1), 3101 memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
3086 btrfs_item_nr_offset(slot), 3102 btrfs_item_nr_offset(slot),
3087 (nritems - slot) * sizeof(struct btrfs_item)); 3103 (nritems - slot) * sizeof(struct btrfs_item));
3088
3089 } 3104 }
3090 3105
3091 btrfs_cpu_key_to_disk(&disk_key, new_key); 3106 btrfs_cpu_key_to_disk(&disk_key, new_key);
@@ -3113,16 +3128,81 @@ split:
3113 item_size - split_offset); 3128 item_size - split_offset);
3114 btrfs_mark_buffer_dirty(leaf); 3129 btrfs_mark_buffer_dirty(leaf);
3115 3130
3116 ret = 0; 3131 BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
3117 if (btrfs_leaf_free_space(root, leaf) < 0) {
3118 btrfs_print_leaf(root, leaf);
3119 BUG();
3120 }
3121 kfree(buf); 3132 kfree(buf);
3133 return 0;
3134}
3135
3136/*
3137 * This function splits a single item into two items,
3138 * giving 'new_key' to the new item and splitting the
3139 * old one at split_offset (from the start of the item).
3140 *
3141 * The path may be released by this operation. After
3142 * the split, the path is pointing to the old item. The
3143 * new item is going to be in the same node as the old one.
3144 *
3145 * Note, the item being split must be smaller enough to live alone on
3146 * a tree block with room for one extra struct btrfs_item
3147 *
3148 * This allows us to split the item in place, keeping a lock on the
3149 * leaf the entire time.
3150 */
3151int btrfs_split_item(struct btrfs_trans_handle *trans,
3152 struct btrfs_root *root,
3153 struct btrfs_path *path,
3154 struct btrfs_key *new_key,
3155 unsigned long split_offset)
3156{
3157 int ret;
3158 ret = setup_leaf_for_split(trans, root, path,
3159 sizeof(struct btrfs_item));
3160 if (ret)
3161 return ret;
3162
3163 ret = split_item(trans, root, path, new_key, split_offset);
3122 return ret; 3164 return ret;
3123} 3165}
3124 3166
3125/* 3167/*
3168 * This function duplicate a item, giving 'new_key' to the new item.
3169 * It guarantees both items live in the same tree leaf and the new item
3170 * is contiguous with the original item.
3171 *
3172 * This allows us to split file extent in place, keeping a lock on the
3173 * leaf the entire time.
3174 */
3175int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
3176 struct btrfs_root *root,
3177 struct btrfs_path *path,
3178 struct btrfs_key *new_key)
3179{
3180 struct extent_buffer *leaf;
3181 int ret;
3182 u32 item_size;
3183
3184 leaf = path->nodes[0];
3185 item_size = btrfs_item_size_nr(leaf, path->slots[0]);
3186 ret = setup_leaf_for_split(trans, root, path,
3187 item_size + sizeof(struct btrfs_item));
3188 if (ret)
3189 return ret;
3190
3191 path->slots[0]++;
3192 ret = setup_items_for_insert(trans, root, path, new_key, &item_size,
3193 item_size, item_size +
3194 sizeof(struct btrfs_item), 1);
3195 BUG_ON(ret);
3196
3197 leaf = path->nodes[0];
3198 memcpy_extent_buffer(leaf,
3199 btrfs_item_ptr_offset(leaf, path->slots[0]),
3200 btrfs_item_ptr_offset(leaf, path->slots[0] - 1),
3201 item_size);
3202 return 0;
3203}
3204
3205/*
3126 * make the item pointed to by the path smaller. new_size indicates 3206 * make the item pointed to by the path smaller. new_size indicates
3127 * how small to make it, and from_end tells us if we just chop bytes 3207 * how small to make it, and from_end tells us if we just chop bytes
3128 * off the end of the item or if we shift the item to chop bytes off 3208 * off the end of the item or if we shift the item to chop bytes off
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 444b3e9b92a4..e3b58001162d 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2089,6 +2089,10 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
2089 struct btrfs_path *path, 2089 struct btrfs_path *path,
2090 struct btrfs_key *new_key, 2090 struct btrfs_key *new_key,
2091 unsigned long split_offset); 2091 unsigned long split_offset);
2092int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
2093 struct btrfs_root *root,
2094 struct btrfs_path *path,
2095 struct btrfs_key *new_key);
2092int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root 2096int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
2093 *root, struct btrfs_key *key, struct btrfs_path *p, int 2097 *root, struct btrfs_key *key, struct btrfs_path *p, int
2094 ins_len, int cow); 2098 ins_len, int cow);