diff options
| -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; |
