diff options
Diffstat (limited to 'fs/fuse/file.c')
| -rw-r--r-- | fs/fuse/file.c | 25 | 
1 files changed, 12 insertions, 13 deletions
| diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6611ef3269a8..43c165e796da 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3091,11 +3091,10 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)  	ssize_t ret = 0;  	struct file *file = iocb->ki_filp;  	struct fuse_file *ff = file->private_data; -	bool async_dio = ff->fc->async_dio;  	loff_t pos = 0;  	struct inode *inode;  	loff_t i_size; -	size_t count = iov_iter_count(iter); +	size_t count = iov_iter_count(iter), shortened = 0;  	loff_t offset = iocb->ki_pos;  	struct fuse_io_priv *io; @@ -3103,17 +3102,9 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)  	inode = file->f_mapping->host;  	i_size = i_size_read(inode); -	if ((iov_iter_rw(iter) == READ) && (offset > i_size)) +	if ((iov_iter_rw(iter) == READ) && (offset >= i_size))  		return 0; -	/* optimization for short read */ -	if (async_dio && iov_iter_rw(iter) != WRITE && offset + count > i_size) { -		if (offset >= i_size) -			return 0; -		iov_iter_truncate(iter, fuse_round_up(ff->fc, i_size - offset)); -		count = iov_iter_count(iter); -	} -  	io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);  	if (!io)  		return -ENOMEM; @@ -3129,15 +3120,22 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)  	 * By default, we want to optimize all I/Os with async request  	 * submission to the client filesystem if supported.  	 */ -	io->async = async_dio; +	io->async = ff->fc->async_dio;  	io->iocb = iocb;  	io->blocking = is_sync_kiocb(iocb); +	/* optimization for short read */ +	if (io->async && !io->write && offset + count > i_size) { +		iov_iter_truncate(iter, fuse_round_up(ff->fc, i_size - offset)); +		shortened = count - iov_iter_count(iter); +		count -= shortened; +	} +  	/*  	 * We cannot asynchronously extend the size of a file.  	 * In such case the aio will behave exactly like sync io.  	 */ -	if ((offset + count > i_size) && iov_iter_rw(iter) == WRITE) +	if ((offset + count > i_size) && io->write)  		io->blocking = true;  	if (io->async && io->blocking) { @@ -3155,6 +3153,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)  	} else {  		ret = __fuse_direct_read(io, iter, &pos);  	} +	iov_iter_reexpand(iter, iov_iter_count(iter) + shortened);  	if (io->async) {  		bool blocking = io->blocking; |