aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-02-01 06:04:40 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-01 11:53:09 -0500
commit9cd684551124e71630ab96d238747051463f5b56 (patch)
tree52de759d09d79ded7ff6746a3e2d5c002c75b2f8 /fs/fuse/inode.c
parentcaf736085f2f0d22a992a855d9caae14973f7ea4 (diff)
[PATCH] fuse: fix async read for legacy filesystems
While asynchronous reads mean a performance improvement in most cases, if the filesystem assumed that reads are synchronous, then async reads may degrade performance (filesystem may receive reads out of order, which can confuse it's own readahead logic). With sshfs a 1.5 to 4 times slowdown can be measured. There's also a need for userspace filesystems to know whether asynchronous reads are supported by the kernel or not. To achive these, negotiate in the INIT request whether async reads will be used and the maximum readahead value. Update interface version to 7.6 If userspace uses a version earlier than 7.6, then disable async reads, and set maximum readahead value to the maximum read size, as done in previous versions. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index c755a0440a66..879e6fba9480 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -473,6 +473,16 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
473 if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) 473 if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
474 fc->conn_error = 1; 474 fc->conn_error = 1;
475 else { 475 else {
476 unsigned long ra_pages;
477
478 if (arg->minor >= 6) {
479 ra_pages = arg->max_readahead / PAGE_CACHE_SIZE;
480 if (arg->flags & FUSE_ASYNC_READ)
481 fc->async_read = 1;
482 } else
483 ra_pages = fc->max_read / PAGE_CACHE_SIZE;
484
485 fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
476 fc->minor = arg->minor; 486 fc->minor = arg->minor;
477 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 487 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
478 } 488 }
@@ -496,6 +506,8 @@ static void fuse_send_init(struct fuse_conn *fc)
496 506
497 arg->major = FUSE_KERNEL_VERSION; 507 arg->major = FUSE_KERNEL_VERSION;
498 arg->minor = FUSE_KERNEL_MINOR_VERSION; 508 arg->minor = FUSE_KERNEL_MINOR_VERSION;
509 arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
510 arg->flags |= FUSE_ASYNC_READ;
499 req->in.h.opcode = FUSE_INIT; 511 req->in.h.opcode = FUSE_INIT;
500 req->in.numargs = 1; 512 req->in.numargs = 1;
501 req->in.args[0].size = sizeof(*arg); 513 req->in.args[0].size = sizeof(*arg);
@@ -552,8 +564,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
552 fc->user_id = d.user_id; 564 fc->user_id = d.user_id;
553 fc->group_id = d.group_id; 565 fc->group_id = d.group_id;
554 fc->max_read = d.max_read; 566 fc->max_read = d.max_read;
555 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
556 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
557 567
558 /* Used by get_root_inode() */ 568 /* Used by get_root_inode() */
559 sb->s_fs_info = fc; 569 sb->s_fs_info = fc;