mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
Btrfs: hold a ref on the inode during writepages
We can race with unlink and not actually be able to do our igrab in btrfs_add_ordered_extent. This will result in all sorts of problems. Instead of doing the complicated work to try and handle returning an error properly from btrfs_add_ordered_extent, just hold a ref to the inode during writepages. If we cannot grab a ref we know we're freeing this inode anyway and can just drop the dirty pages on the floor, because screw them we're going to invalidate them anyway. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
This commit is contained in:
parent
bdb7d303b3
commit
7fd1a3f73f
1 changed files with 14 additions and 0 deletions
|
@ -3324,6 +3324,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
|
||||||
writepage_t writepage, void *data,
|
writepage_t writepage, void *data,
|
||||||
void (*flush_fn)(void *))
|
void (*flush_fn)(void *))
|
||||||
{
|
{
|
||||||
|
struct inode *inode = mapping->host;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
int nr_to_write_done = 0;
|
int nr_to_write_done = 0;
|
||||||
|
@ -3334,6 +3335,18 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
|
||||||
int scanned = 0;
|
int scanned = 0;
|
||||||
int tag;
|
int tag;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have to hold onto the inode so that ordered extents can do their
|
||||||
|
* work when the IO finishes. The alternative to this is failing to add
|
||||||
|
* an ordered extent if the igrab() fails there and that is a huge pain
|
||||||
|
* to deal with, so instead just hold onto the inode throughout the
|
||||||
|
* writepages operation. If it fails here we are freeing up the inode
|
||||||
|
* anyway and we'd rather not waste our time writing out stuff that is
|
||||||
|
* going to be truncated anyway.
|
||||||
|
*/
|
||||||
|
if (!igrab(inode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
pagevec_init(&pvec, 0);
|
pagevec_init(&pvec, 0);
|
||||||
if (wbc->range_cyclic) {
|
if (wbc->range_cyclic) {
|
||||||
index = mapping->writeback_index; /* Start from prev offset */
|
index = mapping->writeback_index; /* Start from prev offset */
|
||||||
|
@ -3428,6 +3441,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
|
||||||
index = 0;
|
index = 0;
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
btrfs_add_delayed_iput(inode);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue