Commit e5c5f05dca0cf90f0f3bb1aea85dcf658baff185

Authored by Maxim Patlasov
Committed by Miklos Szeredi
1 parent c9ecf989cc

fuse: fix alignment in short read optimization for async_dio

The bug was introduced with async_dio feature: trying to optimize short reads,
we cut number-of-bytes-to-read to i_size boundary. Hence the following example:

	truncate --size=300 /mnt/file
	dd if=/mnt/file of=/dev/null iflag=direct

led to FUSE_READ request of 300 bytes size. This turned out to be problem
for userspace fuse implementations who rely on assumption that kernel fuse
does not change alignment of request from client FS.

The patch turns off the optimization if async_dio is disabled. And, if it's
enabled, the patch fixes adjustment of number-of-bytes-to-read to preserve
alignment.

Note, that we cannot throw out short read optimization entirely because
otherwise a direct read of a huge size issued on a tiny file would generate
a huge amount of fuse requests and most of them would be ACKed by userspace
with zero bytes read.

Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>

Showing 1 changed file with 10 additions and 4 deletions Side-by-side Diff

... ... @@ -2373,6 +2373,11 @@
2373 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 2381 static ssize_t
2377 2382 fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2378 2383 loff_t offset, unsigned long nr_segs)
... ... @@ -2380,6 +2385,7 @@
2380 2385 ssize_t ret = 0;
2381 2386 struct file *file = iocb->ki_filp;
2382 2387 struct fuse_file *ff = file->private_data;
  2388 + bool async_dio = ff->fc->async_dio;
2383 2389 loff_t pos = 0;
2384 2390 struct inode *inode;
2385 2391 loff_t i_size;
2386 2392  
... ... @@ -2391,10 +2397,10 @@
2391 2397 i_size = i_size_read(inode);
2392 2398  
2393 2399 /* optimization for short read */
2394   - if (rw != WRITE && offset + count > i_size) {
  2400 + if (async_dio && rw != WRITE && offset + count > i_size) {
2395 2401 if (offset >= i_size)
2396 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 2406 io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
... ... @@ -2412,7 +2418,7 @@
2412 2418 * By default, we want to optimize all I/Os with async request
2413 2419 * submission to the client filesystem if supported.
2414 2420 */
2415   - io->async = ff->fc->async_dio;
  2421 + io->async = async_dio;
2416 2422 io->iocb = iocb;
2417 2423  
2418 2424 /*
... ... @@ -2420,7 +2426,7 @@
2420 2426 * to wait on real async I/O requests, so we must submit this request
2421 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 2430 io->async = false;
2425 2431  
2426 2432 if (rw == WRITE)