aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-10-18 06:07:05 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:37:31 -0400
commit0e9663ee452ffce0d429656ebbcfe69417a30e92 (patch)
treea72825f122c9e38d4adc42ebcfd127f366da4a0f
parentf33321141b273d60cbb3a8f56a5489baad82ba5e (diff)
fuse: add blksize field to fuse_attr
There are cases when the filesystem will be passed the buffer from a single read or write call, namely: 1) in 'direct-io' mode (not O_DIRECT), read/write requests don't go through the page cache, but go directly to the userspace fs 2) currently buffered writes are done with single page requests, but if Nick's ->perform_write() patch goes it, it will be possible to do larger write requests. But only if the original write() was also bigger than a page. In these cases the filesystem might want to give a hint to the app about the optimal I/O size. Allow the userspace filesystem to supply a blksize value to be returned by stat() and friends. If the field is zero, it defaults to the old PAGE_CACHE_SIZE value. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/fuse/dir.c32
-rw-r--r--fs/fuse/inode.c5
-rw-r--r--include/linux/fuse.h7
3 files changed, 39 insertions, 5 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 6c83ed052026..3763757f9fe7 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -116,13 +116,19 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
116 struct dentry *entry, 116 struct dentry *entry,
117 struct fuse_entry_out *outarg) 117 struct fuse_entry_out *outarg)
118{ 118{
119 struct fuse_conn *fc = get_fuse_conn(dir);
120
121 memset(outarg, 0, sizeof(struct fuse_entry_out));
119 req->in.h.opcode = FUSE_LOOKUP; 122 req->in.h.opcode = FUSE_LOOKUP;
120 req->in.h.nodeid = get_node_id(dir); 123 req->in.h.nodeid = get_node_id(dir);
121 req->in.numargs = 1; 124 req->in.numargs = 1;
122 req->in.args[0].size = entry->d_name.len + 1; 125 req->in.args[0].size = entry->d_name.len + 1;
123 req->in.args[0].value = entry->d_name.name; 126 req->in.args[0].value = entry->d_name.name;
124 req->out.numargs = 1; 127 req->out.numargs = 1;
125 req->out.args[0].size = sizeof(struct fuse_entry_out); 128 if (fc->minor < 9)
129 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
130 else
131 req->out.args[0].size = sizeof(struct fuse_entry_out);
126 req->out.args[0].value = outarg; 132 req->out.args[0].value = outarg;
127} 133}
128 134
@@ -356,6 +362,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
356 362
357 flags &= ~O_NOCTTY; 363 flags &= ~O_NOCTTY;
358 memset(&inarg, 0, sizeof(inarg)); 364 memset(&inarg, 0, sizeof(inarg));
365 memset(&outentry, 0, sizeof(outentry));
359 inarg.flags = flags; 366 inarg.flags = flags;
360 inarg.mode = mode; 367 inarg.mode = mode;
361 req->in.h.opcode = FUSE_CREATE; 368 req->in.h.opcode = FUSE_CREATE;
@@ -366,7 +373,10 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
366 req->in.args[1].size = entry->d_name.len + 1; 373 req->in.args[1].size = entry->d_name.len + 1;
367 req->in.args[1].value = entry->d_name.name; 374 req->in.args[1].value = entry->d_name.name;
368 req->out.numargs = 2; 375 req->out.numargs = 2;
369 req->out.args[0].size = sizeof(outentry); 376 if (fc->minor < 9)
377 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
378 else
379 req->out.args[0].size = sizeof(outentry);
370 req->out.args[0].value = &outentry; 380 req->out.args[0].value = &outentry;
371 req->out.args[1].size = sizeof(outopen); 381 req->out.args[1].size = sizeof(outopen);
372 req->out.args[1].value = &outopen; 382 req->out.args[1].value = &outopen;
@@ -431,9 +441,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
431 return PTR_ERR(forget_req); 441 return PTR_ERR(forget_req);
432 } 442 }
433 443
444 memset(&outarg, 0, sizeof(outarg));
434 req->in.h.nodeid = get_node_id(dir); 445 req->in.h.nodeid = get_node_id(dir);
435 req->out.numargs = 1; 446 req->out.numargs = 1;
436 req->out.args[0].size = sizeof(outarg); 447 if (fc->minor < 9)
448 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
449 else
450 req->out.args[0].size = sizeof(outarg);
437 req->out.args[0].value = &outarg; 451 req->out.args[0].value = &outarg;
438 request_send(fc, req); 452 request_send(fc, req);
439 err = req->out.h.error; 453 err = req->out.h.error;
@@ -724,6 +738,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
724 spin_unlock(&fc->lock); 738 spin_unlock(&fc->lock);
725 739
726 memset(&inarg, 0, sizeof(inarg)); 740 memset(&inarg, 0, sizeof(inarg));
741 memset(&outarg, 0, sizeof(outarg));
727 /* Directories have separate file-handle space */ 742 /* Directories have separate file-handle space */
728 if (file && S_ISREG(inode->i_mode)) { 743 if (file && S_ISREG(inode->i_mode)) {
729 struct fuse_file *ff = file->private_data; 744 struct fuse_file *ff = file->private_data;
@@ -737,7 +752,10 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
737 req->in.args[0].size = sizeof(inarg); 752 req->in.args[0].size = sizeof(inarg);
738 req->in.args[0].value = &inarg; 753 req->in.args[0].value = &inarg;
739 req->out.numargs = 1; 754 req->out.numargs = 1;
740 req->out.args[0].size = sizeof(outarg); 755 if (fc->minor < 9)
756 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
757 else
758 req->out.args[0].size = sizeof(outarg);
741 req->out.args[0].value = &outarg; 759 req->out.args[0].value = &outarg;
742 request_send(fc, req); 760 request_send(fc, req);
743 err = req->out.h.error; 761 err = req->out.h.error;
@@ -1102,6 +1120,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1102 return PTR_ERR(req); 1120 return PTR_ERR(req);
1103 1121
1104 memset(&inarg, 0, sizeof(inarg)); 1122 memset(&inarg, 0, sizeof(inarg));
1123 memset(&outarg, 0, sizeof(outarg));
1105 iattr_to_fattr(attr, &inarg); 1124 iattr_to_fattr(attr, &inarg);
1106 if (file) { 1125 if (file) {
1107 struct fuse_file *ff = file->private_data; 1126 struct fuse_file *ff = file->private_data;
@@ -1119,7 +1138,10 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1119 req->in.args[0].size = sizeof(inarg); 1138 req->in.args[0].size = sizeof(inarg);
1120 req->in.args[0].value = &inarg; 1139 req->in.args[0].value = &inarg;
1121 req->out.numargs = 1; 1140 req->out.numargs = 1;
1122 req->out.args[0].size = sizeof(outarg); 1141 if (fc->minor < 9)
1142 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1143 else
1144 req->out.args[0].size = sizeof(outarg);
1123 req->out.args[0].value = &outarg; 1145 req->out.args[0].value = &outarg;
1124 request_send(fc, req); 1146 request_send(fc, req);
1125 err = req->out.h.error; 1147 err = req->out.h.error;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 49d716036ea7..9a68d6970845 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -148,6 +148,11 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
148 inode->i_ctime.tv_sec = attr->ctime; 148 inode->i_ctime.tv_sec = attr->ctime;
149 inode->i_ctime.tv_nsec = attr->ctimensec; 149 inode->i_ctime.tv_nsec = attr->ctimensec;
150 150
151 if (attr->blksize != 0)
152 inode->i_blkbits = ilog2(attr->blksize);
153 else
154 inode->i_blkbits = inode->i_sb->s_blocksize_bits;
155
151 /* 156 /*
152 * Don't set the sticky bit in i_mode, unless we want the VFS 157 * Don't set the sticky bit in i_mode, unless we want the VFS
153 * to check permissions. This prevents failures due to the 158 * to check permissions. This prevents failures due to the
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 7d4fa5b25b87..d0c437028c80 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -15,6 +15,7 @@
15 * - new fuse_getattr_in input argument of GETATTR 15 * - new fuse_getattr_in input argument of GETATTR
16 * - add lk_flags in fuse_lk_in 16 * - add lk_flags in fuse_lk_in
17 * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in 17 * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
18 * - add blksize field to fuse_attr
18 */ 19 */
19 20
20#include <asm/types.h> 21#include <asm/types.h>
@@ -53,6 +54,8 @@ struct fuse_attr {
53 __u32 uid; 54 __u32 uid;
54 __u32 gid; 55 __u32 gid;
55 __u32 rdev; 56 __u32 rdev;
57 __u32 blksize;
58 __u32 padding;
56}; 59};
57 60
58struct fuse_kstatfs { 61struct fuse_kstatfs {
@@ -177,6 +180,8 @@ enum fuse_opcode {
177/* The read buffer is required to be at least 8k, but may be much larger */ 180/* The read buffer is required to be at least 8k, but may be much larger */
178#define FUSE_MIN_READ_BUFFER 8192 181#define FUSE_MIN_READ_BUFFER 8192
179 182
183#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
184
180struct fuse_entry_out { 185struct fuse_entry_out {
181 __u64 nodeid; /* Inode ID */ 186 __u64 nodeid; /* Inode ID */
182 __u64 generation; /* Inode generation: nodeid:gen must 187 __u64 generation; /* Inode generation: nodeid:gen must
@@ -198,6 +203,8 @@ struct fuse_getattr_in {
198 __u64 fh; 203 __u64 fh;
199}; 204};
200 205
206#define FUSE_COMPAT_ATTR_OUT_SIZE 96
207
201struct fuse_attr_out { 208struct fuse_attr_out {
202 __u64 attr_valid; /* Cache timeout for the attributes */ 209 __u64 attr_valid; /* Cache timeout for the attributes */
203 __u32 attr_valid_nsec; 210 __u32 attr_valid_nsec;