|
@@ -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,
|