aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorZheng Yan <zheng.yan@oracle.com>2008-09-26 10:05:38 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-26 10:05:38 -0400
commit5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03 (patch)
tree9af8f539ac487c163f3207bc065767c3c8b37ae7 /fs/btrfs/file.c
parente465768938f95388723b0fd3c50a0ae48173edb9 (diff)
Btrfs: extent_map and data=ordered fixes for space balancing
* Add an EXTENT_BOUNDARY state bit to keep the writepage code from merging data extents that are in the process of being relocated. This allows us to do accounting for them properly. * The balancing code relocates data extents indepdent of the underlying inode. The extent_map code was modified to properly account for things moving around (invalidating extent_map caches in the inode). * Don't take the drop_mutex in the create_subvol ioctl. It isn't required. * Fix walking of the ordered extent list to avoid races with sys_unlink * Change the lock ordering rules. Transaction start goes outside the drop_mutex. This allows btrfs_commit_transaction to directly drop the relocation trees. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 8856570a0ebd..1b7e51a9db0f 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -294,7 +294,7 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
294 last_pos_in_file, 294 last_pos_in_file,
295 0, 0, hole_size, 0); 295 0, 0, hole_size, 0);
296 btrfs_drop_extent_cache(inode, last_pos_in_file, 296 btrfs_drop_extent_cache(inode, last_pos_in_file,
297 last_pos_in_file + hole_size -1); 297 last_pos_in_file + hole_size - 1, 0);
298 mutex_unlock(&BTRFS_I(inode)->extent_mutex); 298 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
299 btrfs_check_file(root, inode); 299 btrfs_check_file(root, inode);
300 } 300 }
@@ -337,7 +337,7 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
337 inline_size -= start_pos; 337 inline_size -= start_pos;
338 err = insert_inline_extent(trans, root, inode, start_pos, 338 err = insert_inline_extent(trans, root, inode, start_pos,
339 inline_size, pages, 0, num_pages); 339 inline_size, pages, 0, num_pages);
340 btrfs_drop_extent_cache(inode, start_pos, aligned_end - 1); 340 btrfs_drop_extent_cache(inode, start_pos, aligned_end - 1, 0);
341 BUG_ON(err); 341 BUG_ON(err);
342 mutex_unlock(&BTRFS_I(inode)->extent_mutex); 342 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
343 343
@@ -362,7 +362,8 @@ out_unlock:
362 return err; 362 return err;
363} 363}
364 364
365int noinline btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end) 365int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
366 int skip_pinned)
366{ 367{
367 struct extent_map *em; 368 struct extent_map *em;
368 struct extent_map *split = NULL; 369 struct extent_map *split = NULL;
@@ -371,6 +372,7 @@ int noinline btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
371 u64 len = end - start + 1; 372 u64 len = end - start + 1;
372 int ret; 373 int ret;
373 int testend = 1; 374 int testend = 1;
375 unsigned long flags;
374 376
375 WARN_ON(end < start); 377 WARN_ON(end < start);
376 if (end == (u64)-1) { 378 if (end == (u64)-1) {
@@ -389,6 +391,23 @@ int noinline btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
389 spin_unlock(&em_tree->lock); 391 spin_unlock(&em_tree->lock);
390 break; 392 break;
391 } 393 }
394 flags = em->flags;
395 if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
396 spin_unlock(&em_tree->lock);
397 if (em->start <= start &&
398 (!testend || em->start + em->len >= start + len)) {
399 free_extent_map(em);
400 break;
401 }
402 if (start < em->start) {
403 len = em->start - start;
404 } else {
405 len = start + len - (em->start + em->len);
406 start = em->start + em->len;
407 }
408 free_extent_map(em);
409 continue;
410 }
392 clear_bit(EXTENT_FLAG_PINNED, &em->flags); 411 clear_bit(EXTENT_FLAG_PINNED, &em->flags);
393 remove_extent_mapping(em_tree, em); 412 remove_extent_mapping(em_tree, em);
394 413
@@ -398,7 +417,7 @@ int noinline btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
398 split->len = start - em->start; 417 split->len = start - em->start;
399 split->block_start = em->block_start; 418 split->block_start = em->block_start;
400 split->bdev = em->bdev; 419 split->bdev = em->bdev;
401 split->flags = em->flags; 420 split->flags = flags;
402 ret = add_extent_mapping(em_tree, split); 421 ret = add_extent_mapping(em_tree, split);
403 BUG_ON(ret); 422 BUG_ON(ret);
404 free_extent_map(split); 423 free_extent_map(split);
@@ -412,7 +431,7 @@ int noinline btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
412 split->start = start + len; 431 split->start = start + len;
413 split->len = em->start + em->len - (start + len); 432 split->len = em->start + em->len - (start + len);
414 split->bdev = em->bdev; 433 split->bdev = em->bdev;
415 split->flags = em->flags; 434 split->flags = flags;
416 435
417 split->block_start = em->block_start + diff; 436 split->block_start = em->block_start + diff;
418 437
@@ -541,7 +560,7 @@ int noinline btrfs_drop_extents(struct btrfs_trans_handle *trans,
541 int recow; 560 int recow;
542 int ret; 561 int ret;
543 562
544 btrfs_drop_extent_cache(inode, start, end - 1); 563 btrfs_drop_extent_cache(inode, start, end - 1, 0);
545 564
546 path = btrfs_alloc_path(); 565 path = btrfs_alloc_path();
547 if (!path) 566 if (!path)