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 /fs | |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/dir.c | 32 | ||||
-rw-r--r-- | fs/fuse/inode.c | 5 |
2 files changed, 32 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 |