aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/file.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ba1d50369c24..8f39f7b8cef2 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1331,7 +1331,8 @@ EXPORT_SYMBOL_GPL(fuse_direct_io);
1331 1331
1332static ssize_t __fuse_direct_read(struct fuse_io_priv *io, 1332static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
1333 const struct iovec *iov, 1333 const struct iovec *iov,
1334 unsigned long nr_segs, loff_t *ppos) 1334 unsigned long nr_segs, loff_t *ppos,
1335 size_t count)
1335{ 1336{
1336 ssize_t res; 1337 ssize_t res;
1337 struct file *file = io->file; 1338 struct file *file = io->file;
@@ -1340,8 +1341,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
1340 if (is_bad_inode(inode)) 1341 if (is_bad_inode(inode))
1341 return -EIO; 1342 return -EIO;
1342 1343
1343 res = fuse_direct_io(io, iov, nr_segs, iov_length(iov, nr_segs), 1344 res = fuse_direct_io(io, iov, nr_segs, count, ppos, 0);
1344 ppos, 0);
1345 1345
1346 fuse_invalidate_attr(inode); 1346 fuse_invalidate_attr(inode);
1347 1347
@@ -1353,7 +1353,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
1353{ 1353{
1354 struct fuse_io_priv io = { .async = 0, .file = file }; 1354 struct fuse_io_priv io = { .async = 0, .file = file };
1355 struct iovec iov = { .iov_base = buf, .iov_len = count }; 1355 struct iovec iov = { .iov_base = buf, .iov_len = count };
1356 return __fuse_direct_read(&io, &iov, 1, ppos); 1356 return __fuse_direct_read(&io, &iov, 1, ppos, count);
1357} 1357}
1358 1358
1359static ssize_t __fuse_direct_write(struct fuse_io_priv *io, 1359static ssize_t __fuse_direct_write(struct fuse_io_priv *io,
@@ -2369,6 +2369,13 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2369 inode = file->f_mapping->host; 2369 inode = file->f_mapping->host;
2370 i_size = i_size_read(inode); 2370 i_size = i_size_read(inode);
2371 2371
2372 /* optimization for short read */
2373 if (rw != WRITE && offset + count > i_size) {
2374 if (offset >= i_size)
2375 return 0;
2376 count = i_size - offset;
2377 }
2378
2372 io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL); 2379 io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
2373 if (!io) 2380 if (!io)
2374 return -ENOMEM; 2381 return -ENOMEM;
@@ -2392,13 +2399,13 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2392 * to wait on real async I/O requests, so we must submit this request 2399 * to wait on real async I/O requests, so we must submit this request
2393 * synchronously. 2400 * synchronously.
2394 */ 2401 */
2395 if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE) 2402 if (!is_sync_kiocb(iocb) && (offset + count > i_size))
2396 io->async = false; 2403 io->async = false;
2397 2404
2398 if (rw == WRITE) 2405 if (rw == WRITE)
2399 ret = __fuse_direct_write(io, iov, nr_segs, &pos); 2406 ret = __fuse_direct_write(io, iov, nr_segs, &pos);
2400 else 2407 else
2401 ret = __fuse_direct_read(io, iov, nr_segs, &pos); 2408 ret = __fuse_direct_read(io, iov, nr_segs, &pos, count);
2402 2409
2403 if (io->async) { 2410 if (io->async) {
2404 fuse_aio_complete(io, ret < 0 ? ret : 0, -1); 2411 fuse_aio_complete(io, ret < 0 ? ret : 0, -1);