diff options
-rw-r--r-- | fs/fuse/dev.c | 48 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 6 | ||||
-rw-r--r-- | fs/fuse/inode.c | 1 | ||||
-rw-r--r-- | include/linux/fuse.h | 11 |
4 files changed, 41 insertions, 25 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 1afdffdf80db..e08ab4702d97 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -148,6 +148,26 @@ void fuse_release_background(struct fuse_req *req) | |||
148 | spin_unlock(&fuse_lock); | 148 | spin_unlock(&fuse_lock); |
149 | } | 149 | } |
150 | 150 | ||
151 | static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | ||
152 | { | ||
153 | int i; | ||
154 | struct fuse_init_out *arg = &req->misc.init_out; | ||
155 | |||
156 | if (arg->major != FUSE_KERNEL_VERSION) | ||
157 | fc->conn_error = 1; | ||
158 | else { | ||
159 | fc->minor = arg->minor; | ||
160 | fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; | ||
161 | } | ||
162 | |||
163 | /* After INIT reply is received other requests can go | ||
164 | out. So do (FUSE_MAX_OUTSTANDING - 1) number of | ||
165 | up()s on outstanding_sem. The last up() is done in | ||
166 | fuse_putback_request() */ | ||
167 | for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) | ||
168 | up(&fc->outstanding_sem); | ||
169 | } | ||
170 | |||
151 | /* | 171 | /* |
152 | * This function is called when a request is finished. Either a reply | 172 | * This function is called when a request is finished. Either a reply |
153 | * has arrived or it was interrupted (and not yet sent) or some error | 173 | * has arrived or it was interrupted (and not yet sent) or some error |
@@ -172,21 +192,9 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) | |||
172 | up_read(&fc->sbput_sem); | 192 | up_read(&fc->sbput_sem); |
173 | } | 193 | } |
174 | wake_up(&req->waitq); | 194 | wake_up(&req->waitq); |
175 | if (req->in.h.opcode == FUSE_INIT) { | 195 | if (req->in.h.opcode == FUSE_INIT) |
176 | int i; | 196 | process_init_reply(fc, req); |
177 | 197 | else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { | |
178 | if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION) | ||
179 | fc->conn_error = 1; | ||
180 | |||
181 | fc->minor = req->misc.init_in_out.minor; | ||
182 | |||
183 | /* After INIT reply is received other requests can go | ||
184 | out. So do (FUSE_MAX_OUTSTANDING - 1) number of | ||
185 | up()s on outstanding_sem. The last up() is done in | ||
186 | fuse_putback_request() */ | ||
187 | for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) | ||
188 | up(&fc->outstanding_sem); | ||
189 | } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { | ||
190 | /* Special case for failed iget in CREATE */ | 198 | /* Special case for failed iget in CREATE */ |
191 | u64 nodeid = req->in.h.nodeid; | 199 | u64 nodeid = req->in.h.nodeid; |
192 | __fuse_get_request(req); | 200 | __fuse_get_request(req); |
@@ -359,7 +367,7 @@ void fuse_send_init(struct fuse_conn *fc) | |||
359 | /* This is called from fuse_read_super() so there's guaranteed | 367 | /* This is called from fuse_read_super() so there's guaranteed |
360 | to be a request available */ | 368 | to be a request available */ |
361 | struct fuse_req *req = do_get_request(fc); | 369 | struct fuse_req *req = do_get_request(fc); |
362 | struct fuse_init_in_out *arg = &req->misc.init_in_out; | 370 | struct fuse_init_in *arg = &req->misc.init_in; |
363 | arg->major = FUSE_KERNEL_VERSION; | 371 | arg->major = FUSE_KERNEL_VERSION; |
364 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 372 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
365 | req->in.h.opcode = FUSE_INIT; | 373 | req->in.h.opcode = FUSE_INIT; |
@@ -367,8 +375,12 @@ void fuse_send_init(struct fuse_conn *fc) | |||
367 | req->in.args[0].size = sizeof(*arg); | 375 | req->in.args[0].size = sizeof(*arg); |
368 | req->in.args[0].value = arg; | 376 | req->in.args[0].value = arg; |
369 | req->out.numargs = 1; | 377 | req->out.numargs = 1; |
370 | req->out.args[0].size = sizeof(*arg); | 378 | /* Variable length arguement used for backward compatibility |
371 | req->out.args[0].value = arg; | 379 | with interface version < 7.5. Rest of init_out is zeroed |
380 | by do_get_request(), so a short reply is not a problem */ | ||
381 | req->out.argvar = 1; | ||
382 | req->out.args[0].size = sizeof(struct fuse_init_out); | ||
383 | req->out.args[0].value = &req->misc.init_out; | ||
372 | request_send_background(fc, req); | 384 | request_send_background(fc, req); |
373 | } | 385 | } |
374 | 386 | ||
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 17fd368559cd..74c8d098a14a 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -21,9 +21,6 @@ | |||
21 | /** If more requests are outstanding, then the operation will block */ | 21 | /** If more requests are outstanding, then the operation will block */ |
22 | #define FUSE_MAX_OUTSTANDING 10 | 22 | #define FUSE_MAX_OUTSTANDING 10 |
23 | 23 | ||
24 | /** Maximum size of data in a write request */ | ||
25 | #define FUSE_MAX_WRITE 4096 | ||
26 | |||
27 | /** It could be as large as PATH_MAX, but would that have any uses? */ | 24 | /** It could be as large as PATH_MAX, but would that have any uses? */ |
28 | #define FUSE_NAME_MAX 1024 | 25 | #define FUSE_NAME_MAX 1024 |
29 | 26 | ||
@@ -162,7 +159,8 @@ struct fuse_req { | |||
162 | union { | 159 | union { |
163 | struct fuse_forget_in forget_in; | 160 | struct fuse_forget_in forget_in; |
164 | struct fuse_release_in release_in; | 161 | struct fuse_release_in release_in; |
165 | struct fuse_init_in_out init_in_out; | 162 | struct fuse_init_in init_in; |
163 | struct fuse_init_out init_out; | ||
166 | } misc; | 164 | } misc; |
167 | 165 | ||
168 | /** page vector */ | 166 | /** page vector */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 3580b9e12345..e4541869831e 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -485,7 +485,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
485 | fc->max_read = d.max_read; | 485 | fc->max_read = d.max_read; |
486 | if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) | 486 | if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) |
487 | fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 487 | fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
488 | fc->max_write = FUSE_MAX_WRITE; | ||
489 | 488 | ||
490 | err = -ENOMEM; | 489 | err = -ENOMEM; |
491 | root = get_root_inode(sb, d.rootmode); | 490 | root = get_root_inode(sb, d.rootmode); |
diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 8f64cc2205b0..528959c52f1b 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #define FUSE_KERNEL_VERSION 7 | 14 | #define FUSE_KERNEL_VERSION 7 |
15 | 15 | ||
16 | /** Minor version number of this interface */ | 16 | /** Minor version number of this interface */ |
17 | #define FUSE_KERNEL_MINOR_VERSION 4 | 17 | #define FUSE_KERNEL_MINOR_VERSION 5 |
18 | 18 | ||
19 | /** The node ID of the root inode */ | 19 | /** The node ID of the root inode */ |
20 | #define FUSE_ROOT_ID 1 | 20 | #define FUSE_ROOT_ID 1 |
@@ -244,11 +244,18 @@ struct fuse_access_in { | |||
244 | __u32 padding; | 244 | __u32 padding; |
245 | }; | 245 | }; |
246 | 246 | ||
247 | struct fuse_init_in_out { | 247 | struct fuse_init_in { |
248 | __u32 major; | 248 | __u32 major; |
249 | __u32 minor; | 249 | __u32 minor; |
250 | }; | 250 | }; |
251 | 251 | ||
252 | struct fuse_init_out { | ||
253 | __u32 major; | ||
254 | __u32 minor; | ||
255 | __u32 unused[3]; | ||
256 | __u32 max_write; | ||
257 | }; | ||
258 | |||
252 | struct fuse_in_header { | 259 | struct fuse_in_header { |
253 | __u32 len; | 260 | __u32 len; |
254 | __u32 opcode; | 261 | __u32 opcode; |