aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-30 10:09:33 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:58 -0400
commit00f5c795fca47d038fedd3f0c9311da3be710c9f (patch)
tree98e6a349ddfa115b4f0577f3c6e1e24fca2fac59
parentca6646264b7dab662d84435441164bb2a8e8885a (diff)
btrfs_drop_extents: make sure the item is getting smaller before truncate
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c8
-rw-r--r--fs/btrfs/file.c30
3 files changed, 24 insertions, 16 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 56b977ffe918..b29b911dd825 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1037,7 +1037,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end);
1037extern struct file_operations btrfs_file_operations; 1037extern struct file_operations btrfs_file_operations;
1038int btrfs_drop_extents(struct btrfs_trans_handle *trans, 1038int btrfs_drop_extents(struct btrfs_trans_handle *trans,
1039 struct btrfs_root *root, struct inode *inode, 1039 struct btrfs_root *root, struct inode *inode,
1040 u64 start, u64 end, u64 inline_end, u64 *hint_block); 1040 u64 start, u64 end, u64 inline_limit, u64 *hint_block);
1041/* tree-defrag.c */ 1041/* tree-defrag.c */
1042int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, 1042int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
1043 struct btrfs_root *root, int cache_only); 1043 struct btrfs_root *root, int cache_only);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3c00f967eccb..55abdf997ca5 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -45,6 +45,9 @@ static int cache_block_group(struct btrfs_root *root,
45 u64 first_free; 45 u64 first_free;
46 int found = 0; 46 int found = 0;
47 47
48 if (!block_group)
49 return 0;
50
48 root = root->fs_info->extent_root; 51 root = root->fs_info->extent_root;
49 free_space_cache = &root->fs_info->free_space_cache; 52 free_space_cache = &root->fs_info->free_space_cache;
50 53
@@ -168,6 +171,11 @@ static u64 find_search_start(struct btrfs_root *root,
168 u64 cache_miss = 0; 171 u64 cache_miss = 0;
169 int wrapped = 0; 172 int wrapped = 0;
170 173
174 if (!cache) {
175 cache = btrfs_lookup_block_group(root->fs_info, search_start);
176 if (!cache)
177 return search_start;
178 }
171again: 179again:
172 ret = cache_block_group(root, cache); 180 ret = cache_block_group(root, cache);
173 if (ret) 181 if (ret)
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index ba624ae16e61..b0d637787264 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -377,23 +377,23 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
377 */ 377 */
378int btrfs_drop_extents(struct btrfs_trans_handle *trans, 378int btrfs_drop_extents(struct btrfs_trans_handle *trans,
379 struct btrfs_root *root, struct inode *inode, 379 struct btrfs_root *root, struct inode *inode,
380 u64 start, u64 end, u64 inline_end, u64 *hint_byte) 380 u64 start, u64 end, u64 inline_limit, u64 *hint_byte)
381{ 381{
382 int ret; 382 u64 extent_end = 0;
383 struct btrfs_key key; 383 u64 search_start = start;
384 struct extent_buffer *leaf; 384 struct extent_buffer *leaf;
385 int slot;
386 struct btrfs_file_extent_item *extent; 385 struct btrfs_file_extent_item *extent;
387 u64 extent_end = 0;
388 int keep;
389 struct btrfs_file_extent_item old;
390 struct btrfs_path *path; 386 struct btrfs_path *path;
391 u64 search_start = start; 387 struct btrfs_key key;
388 struct btrfs_file_extent_item old;
389 int keep;
390 int slot;
392 int bookend; 391 int bookend;
393 int found_type; 392 int found_type;
394 int found_extent; 393 int found_extent;
395 int found_inline; 394 int found_inline;
396 int recow; 395 int recow;
396 int ret;
397 397
398 btrfs_drop_extent_cache(inode, start, end - 1); 398 btrfs_drop_extent_cache(inode, start, end - 1);
399 399
@@ -502,7 +502,7 @@ next_slot:
502 } 502 }
503 bookend = 1; 503 bookend = 1;
504 if (found_inline && start <= key.offset && 504 if (found_inline && start <= key.offset &&
505 inline_end < extent_end) 505 inline_limit < extent_end)
506 keep = 1; 506 keep = 1;
507 } 507 }
508 /* truncate existing extent */ 508 /* truncate existing extent */
@@ -526,12 +526,12 @@ next_slot:
526 btrfs_set_file_extent_num_bytes(leaf, extent, 526 btrfs_set_file_extent_num_bytes(leaf, extent,
527 new_num); 527 new_num);
528 btrfs_mark_buffer_dirty(leaf); 528 btrfs_mark_buffer_dirty(leaf);
529 } else if (end > extent_end && 529 } else if (key.offset < inline_limit &&
530 key.offset < inline_end && 530 (end > extent_end) &&
531 inline_end < extent_end) { 531 (inline_limit < extent_end)) {
532 u32 new_size; 532 u32 new_size;
533 new_size = btrfs_file_extent_calc_inline_size( 533 new_size = btrfs_file_extent_calc_inline_size(
534 inline_end - key.offset); 534 inline_limit - key.offset);
535 btrfs_truncate_item(trans, root, path, 535 btrfs_truncate_item(trans, root, path,
536 new_size, 1); 536 new_size, 1);
537 } 537 }
@@ -575,10 +575,10 @@ next_slot:
575 continue; 575 continue;
576 } 576 }
577 if (bookend && found_inline && start <= key.offset && 577 if (bookend && found_inline && start <= key.offset &&
578 inline_end < extent_end) { 578 inline_limit < extent_end && key.offset <= inline_limit) {
579 u32 new_size; 579 u32 new_size;
580 new_size = btrfs_file_extent_calc_inline_size( 580 new_size = btrfs_file_extent_calc_inline_size(
581 extent_end - inline_end); 581 extent_end - inline_limit);
582 btrfs_truncate_item(trans, root, path, new_size, 0); 582 btrfs_truncate_item(trans, root, path, new_size, 0);
583 } 583 }
584 /* create bookend, splitting the extent in two */ 584 /* create bookend, splitting the extent in two */