diff options
-rw-r--r-- | fs/btrfs/inode.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2dc59734e071..348b7bb920ef 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -608,7 +608,7 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
608 | if (list_empty(&async_cow->extents)) | 608 | if (list_empty(&async_cow->extents)) |
609 | return 0; | 609 | return 0; |
610 | 610 | ||
611 | 611 | again: | |
612 | while (!list_empty(&async_cow->extents)) { | 612 | while (!list_empty(&async_cow->extents)) { |
613 | async_extent = list_entry(async_cow->extents.next, | 613 | async_extent = list_entry(async_cow->extents.next, |
614 | struct async_extent, list); | 614 | struct async_extent, list); |
@@ -648,6 +648,8 @@ retry: | |||
648 | async_extent->ram_size - 1, | 648 | async_extent->ram_size - 1, |
649 | btrfs_get_extent, | 649 | btrfs_get_extent, |
650 | WB_SYNC_ALL); | 650 | WB_SYNC_ALL); |
651 | else if (ret) | ||
652 | unlock_page(async_cow->locked_page); | ||
651 | kfree(async_extent); | 653 | kfree(async_extent); |
652 | cond_resched(); | 654 | cond_resched(); |
653 | continue; | 655 | continue; |
@@ -672,6 +674,7 @@ retry: | |||
672 | 674 | ||
673 | if (ret) { | 675 | if (ret) { |
674 | int i; | 676 | int i; |
677 | |||
675 | for (i = 0; i < async_extent->nr_pages; i++) { | 678 | for (i = 0; i < async_extent->nr_pages; i++) { |
676 | WARN_ON(async_extent->pages[i]->mapping); | 679 | WARN_ON(async_extent->pages[i]->mapping); |
677 | page_cache_release(async_extent->pages[i]); | 680 | page_cache_release(async_extent->pages[i]); |
@@ -679,12 +682,10 @@ retry: | |||
679 | kfree(async_extent->pages); | 682 | kfree(async_extent->pages); |
680 | async_extent->nr_pages = 0; | 683 | async_extent->nr_pages = 0; |
681 | async_extent->pages = NULL; | 684 | async_extent->pages = NULL; |
682 | unlock_extent(io_tree, async_extent->start, | 685 | |
683 | async_extent->start + | ||
684 | async_extent->ram_size - 1); | ||
685 | if (ret == -ENOSPC) | 686 | if (ret == -ENOSPC) |
686 | goto retry; | 687 | goto retry; |
687 | goto out_free; /* JDM: Requeue? */ | 688 | goto out_free; |
688 | } | 689 | } |
689 | 690 | ||
690 | /* | 691 | /* |
@@ -696,7 +697,8 @@ retry: | |||
696 | async_extent->ram_size - 1, 0); | 697 | async_extent->ram_size - 1, 0); |
697 | 698 | ||
698 | em = alloc_extent_map(); | 699 | em = alloc_extent_map(); |
699 | BUG_ON(!em); /* -ENOMEM */ | 700 | if (!em) |
701 | goto out_free_reserve; | ||
700 | em->start = async_extent->start; | 702 | em->start = async_extent->start; |
701 | em->len = async_extent->ram_size; | 703 | em->len = async_extent->ram_size; |
702 | em->orig_start = em->start; | 704 | em->orig_start = em->start; |
@@ -728,6 +730,9 @@ retry: | |||
728 | async_extent->ram_size - 1, 0); | 730 | async_extent->ram_size - 1, 0); |
729 | } | 731 | } |
730 | 732 | ||
733 | if (ret) | ||
734 | goto out_free_reserve; | ||
735 | |||
731 | ret = btrfs_add_ordered_extent_compress(inode, | 736 | ret = btrfs_add_ordered_extent_compress(inode, |
732 | async_extent->start, | 737 | async_extent->start, |
733 | ins.objectid, | 738 | ins.objectid, |
@@ -735,7 +740,8 @@ retry: | |||
735 | ins.offset, | 740 | ins.offset, |
736 | BTRFS_ORDERED_COMPRESSED, | 741 | BTRFS_ORDERED_COMPRESSED, |
737 | async_extent->compress_type); | 742 | async_extent->compress_type); |
738 | BUG_ON(ret); /* -ENOMEM */ | 743 | if (ret) |
744 | goto out_free_reserve; | ||
739 | 745 | ||
740 | /* | 746 | /* |
741 | * clear dirty, set writeback and unlock the pages. | 747 | * clear dirty, set writeback and unlock the pages. |
@@ -756,18 +762,30 @@ retry: | |||
756 | ins.objectid, | 762 | ins.objectid, |
757 | ins.offset, async_extent->pages, | 763 | ins.offset, async_extent->pages, |
758 | async_extent->nr_pages); | 764 | async_extent->nr_pages); |
759 | |||
760 | BUG_ON(ret); /* -ENOMEM */ | ||
761 | alloc_hint = ins.objectid + ins.offset; | 765 | alloc_hint = ins.objectid + ins.offset; |
762 | kfree(async_extent); | 766 | kfree(async_extent); |
767 | if (ret) | ||
768 | goto out; | ||
763 | cond_resched(); | 769 | cond_resched(); |
764 | } | 770 | } |
765 | ret = 0; | 771 | ret = 0; |
766 | out: | 772 | out: |
767 | return ret; | 773 | return ret; |
774 | out_free_reserve: | ||
775 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset); | ||
768 | out_free: | 776 | out_free: |
777 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, | ||
778 | async_extent->start, | ||
779 | async_extent->start + | ||
780 | async_extent->ram_size - 1, | ||
781 | NULL, EXTENT_CLEAR_UNLOCK_PAGE | | ||
782 | EXTENT_CLEAR_UNLOCK | | ||
783 | EXTENT_CLEAR_DELALLOC | | ||
784 | EXTENT_CLEAR_DIRTY | | ||
785 | EXTENT_SET_WRITEBACK | | ||
786 | EXTENT_END_WRITEBACK); | ||
769 | kfree(async_extent); | 787 | kfree(async_extent); |
770 | goto out; | 788 | goto again; |
771 | } | 789 | } |
772 | 790 | ||
773 | static u64 get_extent_allocation_hint(struct inode *inode, u64 start, | 791 | static u64 get_extent_allocation_hint(struct inode *inode, u64 start, |