diff options
author | Yan, Zheng <zheng.yan@oracle.com> | 2009-11-12 04:34:21 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-12-17 12:33:24 -0500 |
commit | c216775458a2ee345d9412a2770c2916acfb5d30 (patch) | |
tree | 41a947a9d254aeeef40b7e42162d80646477f30a /fs/btrfs/inode.c | |
parent | 920bbbfb05c9fce22e088d20eb9dcb8f96342de9 (diff) |
Btrfs: Fix disk_i_size update corner case
There are some cases file extents are inserted without involving
ordered struct. In these cases, we update disk_i_size directly,
without checking pending ordered extent and DELALLOC bit. This
patch extends btrfs_ordered_update_i_size() to handle these cases.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index ef250be49cdb..fa57247887e3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -188,8 +188,18 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
188 | btrfs_mark_buffer_dirty(leaf); | 188 | btrfs_mark_buffer_dirty(leaf); |
189 | btrfs_free_path(path); | 189 | btrfs_free_path(path); |
190 | 190 | ||
191 | /* | ||
192 | * we're an inline extent, so nobody can | ||
193 | * extend the file past i_size without locking | ||
194 | * a page we already have locked. | ||
195 | * | ||
196 | * We must do any isize and inode updates | ||
197 | * before we unlock the pages. Otherwise we | ||
198 | * could end up racing with unlink. | ||
199 | */ | ||
191 | BTRFS_I(inode)->disk_i_size = inode->i_size; | 200 | BTRFS_I(inode)->disk_i_size = inode->i_size; |
192 | btrfs_update_inode(trans, root, inode); | 201 | btrfs_update_inode(trans, root, inode); |
202 | |||
193 | return 0; | 203 | return 0; |
194 | fail: | 204 | fail: |
195 | btrfs_free_path(path); | 205 | btrfs_free_path(path); |
@@ -415,7 +425,6 @@ again: | |||
415 | start, end, | 425 | start, end, |
416 | total_compressed, pages); | 426 | total_compressed, pages); |
417 | } | 427 | } |
418 | btrfs_end_transaction(trans, root); | ||
419 | if (ret == 0) { | 428 | if (ret == 0) { |
420 | /* | 429 | /* |
421 | * inline extent creation worked, we don't need | 430 | * inline extent creation worked, we don't need |
@@ -429,9 +438,11 @@ again: | |||
429 | EXTENT_CLEAR_DELALLOC | | 438 | EXTENT_CLEAR_DELALLOC | |
430 | EXTENT_CLEAR_ACCOUNTING | | 439 | EXTENT_CLEAR_ACCOUNTING | |
431 | EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK); | 440 | EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK); |
432 | ret = 0; | 441 | |
442 | btrfs_end_transaction(trans, root); | ||
433 | goto free_pages_out; | 443 | goto free_pages_out; |
434 | } | 444 | } |
445 | btrfs_end_transaction(trans, root); | ||
435 | } | 446 | } |
436 | 447 | ||
437 | if (will_compress) { | 448 | if (will_compress) { |
@@ -542,7 +553,6 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
542 | if (list_empty(&async_cow->extents)) | 553 | if (list_empty(&async_cow->extents)) |
543 | return 0; | 554 | return 0; |
544 | 555 | ||
545 | trans = btrfs_join_transaction(root, 1); | ||
546 | 556 | ||
547 | while (!list_empty(&async_cow->extents)) { | 557 | while (!list_empty(&async_cow->extents)) { |
548 | async_extent = list_entry(async_cow->extents.next, | 558 | async_extent = list_entry(async_cow->extents.next, |
@@ -589,19 +599,15 @@ retry: | |||
589 | lock_extent(io_tree, async_extent->start, | 599 | lock_extent(io_tree, async_extent->start, |
590 | async_extent->start + async_extent->ram_size - 1, | 600 | async_extent->start + async_extent->ram_size - 1, |
591 | GFP_NOFS); | 601 | GFP_NOFS); |
592 | /* | ||
593 | * here we're doing allocation and writeback of the | ||
594 | * compressed pages | ||
595 | */ | ||
596 | btrfs_drop_extent_cache(inode, async_extent->start, | ||
597 | async_extent->start + | ||
598 | async_extent->ram_size - 1, 0); | ||
599 | 602 | ||
603 | trans = btrfs_join_transaction(root, 1); | ||
600 | ret = btrfs_reserve_extent(trans, root, | 604 | ret = btrfs_reserve_extent(trans, root, |
601 | async_extent->compressed_size, | 605 | async_extent->compressed_size, |
602 | async_extent->compressed_size, | 606 | async_extent->compressed_size, |
603 | 0, alloc_hint, | 607 | 0, alloc_hint, |
604 | (u64)-1, &ins, 1); | 608 | (u64)-1, &ins, 1); |
609 | btrfs_end_transaction(trans, root); | ||
610 | |||
605 | if (ret) { | 611 | if (ret) { |
606 | int i; | 612 | int i; |
607 | for (i = 0; i < async_extent->nr_pages; i++) { | 613 | for (i = 0; i < async_extent->nr_pages; i++) { |
@@ -617,6 +623,14 @@ retry: | |||
617 | goto retry; | 623 | goto retry; |
618 | } | 624 | } |
619 | 625 | ||
626 | /* | ||
627 | * here we're doing allocation and writeback of the | ||
628 | * compressed pages | ||
629 | */ | ||
630 | btrfs_drop_extent_cache(inode, async_extent->start, | ||
631 | async_extent->start + | ||
632 | async_extent->ram_size - 1, 0); | ||
633 | |||
620 | em = alloc_extent_map(GFP_NOFS); | 634 | em = alloc_extent_map(GFP_NOFS); |
621 | em->start = async_extent->start; | 635 | em->start = async_extent->start; |
622 | em->len = async_extent->ram_size; | 636 | em->len = async_extent->ram_size; |
@@ -648,8 +662,6 @@ retry: | |||
648 | BTRFS_ORDERED_COMPRESSED); | 662 | BTRFS_ORDERED_COMPRESSED); |
649 | BUG_ON(ret); | 663 | BUG_ON(ret); |
650 | 664 | ||
651 | btrfs_end_transaction(trans, root); | ||
652 | |||
653 | /* | 665 | /* |
654 | * clear dirty, set writeback and unlock the pages. | 666 | * clear dirty, set writeback and unlock the pages. |
655 | */ | 667 | */ |
@@ -671,13 +683,11 @@ retry: | |||
671 | async_extent->nr_pages); | 683 | async_extent->nr_pages); |
672 | 684 | ||
673 | BUG_ON(ret); | 685 | BUG_ON(ret); |
674 | trans = btrfs_join_transaction(root, 1); | ||
675 | alloc_hint = ins.objectid + ins.offset; | 686 | alloc_hint = ins.objectid + ins.offset; |
676 | kfree(async_extent); | 687 | kfree(async_extent); |
677 | cond_resched(); | 688 | cond_resched(); |
678 | } | 689 | } |
679 | 690 | ||
680 | btrfs_end_transaction(trans, root); | ||
681 | return 0; | 691 | return 0; |
682 | } | 692 | } |
683 | 693 | ||
@@ -741,6 +751,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
741 | EXTENT_CLEAR_DIRTY | | 751 | EXTENT_CLEAR_DIRTY | |
742 | EXTENT_SET_WRITEBACK | | 752 | EXTENT_SET_WRITEBACK | |
743 | EXTENT_END_WRITEBACK); | 753 | EXTENT_END_WRITEBACK); |
754 | |||
744 | *nr_written = *nr_written + | 755 | *nr_written = *nr_written + |
745 | (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE; | 756 | (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE; |
746 | *page_started = 1; | 757 | *page_started = 1; |
@@ -1727,18 +1738,27 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1727 | } | 1738 | } |
1728 | } | 1739 | } |
1729 | 1740 | ||
1730 | trans = btrfs_join_transaction(root, 1); | ||
1731 | |||
1732 | if (!ordered_extent) | 1741 | if (!ordered_extent) |
1733 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); | 1742 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); |
1734 | BUG_ON(!ordered_extent); | 1743 | BUG_ON(!ordered_extent); |
1735 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) | 1744 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) { |
1736 | goto nocow; | 1745 | BUG_ON(!list_empty(&ordered_extent->list)); |
1746 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); | ||
1747 | if (!ret) { | ||
1748 | trans = btrfs_join_transaction(root, 1); | ||
1749 | ret = btrfs_update_inode(trans, root, inode); | ||
1750 | BUG_ON(ret); | ||
1751 | btrfs_end_transaction(trans, root); | ||
1752 | } | ||
1753 | goto out; | ||
1754 | } | ||
1737 | 1755 | ||
1738 | lock_extent(io_tree, ordered_extent->file_offset, | 1756 | lock_extent(io_tree, ordered_extent->file_offset, |
1739 | ordered_extent->file_offset + ordered_extent->len - 1, | 1757 | ordered_extent->file_offset + ordered_extent->len - 1, |
1740 | GFP_NOFS); | 1758 | GFP_NOFS); |
1741 | 1759 | ||
1760 | trans = btrfs_join_transaction(root, 1); | ||
1761 | |||
1742 | if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) | 1762 | if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) |
1743 | compressed = 1; | 1763 | compressed = 1; |
1744 | if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { | 1764 | if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { |
@@ -1765,22 +1785,20 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1765 | unlock_extent(io_tree, ordered_extent->file_offset, | 1785 | unlock_extent(io_tree, ordered_extent->file_offset, |
1766 | ordered_extent->file_offset + ordered_extent->len - 1, | 1786 | ordered_extent->file_offset + ordered_extent->len - 1, |
1767 | GFP_NOFS); | 1787 | GFP_NOFS); |
1768 | nocow: | ||
1769 | add_pending_csums(trans, inode, ordered_extent->file_offset, | 1788 | add_pending_csums(trans, inode, ordered_extent->file_offset, |
1770 | &ordered_extent->list); | 1789 | &ordered_extent->list); |
1771 | 1790 | ||
1772 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | 1791 | /* this also removes the ordered extent from the tree */ |
1773 | btrfs_ordered_update_i_size(inode, ordered_extent); | 1792 | btrfs_ordered_update_i_size(inode, 0, ordered_extent); |
1774 | btrfs_update_inode(trans, root, inode); | 1793 | ret = btrfs_update_inode(trans, root, inode); |
1775 | btrfs_remove_ordered_extent(inode, ordered_extent); | 1794 | BUG_ON(ret); |
1776 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | 1795 | btrfs_end_transaction(trans, root); |
1777 | 1796 | out: | |
1778 | /* once for us */ | 1797 | /* once for us */ |
1779 | btrfs_put_ordered_extent(ordered_extent); | 1798 | btrfs_put_ordered_extent(ordered_extent); |
1780 | /* once for the tree */ | 1799 | /* once for the tree */ |
1781 | btrfs_put_ordered_extent(ordered_extent); | 1800 | btrfs_put_ordered_extent(ordered_extent); |
1782 | 1801 | ||
1783 | btrfs_end_transaction(trans, root); | ||
1784 | return 0; | 1802 | return 0; |
1785 | } | 1803 | } |
1786 | 1804 | ||
@@ -3562,7 +3580,6 @@ static noinline void init_btrfs_i(struct inode *inode) | |||
3562 | INIT_LIST_HEAD(&BTRFS_I(inode)->ordered_operations); | 3580 | INIT_LIST_HEAD(&BTRFS_I(inode)->ordered_operations); |
3563 | RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); | 3581 | RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); |
3564 | btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree); | 3582 | btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree); |
3565 | mutex_init(&BTRFS_I(inode)->extent_mutex); | ||
3566 | mutex_init(&BTRFS_I(inode)->log_mutex); | 3583 | mutex_init(&BTRFS_I(inode)->log_mutex); |
3567 | } | 3584 | } |
3568 | 3585 | ||