diff options
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 22 | 
1 files changed, 15 insertions, 7 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index d11d0289f3d..6dcee88c2e5 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -404,20 +404,28 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)   *	NULL first argument is nfsd_sync_dir() and that's not a directory.   */ -static int block_fsync(struct file *filp, struct dentry *dentry, int datasync) +int blkdev_fsync(struct file *filp, struct dentry *dentry, int datasync)  { -	struct block_device *bdev = I_BDEV(filp->f_mapping->host); +	struct inode *bd_inode = filp->f_mapping->host; +	struct block_device *bdev = I_BDEV(bd_inode);  	int error; -	error = sync_blockdev(bdev); -	if (error) -		return error; -	 +	/* +	 * There is no need to serialise calls to blkdev_issue_flush with +	 * i_mutex and doing so causes performance issues with concurrent +	 * O_SYNC writers to a block device. +	 */ +	mutex_unlock(&bd_inode->i_mutex); +  	error = blkdev_issue_flush(bdev, NULL);  	if (error == -EOPNOTSUPP)  		error = 0; + +	mutex_lock(&bd_inode->i_mutex); +  	return error;  } +EXPORT_SYMBOL(blkdev_fsync);  /*   * pseudo-fs @@ -1481,7 +1489,7 @@ const struct file_operations def_blk_fops = {    	.aio_read	= generic_file_aio_read,  	.aio_write	= blkdev_aio_write,  	.mmap		= generic_file_mmap, -	.fsync		= block_fsync, +	.fsync		= blkdev_fsync,  	.unlocked_ioctl	= block_ioctl,  #ifdef CONFIG_COMPAT  	.compat_ioctl	= compat_blkdev_ioctl,  |