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

btrfs: add helpers for manipulating leaf items and data

We have some gnarly memmove and copy_extent_buffer calls for leaf
manipulation. This is because our item offsets aren't absolute, they're
based on 0 being where the items start in the leaf, which is after the
btrfs_header. This means any manipulation of the data requires adding
sizeof(struct btrfs_header) to the offsets we pull from the items.
Moving the items themselves is easier as the helpers are absolute
offsets, however we of course have to call the helpers to get the
offsets for the item numbers. This makes for
copy_extent_buffer/memmove_extent_buffer calls that are kind of hard to
reason about what's happening.

Fix this by pushing this logic into helpers. For data we'll only use
the item provided offsets, and the helpers will use the
BTRFS_LEAF_DATA_OFFSET addition for the offsets. Additionally for the
item manipulation simply pass in the item numbers, and then the helpers
will call the offset helper to get the actual offset into the leaf.

The diffstat makes this look like more code, but that's simply because I
added comments for the helpers, it's net negative for the amount of
code, and is easier to reason.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>

authored by

Josef Bacik and committed by
David Sterba
637e3b48 e23efd8e

+115 -66
+115 -66
fs/btrfs/ctree.c
··· 65 65 return btrfs_item_offset(leaf, nr - 1); 66 66 } 67 67 68 + /* 69 + * Move data in a @leaf (using memmove, safe for overlapping ranges). 70 + * 71 + * @leaf: leaf that we're doing a memmove on 72 + * @dst_offset: item data offset we're moving to 73 + * @src_offset: item data offset were' moving from 74 + * @len: length of the data we're moving 75 + * 76 + * Wrapper around memmove_extent_buffer() that takes into account the header on 77 + * the leaf. The btrfs_item offset's start directly after the header, so we 78 + * have to adjust any offsets to account for the header in the leaf. This 79 + * handles that math to simplify the callers. 80 + */ 81 + static inline void memmove_leaf_data(const struct extent_buffer *leaf, 82 + unsigned long dst_offset, 83 + unsigned long src_offset, 84 + unsigned long len) 85 + { 86 + memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET + dst_offset, 87 + BTRFS_LEAF_DATA_OFFSET + src_offset, len); 88 + } 89 + 90 + /* 91 + * Copy item data from @src into @dst at the given @offset. 92 + * 93 + * @dst: destination leaf that we're copying into 94 + * @src: source leaf that we're copying from 95 + * @dst_offset: item data offset we're copying to 96 + * @src_offset: item data offset were' copying from 97 + * @len: length of the data we're copying 98 + * 99 + * Wrapper around copy_extent_buffer() that takes into account the header on 100 + * the leaf. The btrfs_item offset's start directly after the header, so we 101 + * have to adjust any offsets to account for the header in the leaf. This 102 + * handles that math to simplify the callers. 103 + */ 104 + static inline void copy_leaf_data(const struct extent_buffer *dst, 105 + const struct extent_buffer *src, 106 + unsigned long dst_offset, 107 + unsigned long src_offset, unsigned long len) 108 + { 109 + copy_extent_buffer(dst, src, BTRFS_LEAF_DATA_OFFSET + dst_offset, 110 + BTRFS_LEAF_DATA_OFFSET + src_offset, len); 111 + } 112 + 113 + /* 114 + * Move items in a @leaf (using memmove). 115 + * 116 + * @dst: destination leaf for the items 117 + * @dst_item: the item nr we're copying into 118 + * @src_item: the item nr we're copying from 119 + * @nr_items: the number of items to copy 120 + * 121 + * Wrapper around memmove_extent_buffer() that does the math to get the 122 + * appropriate offsets into the leaf from the item numbers. 123 + */ 124 + static inline void memmove_leaf_items(const struct extent_buffer *leaf, 125 + int dst_item, int src_item, int nr_items) 126 + { 127 + memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, dst_item), 128 + btrfs_item_nr_offset(leaf, src_item), 129 + nr_items * sizeof(struct btrfs_item)); 130 + } 131 + 132 + /* 133 + * Copy items from @src into @dst at the given @offset. 134 + * 135 + * @dst: destination leaf for the items 136 + * @src: source leaf for the items 137 + * @dst_item: the item nr we're copying into 138 + * @src_item: the item nr we're copying from 139 + * @nr_items: the number of items to copy 140 + * 141 + * Wrapper around copy_extent_buffer() that does the math to get the 142 + * appropriate offsets into the leaf from the item numbers. 143 + */ 144 + static inline void copy_leaf_items(const struct extent_buffer *dst, 145 + const struct extent_buffer *src, 146 + int dst_item, int src_item, int nr_items) 147 + { 148 + copy_extent_buffer(dst, src, btrfs_item_nr_offset(dst, dst_item), 149 + btrfs_item_nr_offset(src, src_item), 150 + nr_items * sizeof(struct btrfs_item)); 151 + } 152 + 68 153 int btrfs_super_csum_size(const struct btrfs_super_block *s) 69 154 { 70 155 u16 t = btrfs_super_csum_type(s); ··· 3107 3022 3108 3023 /* make room in the right data area */ 3109 3024 data_end = leaf_data_end(right); 3110 - memmove_extent_buffer(right, 3111 - BTRFS_LEAF_DATA_OFFSET + data_end - push_space, 3112 - BTRFS_LEAF_DATA_OFFSET + data_end, 3113 - BTRFS_LEAF_DATA_SIZE(fs_info) - data_end); 3025 + memmove_leaf_data(right, data_end - push_space, data_end, 3026 + BTRFS_LEAF_DATA_SIZE(fs_info) - data_end); 3114 3027 3115 3028 /* copy from the left data area */ 3116 - copy_extent_buffer(right, left, BTRFS_LEAF_DATA_OFFSET + 3117 - BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, 3118 - BTRFS_LEAF_DATA_OFFSET + leaf_data_end(left), 3119 - push_space); 3029 + copy_leaf_data(right, left, BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, 3030 + leaf_data_end(left), push_space); 3120 3031 3121 - memmove_extent_buffer(right, btrfs_item_nr_offset(right, push_items), 3122 - btrfs_item_nr_offset(right, 0), 3123 - right_nritems * sizeof(struct btrfs_item)); 3032 + memmove_leaf_items(right, push_items, 0, right_nritems); 3124 3033 3125 3034 /* copy the items from left to right */ 3126 - copy_extent_buffer(right, left, btrfs_item_nr_offset(right, 0), 3127 - btrfs_item_nr_offset(left, left_nritems - push_items), 3128 - push_items * sizeof(struct btrfs_item)); 3035 + copy_leaf_items(right, left, 0, left_nritems - push_items, push_items); 3129 3036 3130 3037 /* update the item pointers */ 3131 3038 btrfs_init_map_token(&token, right); ··· 3309 3232 WARN_ON(!empty && push_items == btrfs_header_nritems(right)); 3310 3233 3311 3234 /* push data from right to left */ 3312 - copy_extent_buffer(left, right, 3313 - btrfs_item_nr_offset(left, btrfs_header_nritems(left)), 3314 - btrfs_item_nr_offset(right, 0), 3315 - push_items * sizeof(struct btrfs_item)); 3235 + copy_leaf_items(left, right, btrfs_header_nritems(left), 0, push_items); 3316 3236 3317 3237 push_space = BTRFS_LEAF_DATA_SIZE(fs_info) - 3318 3238 btrfs_item_offset(right, push_items - 1); 3319 3239 3320 - copy_extent_buffer(left, right, BTRFS_LEAF_DATA_OFFSET + 3321 - leaf_data_end(left) - push_space, 3322 - BTRFS_LEAF_DATA_OFFSET + 3323 - btrfs_item_offset(right, push_items - 1), 3324 - push_space); 3240 + copy_leaf_data(left, right, leaf_data_end(left) - push_space, 3241 + btrfs_item_offset(right, push_items - 1), push_space); 3325 3242 old_left_nritems = btrfs_header_nritems(left); 3326 3243 BUG_ON(old_left_nritems <= 0); 3327 3244 ··· 3338 3267 if (push_items < right_nritems) { 3339 3268 push_space = btrfs_item_offset(right, push_items - 1) - 3340 3269 leaf_data_end(right); 3341 - memmove_extent_buffer(right, BTRFS_LEAF_DATA_OFFSET + 3342 - BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, 3343 - BTRFS_LEAF_DATA_OFFSET + 3344 - leaf_data_end(right), push_space); 3270 + memmove_leaf_data(right, 3271 + BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, 3272 + leaf_data_end(right), push_space); 3345 3273 3346 - memmove_extent_buffer(right, btrfs_item_nr_offset(right, 0), 3347 - btrfs_item_nr_offset(left, push_items), 3348 - (btrfs_header_nritems(right) - push_items) * 3349 - sizeof(struct btrfs_item)); 3274 + memmove_leaf_items(right, 0, push_items, 3275 + btrfs_header_nritems(right) - push_items); 3350 3276 } 3351 3277 3352 3278 btrfs_init_map_token(&token, right); ··· 3475 3407 btrfs_set_header_nritems(right, nritems); 3476 3408 data_copy_size = btrfs_item_data_end(l, mid) - leaf_data_end(l); 3477 3409 3478 - copy_extent_buffer(right, l, btrfs_item_nr_offset(right, 0), 3479 - btrfs_item_nr_offset(l, mid), 3480 - nritems * sizeof(struct btrfs_item)); 3410 + copy_leaf_items(right, l, 0, mid, nritems); 3481 3411 3482 - copy_extent_buffer(right, l, 3483 - BTRFS_LEAF_DATA_OFFSET + BTRFS_LEAF_DATA_SIZE(fs_info) - 3484 - data_copy_size, BTRFS_LEAF_DATA_OFFSET + 3485 - leaf_data_end(l), data_copy_size); 3412 + copy_leaf_data(right, l, BTRFS_LEAF_DATA_SIZE(fs_info) - data_copy_size, 3413 + leaf_data_end(l), data_copy_size); 3486 3414 3487 3415 rt_data_off = BTRFS_LEAF_DATA_SIZE(fs_info) - btrfs_item_data_end(l, mid); 3488 3416 ··· 3848 3784 nritems = btrfs_header_nritems(leaf); 3849 3785 if (slot != nritems) { 3850 3786 /* shift the items */ 3851 - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, slot + 1), 3852 - btrfs_item_nr_offset(leaf, slot), 3853 - (nritems - slot) * sizeof(struct btrfs_item)); 3787 + memmove_leaf_items(leaf, slot + 1, slot, nritems - slot); 3854 3788 } 3855 3789 3856 3790 btrfs_cpu_key_to_disk(&disk_key, new_key); ··· 3959 3897 3960 3898 /* shift the data */ 3961 3899 if (from_end) { 3962 - memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET + 3963 - data_end + size_diff, BTRFS_LEAF_DATA_OFFSET + 3964 - data_end, old_data_start + new_size - data_end); 3900 + memmove_leaf_data(leaf, data_end + size_diff, data_end, 3901 + old_data_start + new_size - data_end); 3965 3902 } else { 3966 3903 struct btrfs_disk_key disk_key; 3967 3904 u64 offset; ··· 3985 3924 } 3986 3925 } 3987 3926 3988 - memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET + 3989 - data_end + size_diff, BTRFS_LEAF_DATA_OFFSET + 3990 - data_end, old_data_start - data_end); 3927 + memmove_leaf_data(leaf, data_end + size_diff, data_end, 3928 + old_data_start - data_end); 3991 3929 3992 3930 offset = btrfs_disk_key_offset(&disk_key); 3993 3931 btrfs_set_disk_key_offset(&disk_key, offset + size_diff); ··· 4051 3991 } 4052 3992 4053 3993 /* shift the data */ 4054 - memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET + 4055 - data_end - data_size, BTRFS_LEAF_DATA_OFFSET + 4056 - data_end, old_data - data_end); 3994 + memmove_leaf_data(leaf, data_end - data_size, data_end, 3995 + old_data - data_end); 4057 3996 4058 3997 data_end = old_data; 4059 3998 old_size = btrfs_item_size(leaf, slot); ··· 4136 4077 ioff - batch->total_data_size); 4137 4078 } 4138 4079 /* shift the items */ 4139 - memmove_extent_buffer(leaf, 4140 - btrfs_item_nr_offset(leaf, slot + batch->nr), 4141 - btrfs_item_nr_offset(leaf, slot), 4142 - (nritems - slot) * sizeof(struct btrfs_item)); 4080 + memmove_leaf_items(leaf, slot + batch->nr, slot, nritems - slot); 4143 4081 4144 4082 /* shift the data */ 4145 - memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET + 4146 - data_end - batch->total_data_size, 4147 - BTRFS_LEAF_DATA_OFFSET + data_end, 4148 - old_data - data_end); 4083 + memmove_leaf_data(leaf, data_end - batch->total_data_size, 4084 + data_end, old_data - data_end); 4149 4085 data_end = old_data; 4150 4086 } 4151 4087 ··· 4375 4321 for (i = 0; i < nr; i++) 4376 4322 dsize += btrfs_item_size(leaf, slot + i); 4377 4323 4378 - memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET + 4379 - data_end + dsize, 4380 - BTRFS_LEAF_DATA_OFFSET + data_end, 4381 - last_off - data_end); 4324 + memmove_leaf_data(leaf, data_end + dsize, data_end, 4325 + last_off - data_end); 4382 4326 4383 4327 btrfs_init_map_token(&token, leaf); 4384 4328 for (i = slot + nr; i < nritems; i++) { ··· 4386 4334 btrfs_set_token_item_offset(&token, i, ioff + dsize); 4387 4335 } 4388 4336 4389 - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, slot), 4390 - btrfs_item_nr_offset(leaf, slot + nr), 4391 - sizeof(struct btrfs_item) * 4392 - (nritems - slot - nr)); 4337 + memmove_leaf_items(leaf, slot, slot + nr, nritems - slot - nr); 4393 4338 } 4394 4339 btrfs_set_header_nritems(leaf, nritems - nr); 4395 4340 nritems -= nr;