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/fuse | |
| 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/fuse')
| -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 |
