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.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 516b90224a1b..eef9c92f86d5 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1930,7 +1930,7 @@ again:
1930int btrfs_truncate_item(struct btrfs_trans_handle *trans, 1930int btrfs_truncate_item(struct btrfs_trans_handle *trans,
1931 struct btrfs_root *root, 1931 struct btrfs_root *root,
1932 struct btrfs_path *path, 1932 struct btrfs_path *path,
1933 u32 new_size) 1933 u32 new_size, int from_end)
1934{ 1934{
1935 int ret = 0; 1935 int ret = 0;
1936 int slot; 1936 int slot;
@@ -1946,13 +1946,17 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
1946 1946
1947 slot_orig = path->slots[0]; 1947 slot_orig = path->slots[0];
1948 leaf = path->nodes[0]; 1948 leaf = path->nodes[0];
1949 slot = path->slots[0];
1950
1951 old_size = btrfs_item_size_nr(leaf, slot);
1952 if (old_size == new_size)
1953 return 0;
1949 1954
1950 nritems = btrfs_header_nritems(leaf); 1955 nritems = btrfs_header_nritems(leaf);
1951 data_end = leaf_data_end(root, leaf); 1956 data_end = leaf_data_end(root, leaf);
1952 1957
1953 slot = path->slots[0];
1954 old_data_start = btrfs_item_offset_nr(leaf, slot); 1958 old_data_start = btrfs_item_offset_nr(leaf, slot);
1955 old_size = btrfs_item_size_nr(leaf, slot); BUG_ON(old_size <= new_size); 1959
1956 size_diff = old_size - new_size; 1960 size_diff = old_size - new_size;
1957 1961
1958 BUG_ON(slot < 0); 1962 BUG_ON(slot < 0);
@@ -1984,9 +1988,45 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
1984 } 1988 }
1985 1989
1986 /* shift the data */ 1990 /* shift the data */
1987 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + 1991 if (from_end) {
1988 data_end + size_diff, btrfs_leaf_data(leaf) + 1992 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
1989 data_end, old_data_start + new_size - data_end); 1993 data_end + size_diff, btrfs_leaf_data(leaf) +
1994 data_end, old_data_start + new_size - data_end);
1995 } else {
1996 struct btrfs_disk_key disk_key;
1997 u64 offset;
1998
1999 btrfs_item_key(leaf, &disk_key, slot);
2000
2001 if (btrfs_disk_key_type(&disk_key) == BTRFS_EXTENT_DATA_KEY) {
2002 unsigned long ptr;
2003 struct btrfs_file_extent_item *fi;
2004
2005 fi = btrfs_item_ptr(leaf, slot,
2006 struct btrfs_file_extent_item);
2007 fi = (struct btrfs_file_extent_item *)(
2008 (unsigned long)fi - size_diff);
2009
2010 if (btrfs_file_extent_type(leaf, fi) ==
2011 BTRFS_FILE_EXTENT_INLINE) {
2012 ptr = btrfs_item_ptr_offset(leaf, slot);
2013 memmove_extent_buffer(leaf, ptr,
2014 (unsigned long)fi,
2015 offsetof(struct btrfs_file_extent_item,
2016 disk_bytenr));
2017 }
2018 }
2019
2020 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
2021 data_end + size_diff, btrfs_leaf_data(leaf) +
2022 data_end, old_data_start - data_end);
2023
2024 offset = btrfs_disk_key_offset(&disk_key);
2025 btrfs_set_disk_key_offset(&disk_key, offset + size_diff);
2026 btrfs_set_item_key(leaf, &disk_key, slot);
2027 if (slot == 0)
2028 fixup_low_keys(trans, root, path, &disk_key, 1);
2029 }
1990 2030
1991 item = btrfs_item_nr(leaf, slot); 2031 item = btrfs_item_nr(leaf, slot);
1992 btrfs_set_item_size(leaf, item, new_size); 2032 btrfs_set_item_size(leaf, item, new_size);