aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/file.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index b3ad8d61a162..e570081f9f76 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2373,6 +2373,11 @@ static void fuse_do_truncate(struct file *file)
2373 fuse_do_setattr(inode, &attr, file); 2373 fuse_do_setattr(inode, &attr, file);
2374} 2374}
2375 2375
2376static inline loff_t fuse_round_up(loff_t off)
2377{
2378 return round_up(off, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
2379}
2380
2376static ssize_t 2381static ssize_t
2377fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, 2382fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2378 loff_t offset, unsigned long nr_segs) 2383 loff_t offset, unsigned long nr_segs)
@@ -2380,6 +2385,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2380 ssize_t ret = 0; 2385 ssize_t ret = 0;
2381 struct file *file = iocb->ki_filp; 2386 struct file *file = iocb->ki_filp;
2382 struct fuse_file *ff = file->private_data; 2387 struct fuse_file *ff = file->private_data;
2388 bool async_dio = ff->fc->async_dio;
2383 loff_t pos = 0; 2389 loff_t pos = 0;
2384 struct inode *inode; 2390 struct inode *inode;
2385 loff_t i_size; 2391 loff_t i_size;
@@ -2391,10 +2397,10 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2391 i_size = i_size_read(inode); 2397 i_size = i_size_read(inode);
2392 2398
2393 /* optimization for short read */ 2399 /* optimization for short read */
2394 if (rw != WRITE && offset + count > i_size) { 2400 if (async_dio && rw != WRITE && offset + count > i_size) {
2395 if (offset >= i_size) 2401 if (offset >= i_size)
2396 return 0; 2402 return 0;
2397 count = i_size - offset; 2403 count = min_t(loff_t, count, fuse_round_up(i_size - offset));
2398 } 2404 }
2399 2405
2400 io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL); 2406 io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
@@ -2412,7 +2418,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2412 * By default, we want to optimize all I/Os with async request 2418 * By default, we want to optimize all I/Os with async request
2413 * submission to the client filesystem if supported. 2419 * submission to the client filesystem if supported.
2414 */ 2420 */
2415 io->async = ff->fc->async_dio; 2421 io->async = async_dio;
2416 io->iocb = iocb; 2422 io->iocb = iocb;
2417 2423
2418 /* 2424 /*
@@ -2420,7 +2426,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2420 * to wait on real async I/O requests, so we must submit this request 2426 * to wait on real async I/O requests, so we must submit this request
2421 * synchronously. 2427 * synchronously.
2422 */ 2428 */
2423 if (!is_sync_kiocb(iocb) && (offset + count > i_size)) 2429 if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE)
2424 io->async = false; 2430 io->async = false;
2425 2431
2426 if (rw == WRITE) 2432 if (rw == WRITE)