diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2007-10-18 06:07:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-18 17:37:31 -0400 |
commit | 0e9663ee452ffce0d429656ebbcfe69417a30e92 (patch) | |
tree | a72825f122c9e38d4adc42ebcfd127f366da4a0f | |
parent | f33321141b273d60cbb3a8f56a5489baad82ba5e (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.c | 32 | ||||
-rw-r--r-- | fs/fuse/inode.c | 5 | ||||
-rw-r--r-- | include/linux/fuse.h | 7 |
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 | ||
58 | struct fuse_kstatfs { | 61 | struct 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 | |||
180 | struct fuse_entry_out { | 185 | struct 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 | |||
201 | struct fuse_attr_out { | 208 | struct 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; |