diff options
Diffstat (limited to 'fs/btrfs/file.c')
| -rw-r--r-- | fs/btrfs/file.c | 21 | 
1 files changed, 15 insertions, 6 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index bd4d061c6e4..59cbdb120ad 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1452,7 +1452,7 @@ int btrfs_release_file(struct inode *inode, struct file *filp)   * important optimization for directories because holding the mutex prevents   * new operations on the dir while we write to disk.   */ -int btrfs_sync_file(struct file *file, int datasync) +int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)  {  	struct dentry *dentry = file->f_path.dentry;  	struct inode *inode = dentry->d_inode; @@ -1462,9 +1462,13 @@ int btrfs_sync_file(struct file *file, int datasync)  	trace_btrfs_sync_file(file, datasync); +	ret = filemap_write_and_wait_range(inode->i_mapping, start, end); +	if (ret) +		return ret; +	mutex_lock(&inode->i_mutex); +  	/* we wait first, since the writeback may change the inode */  	root->log_batch++; -	/* the VFS called filemap_fdatawrite for us */  	btrfs_wait_ordered_range(inode, 0, (u64)-1);  	root->log_batch++; @@ -1472,8 +1476,10 @@ int btrfs_sync_file(struct file *file, int datasync)  	 * check the transaction that last modified this inode  	 * and see if its already been committed  	 */ -	if (!BTRFS_I(inode)->last_trans) +	if (!BTRFS_I(inode)->last_trans) { +		mutex_unlock(&inode->i_mutex);  		goto out; +	}  	/*  	 * if the last transaction that changed this file was before @@ -1484,6 +1490,7 @@ int btrfs_sync_file(struct file *file, int datasync)  	if (BTRFS_I(inode)->last_trans <=  	    root->fs_info->last_trans_committed) {  		BTRFS_I(inode)->last_trans = 0; +		mutex_unlock(&inode->i_mutex);  		goto out;  	} @@ -1496,12 +1503,15 @@ int btrfs_sync_file(struct file *file, int datasync)  	trans = btrfs_start_transaction(root, 0);  	if (IS_ERR(trans)) {  		ret = PTR_ERR(trans); +		mutex_unlock(&inode->i_mutex);  		goto out;  	}  	ret = btrfs_log_dentry_safe(trans, root, dentry); -	if (ret < 0) +	if (ret < 0) { +		mutex_unlock(&inode->i_mutex);  		goto out; +	}  	/* we've logged all the items and now have a consistent  	 * version of the file in the log.  It is possible that @@ -1513,7 +1523,7 @@ int btrfs_sync_file(struct file *file, int datasync)  	 * file again, but that will end up using the synchronization  	 * inside btrfs_sync_log to keep things safe.  	 */ -	mutex_unlock(&dentry->d_inode->i_mutex); +	mutex_unlock(&inode->i_mutex);  	if (ret != BTRFS_NO_LOG_SYNC) {  		if (ret > 0) { @@ -1528,7 +1538,6 @@ int btrfs_sync_file(struct file *file, int datasync)  	} else {  		ret = btrfs_end_transaction(trans, root);  	} -	mutex_lock(&dentry->d_inode->i_mutex);  out:  	return ret > 0 ? -EIO : ret;  }  |