diff options
| -rw-r--r-- | fs/fuse/file.c | 14 |
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 | ||
| 2376 | static inline loff_t fuse_round_up(loff_t off) | ||
| 2377 | { | ||
| 2378 | return round_up(off, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); | ||
| 2379 | } | ||
| 2380 | |||
| 2376 | static ssize_t | 2381 | static ssize_t |
| 2377 | fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 2382 | fuse_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) |
