diff options
Diffstat (limited to 'fs/btrfs/file.c')
| -rw-r--r-- | fs/btrfs/file.c | 16 | 
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e764ac3f22e2..d90138683a0a 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1885,6 +1885,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)  	 */  	if (full_sync || btrfs_is_zoned(fs_info)) {  		ret = btrfs_wait_ordered_range(inode, start, len); +		clear_bit(BTRFS_INODE_COW_WRITE_ERROR, &BTRFS_I(inode)->runtime_flags);  	} else {  		/*  		 * Get our ordered extents as soon as possible to avoid doing @@ -1894,6 +1895,21 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)  		btrfs_get_ordered_extents_for_logging(BTRFS_I(inode),  						      &ctx.ordered_extents);  		ret = filemap_fdatawait_range(inode->i_mapping, start, end); +		if (ret) +			goto out_release_extents; + +		/* +		 * Check and clear the BTRFS_INODE_COW_WRITE_ERROR now after +		 * starting and waiting for writeback, because for buffered IO +		 * it may have been set during the end IO callback +		 * (end_bbio_data_write() -> btrfs_finish_ordered_extent()) in +		 * case an error happened and we need to wait for ordered +		 * extents to complete so that any extent maps that point to +		 * unwritten locations are dropped and we don't log them. +		 */ +		if (test_and_clear_bit(BTRFS_INODE_COW_WRITE_ERROR, +				       &BTRFS_I(inode)->runtime_flags)) +			ret = btrfs_wait_ordered_range(inode, start, len);  	}  	if (ret)  |