Commit 8180ef88 authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: keep inode pinned when compressing writes

A user reported lots of problems using compression on the new code and it
turns out part of the problem was that igrab() was failing when we added a
new ordered extent.  This is because when writing out an inode under
compression we immediately return without actually doing anything to the
pages, and then in another thread at some point down the line actually do
the ordered dance.  The problem is between the point that we start writeback
and we actually add the ordered extent we could be trying to reclaim the
inode, which makes igrab() return NULL.  So we need to do an igrab() when we
create the async extent and then drop it when we are done with it.  This
makes sure we stay pinned in memory until the ordered extent can get a
reference on it and we are good to go.  With this patch we no longer panic
in btrfs_finish_ordered_io().  Thanks,
Signed-off-by: default avatarJosef Bacik <josef@redhat.com>
parent 9c5085c1
...@@ -986,8 +986,10 @@ static noinline void async_cow_start(struct btrfs_work *work) ...@@ -986,8 +986,10 @@ static noinline void async_cow_start(struct btrfs_work *work)
compress_file_range(async_cow->inode, async_cow->locked_page, compress_file_range(async_cow->inode, async_cow->locked_page,
async_cow->start, async_cow->end, async_cow, async_cow->start, async_cow->end, async_cow,
&num_added); &num_added);
if (num_added == 0) if (num_added == 0) {
iput(async_cow->inode);
async_cow->inode = NULL; async_cow->inode = NULL;
}
} }
/* /*
...@@ -1020,6 +1022,8 @@ static noinline void async_cow_free(struct btrfs_work *work) ...@@ -1020,6 +1022,8 @@ static noinline void async_cow_free(struct btrfs_work *work)
{ {
struct async_cow *async_cow; struct async_cow *async_cow;
async_cow = container_of(work, struct async_cow, work); async_cow = container_of(work, struct async_cow, work);
if (async_cow->inode)
iput(async_cow->inode);
kfree(async_cow); kfree(async_cow);
} }
...@@ -1038,7 +1042,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, ...@@ -1038,7 +1042,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
while (start < end) { while (start < end) {
async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS);
BUG_ON(!async_cow); /* -ENOMEM */ BUG_ON(!async_cow); /* -ENOMEM */
async_cow->inode = inode; async_cow->inode = igrab(inode);
async_cow->root = root; async_cow->root = root;
async_cow->locked_page = locked_page; async_cow->locked_page = locked_page;
async_cow->start = start; async_cow->start = start;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment