Commit 00f5c795 authored by Chris Mason's avatar Chris Mason

btrfs_drop_extents: make sure the item is getting smaller before truncate

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent ca664626
...@@ -1037,7 +1037,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end); ...@@ -1037,7 +1037,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end);
extern struct file_operations btrfs_file_operations; extern struct file_operations btrfs_file_operations;
int btrfs_drop_extents(struct btrfs_trans_handle *trans, int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode, struct btrfs_root *root, struct inode *inode,
u64 start, u64 end, u64 inline_end, u64 *hint_block); u64 start, u64 end, u64 inline_limit, u64 *hint_block);
/* tree-defrag.c */ /* tree-defrag.c */
int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
struct btrfs_root *root, int cache_only); struct btrfs_root *root, int cache_only);
......
...@@ -45,6 +45,9 @@ static int cache_block_group(struct btrfs_root *root, ...@@ -45,6 +45,9 @@ static int cache_block_group(struct btrfs_root *root,
u64 first_free; u64 first_free;
int found = 0; int found = 0;
if (!block_group)
return 0;
root = root->fs_info->extent_root; root = root->fs_info->extent_root;
free_space_cache = &root->fs_info->free_space_cache; free_space_cache = &root->fs_info->free_space_cache;
...@@ -168,6 +171,11 @@ static u64 find_search_start(struct btrfs_root *root, ...@@ -168,6 +171,11 @@ static u64 find_search_start(struct btrfs_root *root,
u64 cache_miss = 0; u64 cache_miss = 0;
int wrapped = 0; int wrapped = 0;
if (!cache) {
cache = btrfs_lookup_block_group(root->fs_info, search_start);
if (!cache)
return search_start;
}
again: again:
ret = cache_block_group(root, cache); ret = cache_block_group(root, cache);
if (ret) if (ret)
......
...@@ -377,23 +377,23 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end) ...@@ -377,23 +377,23 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
*/ */
int btrfs_drop_extents(struct btrfs_trans_handle *trans, int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode, struct btrfs_root *root, struct inode *inode,
u64 start, u64 end, u64 inline_end, u64 *hint_byte) u64 start, u64 end, u64 inline_limit, u64 *hint_byte)
{ {
int ret; u64 extent_end = 0;
struct btrfs_key key; u64 search_start = start;
struct extent_buffer *leaf; struct extent_buffer *leaf;
int slot;
struct btrfs_file_extent_item *extent; struct btrfs_file_extent_item *extent;
u64 extent_end = 0;
int keep;
struct btrfs_file_extent_item old;
struct btrfs_path *path; struct btrfs_path *path;
u64 search_start = start; struct btrfs_key key;
struct btrfs_file_extent_item old;
int keep;
int slot;
int bookend; int bookend;
int found_type; int found_type;
int found_extent; int found_extent;
int found_inline; int found_inline;
int recow; int recow;
int ret;
btrfs_drop_extent_cache(inode, start, end - 1); btrfs_drop_extent_cache(inode, start, end - 1);
...@@ -502,7 +502,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, ...@@ -502,7 +502,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
} }
bookend = 1; bookend = 1;
if (found_inline && start <= key.offset && if (found_inline && start <= key.offset &&
inline_end < extent_end) inline_limit < extent_end)
keep = 1; keep = 1;
} }
/* truncate existing extent */ /* truncate existing extent */
...@@ -526,12 +526,12 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, ...@@ -526,12 +526,12 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
btrfs_set_file_extent_num_bytes(leaf, extent, btrfs_set_file_extent_num_bytes(leaf, extent,
new_num); new_num);
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
} else if (end > extent_end && } else if (key.offset < inline_limit &&
key.offset < inline_end && (end > extent_end) &&
inline_end < extent_end) { (inline_limit < extent_end)) {
u32 new_size; u32 new_size;
new_size = btrfs_file_extent_calc_inline_size( new_size = btrfs_file_extent_calc_inline_size(
inline_end - key.offset); inline_limit - key.offset);
btrfs_truncate_item(trans, root, path, btrfs_truncate_item(trans, root, path,
new_size, 1); new_size, 1);
} }
...@@ -575,10 +575,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, ...@@ -575,10 +575,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
continue; continue;
} }
if (bookend && found_inline && start <= key.offset && if (bookend && found_inline && start <= key.offset &&
inline_end < extent_end) { inline_limit < extent_end && key.offset <= inline_limit) {
u32 new_size; u32 new_size;
new_size = btrfs_file_extent_calc_inline_size( new_size = btrfs_file_extent_calc_inline_size(
extent_end - inline_end); extent_end - inline_limit);
btrfs_truncate_item(trans, root, path, new_size, 0); btrfs_truncate_item(trans, root, path, new_size, 0);
} }
/* create bookend, splitting the extent in two */ /* create bookend, splitting the extent in two */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment