diff options
author | Zheng Yan <zheng.yan@oracle.com> | 2008-09-26 10:05:38 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-26 10:05:38 -0400 |
commit | 5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03 (patch) | |
tree | 9af8f539ac487c163f3207bc065767c3c8b37ae7 /fs/btrfs/file.c | |
parent | e465768938f95388723b0fd3c50a0ae48173edb9 (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.c | 31 |
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 | ||
365 | int noinline btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end) | 365 | int 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) |