diff options
Diffstat (limited to 'fs/btrfs/inode.c')
| -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 2dc59734e07..348b7bb920e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -608,7 +608,7 @@ static noinline int submit_compressed_extents(struct inode *inode,  	if (list_empty(&async_cow->extents))  		return 0; - +again:  	while (!list_empty(&async_cow->extents)) {  		async_extent = list_entry(async_cow->extents.next,  					  struct async_extent, list); @@ -648,6 +648,8 @@ retry:  						  async_extent->ram_size - 1,  						  btrfs_get_extent,  						  WB_SYNC_ALL); +			else if (ret) +				unlock_page(async_cow->locked_page);  			kfree(async_extent);  			cond_resched();  			continue; @@ -672,6 +674,7 @@ retry:  		if (ret) {  			int i; +  			for (i = 0; i < async_extent->nr_pages; i++) {  				WARN_ON(async_extent->pages[i]->mapping);  				page_cache_release(async_extent->pages[i]); @@ -679,12 +682,10 @@ retry:  			kfree(async_extent->pages);  			async_extent->nr_pages = 0;  			async_extent->pages = NULL; -			unlock_extent(io_tree, async_extent->start, -				      async_extent->start + -				      async_extent->ram_size - 1); +  			if (ret == -ENOSPC)  				goto retry; -			goto out_free; /* JDM: Requeue? */ +			goto out_free;  		}  		/* @@ -696,7 +697,8 @@ retry:  					async_extent->ram_size - 1, 0);  		em = alloc_extent_map(); -		BUG_ON(!em); /* -ENOMEM */ +		if (!em) +			goto out_free_reserve;  		em->start = async_extent->start;  		em->len = async_extent->ram_size;  		em->orig_start = em->start; @@ -728,6 +730,9 @@ retry:  						async_extent->ram_size - 1, 0);  		} +		if (ret) +			goto out_free_reserve; +  		ret = btrfs_add_ordered_extent_compress(inode,  						async_extent->start,  						ins.objectid, @@ -735,7 +740,8 @@ retry:  						ins.offset,  						BTRFS_ORDERED_COMPRESSED,  						async_extent->compress_type); -		BUG_ON(ret); /* -ENOMEM */ +		if (ret) +			goto out_free_reserve;  		/*  		 * clear dirty, set writeback and unlock the pages. @@ -756,18 +762,30 @@ retry:  				    ins.objectid,  				    ins.offset, async_extent->pages,  				    async_extent->nr_pages); - -		BUG_ON(ret); /* -ENOMEM */  		alloc_hint = ins.objectid + ins.offset;  		kfree(async_extent); +		if (ret) +			goto out;  		cond_resched();  	}  	ret = 0;  out:  	return ret; +out_free_reserve: +	btrfs_free_reserved_extent(root, ins.objectid, ins.offset);  out_free: +	extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, +				     async_extent->start, +				     async_extent->start + +				     async_extent->ram_size - 1, +				     NULL, EXTENT_CLEAR_UNLOCK_PAGE | +				     EXTENT_CLEAR_UNLOCK | +				     EXTENT_CLEAR_DELALLOC | +				     EXTENT_CLEAR_DIRTY | +				     EXTENT_SET_WRITEBACK | +				     EXTENT_END_WRITEBACK);  	kfree(async_extent); -	goto out; +	goto again;  }  static u64 get_extent_allocation_hint(struct inode *inode, u64 start,  |