diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
| -rw-r--r-- | fs/btrfs/extent_io.c | 14 | 
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index aaa12c1eb34..01c21b6c6d4 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3324,6 +3324,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,  			     writepage_t writepage, void *data,  			     void (*flush_fn)(void *))  { +	struct inode *inode = mapping->host;  	int ret = 0;  	int 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 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);  	if (wbc->range_cyclic) {  		index = mapping->writeback_index; /* Start from prev offset */ @@ -3428,6 +3441,7 @@ retry:  		index = 0;  		goto retry;  	} +	btrfs_add_delayed_iput(inode);  	return ret;  }  |