diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 105 |
1 files changed, 81 insertions, 24 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 5799bc46a309..9b16073bb875 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -291,16 +291,16 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) | |||
291 | 291 | ||
292 | /* | 292 | /* |
293 | * remove an ordered extent from the tree. No references are dropped | 293 | * remove an ordered extent from the tree. No references are dropped |
294 | * but, anyone waiting on this extent is woken up. | 294 | * and you must wake_up entry->wait. You must hold the tree mutex |
295 | * while you call this function. | ||
295 | */ | 296 | */ |
296 | int btrfs_remove_ordered_extent(struct inode *inode, | 297 | static int __btrfs_remove_ordered_extent(struct inode *inode, |
297 | struct btrfs_ordered_extent *entry) | 298 | struct btrfs_ordered_extent *entry) |
298 | { | 299 | { |
299 | struct btrfs_ordered_inode_tree *tree; | 300 | struct btrfs_ordered_inode_tree *tree; |
300 | struct rb_node *node; | 301 | struct rb_node *node; |
301 | 302 | ||
302 | tree = &BTRFS_I(inode)->ordered_tree; | 303 | tree = &BTRFS_I(inode)->ordered_tree; |
303 | mutex_lock(&tree->mutex); | ||
304 | node = &entry->rb_node; | 304 | node = &entry->rb_node; |
305 | rb_erase(node, &tree->tree); | 305 | rb_erase(node, &tree->tree); |
306 | tree->last = NULL; | 306 | tree->last = NULL; |
@@ -326,9 +326,26 @@ int btrfs_remove_ordered_extent(struct inode *inode, | |||
326 | } | 326 | } |
327 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | 327 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); |
328 | 328 | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * remove an ordered extent from the tree. No references are dropped | ||
334 | * but any waiters are woken. | ||
335 | */ | ||
336 | int btrfs_remove_ordered_extent(struct inode *inode, | ||
337 | struct btrfs_ordered_extent *entry) | ||
338 | { | ||
339 | struct btrfs_ordered_inode_tree *tree; | ||
340 | int ret; | ||
341 | |||
342 | tree = &BTRFS_I(inode)->ordered_tree; | ||
343 | mutex_lock(&tree->mutex); | ||
344 | ret = __btrfs_remove_ordered_extent(inode, entry); | ||
329 | mutex_unlock(&tree->mutex); | 345 | mutex_unlock(&tree->mutex); |
330 | wake_up(&entry->wait); | 346 | wake_up(&entry->wait); |
331 | return 0; | 347 | |
348 | return ret; | ||
332 | } | 349 | } |
333 | 350 | ||
334 | /* | 351 | /* |
@@ -589,7 +606,7 @@ out: | |||
589 | * After an extent is done, call this to conditionally update the on disk | 606 | * After an extent is done, call this to conditionally update the on disk |
590 | * i_size. i_size is updated to cover any fully written part of the file. | 607 | * i_size. i_size is updated to cover any fully written part of the file. |
591 | */ | 608 | */ |
592 | int btrfs_ordered_update_i_size(struct inode *inode, | 609 | int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, |
593 | struct btrfs_ordered_extent *ordered) | 610 | struct btrfs_ordered_extent *ordered) |
594 | { | 611 | { |
595 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; | 612 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
@@ -597,18 +614,30 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
597 | u64 disk_i_size; | 614 | u64 disk_i_size; |
598 | u64 new_i_size; | 615 | u64 new_i_size; |
599 | u64 i_size_test; | 616 | u64 i_size_test; |
617 | u64 i_size = i_size_read(inode); | ||
600 | struct rb_node *node; | 618 | struct rb_node *node; |
619 | struct rb_node *prev = NULL; | ||
601 | struct btrfs_ordered_extent *test; | 620 | struct btrfs_ordered_extent *test; |
621 | int ret = 1; | ||
622 | |||
623 | if (ordered) | ||
624 | offset = entry_end(ordered); | ||
602 | 625 | ||
603 | mutex_lock(&tree->mutex); | 626 | mutex_lock(&tree->mutex); |
604 | disk_i_size = BTRFS_I(inode)->disk_i_size; | 627 | disk_i_size = BTRFS_I(inode)->disk_i_size; |
605 | 628 | ||
629 | /* truncate file */ | ||
630 | if (disk_i_size > i_size) { | ||
631 | BTRFS_I(inode)->disk_i_size = i_size; | ||
632 | ret = 0; | ||
633 | goto out; | ||
634 | } | ||
635 | |||
606 | /* | 636 | /* |
607 | * if the disk i_size is already at the inode->i_size, or | 637 | * if the disk i_size is already at the inode->i_size, or |
608 | * this ordered extent is inside the disk i_size, we're done | 638 | * this ordered extent is inside the disk i_size, we're done |
609 | */ | 639 | */ |
610 | if (disk_i_size >= inode->i_size || | 640 | if (disk_i_size == i_size || offset <= disk_i_size) { |
611 | ordered->file_offset + ordered->len <= disk_i_size) { | ||
612 | goto out; | 641 | goto out; |
613 | } | 642 | } |
614 | 643 | ||
@@ -616,8 +645,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
616 | * we can't update the disk_isize if there are delalloc bytes | 645 | * we can't update the disk_isize if there are delalloc bytes |
617 | * between disk_i_size and this ordered extent | 646 | * between disk_i_size and this ordered extent |
618 | */ | 647 | */ |
619 | if (test_range_bit(io_tree, disk_i_size, | 648 | if (test_range_bit(io_tree, disk_i_size, offset - 1, |
620 | ordered->file_offset + ordered->len - 1, | ||
621 | EXTENT_DELALLOC, 0, NULL)) { | 649 | EXTENT_DELALLOC, 0, NULL)) { |
622 | goto out; | 650 | goto out; |
623 | } | 651 | } |
@@ -626,20 +654,32 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
626 | * if we find an ordered extent then we can't update disk i_size | 654 | * if we find an ordered extent then we can't update disk i_size |
627 | * yet | 655 | * yet |
628 | */ | 656 | */ |
629 | node = &ordered->rb_node; | 657 | if (ordered) { |
630 | while (1) { | 658 | node = rb_prev(&ordered->rb_node); |
631 | node = rb_prev(node); | 659 | } else { |
632 | if (!node) | 660 | prev = tree_search(tree, offset); |
633 | break; | 661 | /* |
662 | * we insert file extents without involving ordered struct, | ||
663 | * so there should be no ordered struct cover this offset | ||
664 | */ | ||
665 | if (prev) { | ||
666 | test = rb_entry(prev, struct btrfs_ordered_extent, | ||
667 | rb_node); | ||
668 | BUG_ON(offset_in_entry(test, offset)); | ||
669 | } | ||
670 | node = prev; | ||
671 | } | ||
672 | while (node) { | ||
634 | test = rb_entry(node, struct btrfs_ordered_extent, rb_node); | 673 | test = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
635 | if (test->file_offset + test->len <= disk_i_size) | 674 | if (test->file_offset + test->len <= disk_i_size) |
636 | break; | 675 | break; |
637 | if (test->file_offset >= inode->i_size) | 676 | if (test->file_offset >= i_size) |
638 | break; | 677 | break; |
639 | if (test->file_offset >= disk_i_size) | 678 | if (test->file_offset >= disk_i_size) |
640 | goto out; | 679 | goto out; |
680 | node = rb_prev(node); | ||
641 | } | 681 | } |
642 | new_i_size = min_t(u64, entry_end(ordered), i_size_read(inode)); | 682 | new_i_size = min_t(u64, offset, i_size); |
643 | 683 | ||
644 | /* | 684 | /* |
645 | * at this point, we know we can safely update i_size to at least | 685 | * at this point, we know we can safely update i_size to at least |
@@ -647,7 +687,14 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
647 | * walk forward and see if ios from higher up in the file have | 687 | * walk forward and see if ios from higher up in the file have |
648 | * finished. | 688 | * finished. |
649 | */ | 689 | */ |
650 | node = rb_next(&ordered->rb_node); | 690 | if (ordered) { |
691 | node = rb_next(&ordered->rb_node); | ||
692 | } else { | ||
693 | if (prev) | ||
694 | node = rb_next(prev); | ||
695 | else | ||
696 | node = rb_first(&tree->tree); | ||
697 | } | ||
651 | i_size_test = 0; | 698 | i_size_test = 0; |
652 | if (node) { | 699 | if (node) { |
653 | /* | 700 | /* |
@@ -655,10 +702,10 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
655 | * between our ordered extent and the next one. | 702 | * between our ordered extent and the next one. |
656 | */ | 703 | */ |
657 | test = rb_entry(node, struct btrfs_ordered_extent, rb_node); | 704 | test = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
658 | if (test->file_offset > entry_end(ordered)) | 705 | if (test->file_offset > offset) |
659 | i_size_test = test->file_offset; | 706 | i_size_test = test->file_offset; |
660 | } else { | 707 | } else { |
661 | i_size_test = i_size_read(inode); | 708 | i_size_test = i_size; |
662 | } | 709 | } |
663 | 710 | ||
664 | /* | 711 | /* |
@@ -667,15 +714,25 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
667 | * are no delalloc bytes in this area, it is safe to update | 714 | * are no delalloc bytes in this area, it is safe to update |
668 | * disk_i_size to the end of the region. | 715 | * disk_i_size to the end of the region. |
669 | */ | 716 | */ |
670 | if (i_size_test > entry_end(ordered) && | 717 | if (i_size_test > offset && |
671 | !test_range_bit(io_tree, entry_end(ordered), i_size_test - 1, | 718 | !test_range_bit(io_tree, offset, i_size_test - 1, |
672 | EXTENT_DELALLOC, 0, NULL)) { | 719 | EXTENT_DELALLOC, 0, NULL)) { |
673 | new_i_size = min_t(u64, i_size_test, i_size_read(inode)); | 720 | new_i_size = min_t(u64, i_size_test, i_size); |
674 | } | 721 | } |
675 | BTRFS_I(inode)->disk_i_size = new_i_size; | 722 | BTRFS_I(inode)->disk_i_size = new_i_size; |
723 | ret = 0; | ||
676 | out: | 724 | out: |
725 | /* | ||
726 | * we need to remove the ordered extent with the tree lock held | ||
727 | * so that other people calling this function don't find our fully | ||
728 | * processed ordered entry and skip updating the i_size | ||
729 | */ | ||
730 | if (ordered) | ||
731 | __btrfs_remove_ordered_extent(inode, ordered); | ||
677 | mutex_unlock(&tree->mutex); | 732 | mutex_unlock(&tree->mutex); |
678 | return 0; | 733 | if (ordered) |
734 | wake_up(&ordered->wait); | ||
735 | return ret; | ||
679 | } | 736 | } |
680 | 737 | ||
681 | /* | 738 | /* |