diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/inode.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index bb7fd8072802..d3d7d46a6af2 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -538,7 +538,7 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
538 | struct btrfs_root *root = BTRFS_I(inode)->root; | 538 | struct btrfs_root *root = BTRFS_I(inode)->root; |
539 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 539 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
540 | struct extent_io_tree *io_tree; | 540 | struct extent_io_tree *io_tree; |
541 | int ret; | 541 | int ret = 0; |
542 | 542 | ||
543 | if (list_empty(&async_cow->extents)) | 543 | if (list_empty(&async_cow->extents)) |
544 | return 0; | 544 | return 0; |
@@ -552,6 +552,7 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
552 | 552 | ||
553 | io_tree = &BTRFS_I(inode)->io_tree; | 553 | io_tree = &BTRFS_I(inode)->io_tree; |
554 | 554 | ||
555 | retry: | ||
555 | /* did the compression code fall back to uncompressed IO? */ | 556 | /* did the compression code fall back to uncompressed IO? */ |
556 | if (!async_extent->pages) { | 557 | if (!async_extent->pages) { |
557 | int page_started = 0; | 558 | int page_started = 0; |
@@ -562,11 +563,11 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
562 | async_extent->ram_size - 1, GFP_NOFS); | 563 | async_extent->ram_size - 1, GFP_NOFS); |
563 | 564 | ||
564 | /* allocate blocks */ | 565 | /* allocate blocks */ |
565 | cow_file_range(inode, async_cow->locked_page, | 566 | ret = cow_file_range(inode, async_cow->locked_page, |
566 | async_extent->start, | 567 | async_extent->start, |
567 | async_extent->start + | 568 | async_extent->start + |
568 | async_extent->ram_size - 1, | 569 | async_extent->ram_size - 1, |
569 | &page_started, &nr_written, 0); | 570 | &page_started, &nr_written, 0); |
570 | 571 | ||
571 | /* | 572 | /* |
572 | * if page_started, cow_file_range inserted an | 573 | * if page_started, cow_file_range inserted an |
@@ -574,7 +575,7 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
574 | * and IO for us. Otherwise, we need to submit | 575 | * and IO for us. Otherwise, we need to submit |
575 | * all those pages down to the drive. | 576 | * all those pages down to the drive. |
576 | */ | 577 | */ |
577 | if (!page_started) | 578 | if (!page_started && !ret) |
578 | extent_write_locked_range(io_tree, | 579 | extent_write_locked_range(io_tree, |
579 | inode, async_extent->start, | 580 | inode, async_extent->start, |
580 | async_extent->start + | 581 | async_extent->start + |
@@ -602,7 +603,21 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
602 | async_extent->compressed_size, | 603 | async_extent->compressed_size, |
603 | 0, alloc_hint, | 604 | 0, alloc_hint, |
604 | (u64)-1, &ins, 1); | 605 | (u64)-1, &ins, 1); |
605 | BUG_ON(ret); | 606 | if (ret) { |
607 | int i; | ||
608 | for (i = 0; i < async_extent->nr_pages; i++) { | ||
609 | WARN_ON(async_extent->pages[i]->mapping); | ||
610 | page_cache_release(async_extent->pages[i]); | ||
611 | } | ||
612 | kfree(async_extent->pages); | ||
613 | async_extent->nr_pages = 0; | ||
614 | async_extent->pages = NULL; | ||
615 | unlock_extent(io_tree, async_extent->start, | ||
616 | async_extent->start + | ||
617 | async_extent->ram_size - 1, GFP_NOFS); | ||
618 | goto retry; | ||
619 | } | ||
620 | |||
606 | em = alloc_extent_map(GFP_NOFS); | 621 | em = alloc_extent_map(GFP_NOFS); |
607 | em->start = async_extent->start; | 622 | em->start = async_extent->start; |
608 | em->len = async_extent->ram_size; | 623 | em->len = async_extent->ram_size; |