aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/file.c9
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c14
-rw-r--r--include/linux/fuse.h16
4 files changed, 36 insertions, 6 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a7ef5e716f3c..296351615b00 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -335,9 +335,14 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file,
335 loff_t pos = page_offset(req->pages[0]); 335 loff_t pos = page_offset(req->pages[0]);
336 size_t count = req->num_pages << PAGE_CACHE_SHIFT; 336 size_t count = req->num_pages << PAGE_CACHE_SHIFT;
337 req->out.page_zeroing = 1; 337 req->out.page_zeroing = 1;
338 req->end = fuse_readpages_end;
339 fuse_read_fill(req, file, inode, pos, count, FUSE_READ); 338 fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
340 request_send_background(fc, req); 339 if (fc->async_read) {
340 req->end = fuse_readpages_end;
341 request_send_background(fc, req);
342 } else {
343 request_send(fc, req);
344 fuse_readpages_end(fc, req);
345 }
341} 346}
342 347
343struct fuse_readpages_data { 348struct fuse_readpages_data {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 46cf933aa3bf..4a83adfec968 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -272,6 +272,9 @@ struct fuse_conn {
272 reply, before any other request, and never cleared */ 272 reply, before any other request, and never cleared */
273 unsigned conn_error : 1; 273 unsigned conn_error : 1;
274 274
275 /** Do readpages asynchronously? Only set in INIT */
276 unsigned async_read : 1;
277
275 /* 278 /*
276 * The following bitfields are only for optimization purposes 279 * The following bitfields are only for optimization purposes
277 * and hence races in setting them will not cause malfunction 280 * and hence races in setting them will not cause malfunction
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;
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 528959c52f1b..5425b60021e3 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -14,7 +14,7 @@
14#define FUSE_KERNEL_VERSION 7 14#define FUSE_KERNEL_VERSION 7
15 15
16/** Minor version number of this interface */ 16/** Minor version number of this interface */
17#define FUSE_KERNEL_MINOR_VERSION 5 17#define FUSE_KERNEL_MINOR_VERSION 6
18 18
19/** The node ID of the root inode */ 19/** The node ID of the root inode */
20#define FUSE_ROOT_ID 1 20#define FUSE_ROOT_ID 1
@@ -58,6 +58,9 @@ struct fuse_kstatfs {
58 __u32 spare[6]; 58 __u32 spare[6];
59}; 59};
60 60
61/**
62 * Bitmasks for fuse_setattr_in.valid
63 */
61#define FATTR_MODE (1 << 0) 64#define FATTR_MODE (1 << 0)
62#define FATTR_UID (1 << 1) 65#define FATTR_UID (1 << 1)
63#define FATTR_GID (1 << 2) 66#define FATTR_GID (1 << 2)
@@ -75,6 +78,11 @@ struct fuse_kstatfs {
75#define FOPEN_DIRECT_IO (1 << 0) 78#define FOPEN_DIRECT_IO (1 << 0)
76#define FOPEN_KEEP_CACHE (1 << 1) 79#define FOPEN_KEEP_CACHE (1 << 1)
77 80
81/**
82 * INIT request/reply flags
83 */
84#define FUSE_ASYNC_READ (1 << 0)
85
78enum fuse_opcode { 86enum fuse_opcode {
79 FUSE_LOOKUP = 1, 87 FUSE_LOOKUP = 1,
80 FUSE_FORGET = 2, /* no reply */ 88 FUSE_FORGET = 2, /* no reply */
@@ -247,12 +255,16 @@ struct fuse_access_in {
247struct fuse_init_in { 255struct fuse_init_in {
248 __u32 major; 256 __u32 major;
249 __u32 minor; 257 __u32 minor;
258 __u32 max_readahead;
259 __u32 flags;
250}; 260};
251 261
252struct fuse_init_out { 262struct fuse_init_out {
253 __u32 major; 263 __u32 major;
254 __u32 minor; 264 __u32 minor;
255 __u32 unused[3]; 265 __u32 max_readahead;
266 __u32 flags;
267 __u32 unused;
256 __u32 max_write; 268 __u32 max_write;
257}; 269};
258 270