diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 12:41:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 12:41:32 -0500 |
commit | c103b21c20ee3d173ccccb7d5ca8f5b8bc02cac3 (patch) | |
tree | 9fed771f32b878b5bd16f2251052c5177820fcd2 /fs | |
parent | 603ba7e41bf5d405aba22294af5d075d8898176d (diff) | |
parent | 1c68271cf1bfe7f3664b6dbf4ffd5fe11130be5c (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse update from Miklos Szeredi:
"The first part makes sure we don't hold up umount with pending async
requests. In addition to being a cleanup, this is a small behavioral
change (for the better) and unlikely to break anything.
The second part prepares for a cleanup of the fuse device I/O code by
adding a helper for simple request submission, with some savings in
line numbers already realized"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
fuse: use file_inode() in fuse_file_fallocate()
fuse: introduce fuse_simple_request() helper
fuse: reduce max out args
fuse: hold inode instead of path after release
fuse: flush requests on umount
fuse: don't wake up reserved req in fuse_conn_kill()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/cuse.c | 2 | ||||
-rw-r--r-- | fs/fuse/dev.c | 29 | ||||
-rw-r--r-- | fs/fuse/dir.c | 538 | ||||
-rw-r--r-- | fs/fuse/file.c | 230 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 45 | ||||
-rw-r--r-- | fs/fuse/inode.c | 39 |
6 files changed, 359 insertions, 524 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 966ace8b243f..28d0c7abba1c 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
@@ -415,7 +415,7 @@ err_unlock: | |||
415 | err_region: | 415 | err_region: |
416 | unregister_chrdev_region(devt, 1); | 416 | unregister_chrdev_region(devt, 1); |
417 | err: | 417 | err: |
418 | fuse_conn_kill(fc); | 418 | fuse_abort_conn(fc); |
419 | goto out; | 419 | goto out; |
420 | } | 420 | } |
421 | 421 | ||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ca887314aba9..ba1107977f2e 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -511,6 +511,35 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | |||
511 | } | 511 | } |
512 | EXPORT_SYMBOL_GPL(fuse_request_send); | 512 | EXPORT_SYMBOL_GPL(fuse_request_send); |
513 | 513 | ||
514 | ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) | ||
515 | { | ||
516 | struct fuse_req *req; | ||
517 | ssize_t ret; | ||
518 | |||
519 | req = fuse_get_req(fc, 0); | ||
520 | if (IS_ERR(req)) | ||
521 | return PTR_ERR(req); | ||
522 | |||
523 | req->in.h.opcode = args->in.h.opcode; | ||
524 | req->in.h.nodeid = args->in.h.nodeid; | ||
525 | req->in.numargs = args->in.numargs; | ||
526 | memcpy(req->in.args, args->in.args, | ||
527 | args->in.numargs * sizeof(struct fuse_in_arg)); | ||
528 | req->out.argvar = args->out.argvar; | ||
529 | req->out.numargs = args->out.numargs; | ||
530 | memcpy(req->out.args, args->out.args, | ||
531 | args->out.numargs * sizeof(struct fuse_arg)); | ||
532 | fuse_request_send(fc, req); | ||
533 | ret = req->out.h.error; | ||
534 | if (!ret && args->out.argvar) { | ||
535 | BUG_ON(args->out.numargs != 1); | ||
536 | ret = req->out.args[0].size; | ||
537 | } | ||
538 | fuse_put_request(fc, req); | ||
539 | |||
540 | return ret; | ||
541 | } | ||
542 | |||
514 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | 543 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, |
515 | struct fuse_req *req) | 544 | struct fuse_req *req) |
516 | { | 545 | { |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index df562cc87763..252b8a5de8b5 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -145,22 +145,22 @@ static void fuse_invalidate_entry(struct dentry *entry) | |||
145 | fuse_invalidate_entry_cache(entry); | 145 | fuse_invalidate_entry_cache(entry); |
146 | } | 146 | } |
147 | 147 | ||
148 | static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req, | 148 | static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, |
149 | u64 nodeid, struct qstr *name, | 149 | u64 nodeid, struct qstr *name, |
150 | struct fuse_entry_out *outarg) | 150 | struct fuse_entry_out *outarg) |
151 | { | 151 | { |
152 | memset(outarg, 0, sizeof(struct fuse_entry_out)); | 152 | memset(outarg, 0, sizeof(struct fuse_entry_out)); |
153 | req->in.h.opcode = FUSE_LOOKUP; | 153 | args->in.h.opcode = FUSE_LOOKUP; |
154 | req->in.h.nodeid = nodeid; | 154 | args->in.h.nodeid = nodeid; |
155 | req->in.numargs = 1; | 155 | args->in.numargs = 1; |
156 | req->in.args[0].size = name->len + 1; | 156 | args->in.args[0].size = name->len + 1; |
157 | req->in.args[0].value = name->name; | 157 | args->in.args[0].value = name->name; |
158 | req->out.numargs = 1; | 158 | args->out.numargs = 1; |
159 | if (fc->minor < 9) | 159 | if (fc->minor < 9) |
160 | req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | 160 | args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; |
161 | else | 161 | else |
162 | req->out.args[0].size = sizeof(struct fuse_entry_out); | 162 | args->out.args[0].size = sizeof(struct fuse_entry_out); |
163 | req->out.args[0].value = outarg; | 163 | args->out.args[0].value = outarg; |
164 | } | 164 | } |
165 | 165 | ||
166 | u64 fuse_get_attr_version(struct fuse_conn *fc) | 166 | u64 fuse_get_attr_version(struct fuse_conn *fc) |
@@ -200,9 +200,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
200 | goto invalid; | 200 | goto invalid; |
201 | else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || | 201 | else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || |
202 | (flags & LOOKUP_REVAL)) { | 202 | (flags & LOOKUP_REVAL)) { |
203 | int err; | ||
204 | struct fuse_entry_out outarg; | 203 | struct fuse_entry_out outarg; |
205 | struct fuse_req *req; | 204 | FUSE_ARGS(args); |
206 | struct fuse_forget_link *forget; | 205 | struct fuse_forget_link *forget; |
207 | u64 attr_version; | 206 | u64 attr_version; |
208 | 207 | ||
@@ -215,31 +214,23 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
215 | goto out; | 214 | goto out; |
216 | 215 | ||
217 | fc = get_fuse_conn(inode); | 216 | fc = get_fuse_conn(inode); |
218 | req = fuse_get_req_nopages(fc); | ||
219 | ret = PTR_ERR(req); | ||
220 | if (IS_ERR(req)) | ||
221 | goto out; | ||
222 | 217 | ||
223 | forget = fuse_alloc_forget(); | 218 | forget = fuse_alloc_forget(); |
224 | if (!forget) { | 219 | ret = -ENOMEM; |
225 | fuse_put_request(fc, req); | 220 | if (!forget) |
226 | ret = -ENOMEM; | ||
227 | goto out; | 221 | goto out; |
228 | } | ||
229 | 222 | ||
230 | attr_version = fuse_get_attr_version(fc); | 223 | attr_version = fuse_get_attr_version(fc); |
231 | 224 | ||
232 | parent = dget_parent(entry); | 225 | parent = dget_parent(entry); |
233 | fuse_lookup_init(fc, req, get_node_id(parent->d_inode), | 226 | fuse_lookup_init(fc, &args, get_node_id(parent->d_inode), |
234 | &entry->d_name, &outarg); | 227 | &entry->d_name, &outarg); |
235 | fuse_request_send(fc, req); | 228 | ret = fuse_simple_request(fc, &args); |
236 | dput(parent); | 229 | dput(parent); |
237 | err = req->out.h.error; | ||
238 | fuse_put_request(fc, req); | ||
239 | /* Zero nodeid is same as -ENOENT */ | 230 | /* Zero nodeid is same as -ENOENT */ |
240 | if (!err && !outarg.nodeid) | 231 | if (!ret && !outarg.nodeid) |
241 | err = -ENOENT; | 232 | ret = -ENOENT; |
242 | if (!err) { | 233 | if (!ret) { |
243 | fi = get_fuse_inode(inode); | 234 | fi = get_fuse_inode(inode); |
244 | if (outarg.nodeid != get_node_id(inode)) { | 235 | if (outarg.nodeid != get_node_id(inode)) { |
245 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); | 236 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); |
@@ -250,7 +241,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
250 | spin_unlock(&fc->lock); | 241 | spin_unlock(&fc->lock); |
251 | } | 242 | } |
252 | kfree(forget); | 243 | kfree(forget); |
253 | if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) | 244 | if (ret == -ENOMEM) |
245 | goto out; | ||
246 | if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) | ||
254 | goto invalid; | 247 | goto invalid; |
255 | 248 | ||
256 | fuse_change_attributes(inode, &outarg.attr, | 249 | fuse_change_attributes(inode, &outarg.attr, |
@@ -296,7 +289,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
296 | struct fuse_entry_out *outarg, struct inode **inode) | 289 | struct fuse_entry_out *outarg, struct inode **inode) |
297 | { | 290 | { |
298 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 291 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
299 | struct fuse_req *req; | 292 | FUSE_ARGS(args); |
300 | struct fuse_forget_link *forget; | 293 | struct fuse_forget_link *forget; |
301 | u64 attr_version; | 294 | u64 attr_version; |
302 | int err; | 295 | int err; |
@@ -306,24 +299,16 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
306 | if (name->len > FUSE_NAME_MAX) | 299 | if (name->len > FUSE_NAME_MAX) |
307 | goto out; | 300 | goto out; |
308 | 301 | ||
309 | req = fuse_get_req_nopages(fc); | ||
310 | err = PTR_ERR(req); | ||
311 | if (IS_ERR(req)) | ||
312 | goto out; | ||
313 | 302 | ||
314 | forget = fuse_alloc_forget(); | 303 | forget = fuse_alloc_forget(); |
315 | err = -ENOMEM; | 304 | err = -ENOMEM; |
316 | if (!forget) { | 305 | if (!forget) |
317 | fuse_put_request(fc, req); | ||
318 | goto out; | 306 | goto out; |
319 | } | ||
320 | 307 | ||
321 | attr_version = fuse_get_attr_version(fc); | 308 | attr_version = fuse_get_attr_version(fc); |
322 | 309 | ||
323 | fuse_lookup_init(fc, req, nodeid, name, outarg); | 310 | fuse_lookup_init(fc, &args, nodeid, name, outarg); |
324 | fuse_request_send(fc, req); | 311 | err = fuse_simple_request(fc, &args); |
325 | err = req->out.h.error; | ||
326 | fuse_put_request(fc, req); | ||
327 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ | 312 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ |
328 | if (err || !outarg->nodeid) | 313 | if (err || !outarg->nodeid) |
329 | goto out_put_forget; | 314 | goto out_put_forget; |
@@ -405,7 +390,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
405 | int err; | 390 | int err; |
406 | struct inode *inode; | 391 | struct inode *inode; |
407 | struct fuse_conn *fc = get_fuse_conn(dir); | 392 | struct fuse_conn *fc = get_fuse_conn(dir); |
408 | struct fuse_req *req; | 393 | FUSE_ARGS(args); |
409 | struct fuse_forget_link *forget; | 394 | struct fuse_forget_link *forget; |
410 | struct fuse_create_in inarg; | 395 | struct fuse_create_in inarg; |
411 | struct fuse_open_out outopen; | 396 | struct fuse_open_out outopen; |
@@ -420,15 +405,10 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
420 | if (!forget) | 405 | if (!forget) |
421 | goto out_err; | 406 | goto out_err; |
422 | 407 | ||
423 | req = fuse_get_req_nopages(fc); | ||
424 | err = PTR_ERR(req); | ||
425 | if (IS_ERR(req)) | ||
426 | goto out_put_forget_req; | ||
427 | |||
428 | err = -ENOMEM; | 408 | err = -ENOMEM; |
429 | ff = fuse_file_alloc(fc); | 409 | ff = fuse_file_alloc(fc); |
430 | if (!ff) | 410 | if (!ff) |
431 | goto out_put_request; | 411 | goto out_put_forget_req; |
432 | 412 | ||
433 | if (!fc->dont_mask) | 413 | if (!fc->dont_mask) |
434 | mode &= ~current_umask(); | 414 | mode &= ~current_umask(); |
@@ -439,24 +419,23 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
439 | inarg.flags = flags; | 419 | inarg.flags = flags; |
440 | inarg.mode = mode; | 420 | inarg.mode = mode; |
441 | inarg.umask = current_umask(); | 421 | inarg.umask = current_umask(); |
442 | req->in.h.opcode = FUSE_CREATE; | 422 | args.in.h.opcode = FUSE_CREATE; |
443 | req->in.h.nodeid = get_node_id(dir); | 423 | args.in.h.nodeid = get_node_id(dir); |
444 | req->in.numargs = 2; | 424 | args.in.numargs = 2; |
445 | req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : | 425 | args.in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : |
446 | sizeof(inarg); | 426 | sizeof(inarg); |
447 | req->in.args[0].value = &inarg; | 427 | args.in.args[0].value = &inarg; |
448 | req->in.args[1].size = entry->d_name.len + 1; | 428 | args.in.args[1].size = entry->d_name.len + 1; |
449 | req->in.args[1].value = entry->d_name.name; | 429 | args.in.args[1].value = entry->d_name.name; |
450 | req->out.numargs = 2; | 430 | args.out.numargs = 2; |
451 | if (fc->minor < 9) | 431 | if (fc->minor < 9) |
452 | req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | 432 | args.out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; |
453 | else | 433 | else |
454 | req->out.args[0].size = sizeof(outentry); | 434 | args.out.args[0].size = sizeof(outentry); |
455 | req->out.args[0].value = &outentry; | 435 | args.out.args[0].value = &outentry; |
456 | req->out.args[1].size = sizeof(outopen); | 436 | args.out.args[1].size = sizeof(outopen); |
457 | req->out.args[1].value = &outopen; | 437 | args.out.args[1].value = &outopen; |
458 | fuse_request_send(fc, req); | 438 | err = fuse_simple_request(fc, &args); |
459 | err = req->out.h.error; | ||
460 | if (err) | 439 | if (err) |
461 | goto out_free_ff; | 440 | goto out_free_ff; |
462 | 441 | ||
@@ -464,7 +443,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
464 | if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) | 443 | if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) |
465 | goto out_free_ff; | 444 | goto out_free_ff; |
466 | 445 | ||
467 | fuse_put_request(fc, req); | ||
468 | ff->fh = outopen.fh; | 446 | ff->fh = outopen.fh; |
469 | ff->nodeid = outentry.nodeid; | 447 | ff->nodeid = outentry.nodeid; |
470 | ff->open_flags = outopen.open_flags; | 448 | ff->open_flags = outopen.open_flags; |
@@ -492,8 +470,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
492 | 470 | ||
493 | out_free_ff: | 471 | out_free_ff: |
494 | fuse_file_free(ff); | 472 | fuse_file_free(ff); |
495 | out_put_request: | ||
496 | fuse_put_request(fc, req); | ||
497 | out_put_forget_req: | 473 | out_put_forget_req: |
498 | kfree(forget); | 474 | kfree(forget); |
499 | out_err: | 475 | out_err: |
@@ -547,7 +523,7 @@ no_open: | |||
547 | /* | 523 | /* |
548 | * Code shared between mknod, mkdir, symlink and link | 524 | * Code shared between mknod, mkdir, symlink and link |
549 | */ | 525 | */ |
550 | static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | 526 | static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, |
551 | struct inode *dir, struct dentry *entry, | 527 | struct inode *dir, struct dentry *entry, |
552 | umode_t mode) | 528 | umode_t mode) |
553 | { | 529 | { |
@@ -557,22 +533,18 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
557 | struct fuse_forget_link *forget; | 533 | struct fuse_forget_link *forget; |
558 | 534 | ||
559 | forget = fuse_alloc_forget(); | 535 | forget = fuse_alloc_forget(); |
560 | if (!forget) { | 536 | if (!forget) |
561 | fuse_put_request(fc, req); | ||
562 | return -ENOMEM; | 537 | return -ENOMEM; |
563 | } | ||
564 | 538 | ||
565 | memset(&outarg, 0, sizeof(outarg)); | 539 | memset(&outarg, 0, sizeof(outarg)); |
566 | req->in.h.nodeid = get_node_id(dir); | 540 | args->in.h.nodeid = get_node_id(dir); |
567 | req->out.numargs = 1; | 541 | args->out.numargs = 1; |
568 | if (fc->minor < 9) | 542 | if (fc->minor < 9) |
569 | req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | 543 | args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; |
570 | else | 544 | else |
571 | req->out.args[0].size = sizeof(outarg); | 545 | args->out.args[0].size = sizeof(outarg); |
572 | req->out.args[0].value = &outarg; | 546 | args->out.args[0].value = &outarg; |
573 | fuse_request_send(fc, req); | 547 | err = fuse_simple_request(fc, args); |
574 | err = req->out.h.error; | ||
575 | fuse_put_request(fc, req); | ||
576 | if (err) | 548 | if (err) |
577 | goto out_put_forget_req; | 549 | goto out_put_forget_req; |
578 | 550 | ||
@@ -609,9 +581,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, | |||
609 | { | 581 | { |
610 | struct fuse_mknod_in inarg; | 582 | struct fuse_mknod_in inarg; |
611 | struct fuse_conn *fc = get_fuse_conn(dir); | 583 | struct fuse_conn *fc = get_fuse_conn(dir); |
612 | struct fuse_req *req = fuse_get_req_nopages(fc); | 584 | FUSE_ARGS(args); |
613 | if (IS_ERR(req)) | ||
614 | return PTR_ERR(req); | ||
615 | 585 | ||
616 | if (!fc->dont_mask) | 586 | if (!fc->dont_mask) |
617 | mode &= ~current_umask(); | 587 | mode &= ~current_umask(); |
@@ -620,14 +590,14 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, | |||
620 | inarg.mode = mode; | 590 | inarg.mode = mode; |
621 | inarg.rdev = new_encode_dev(rdev); | 591 | inarg.rdev = new_encode_dev(rdev); |
622 | inarg.umask = current_umask(); | 592 | inarg.umask = current_umask(); |
623 | req->in.h.opcode = FUSE_MKNOD; | 593 | args.in.h.opcode = FUSE_MKNOD; |
624 | req->in.numargs = 2; | 594 | args.in.numargs = 2; |
625 | req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : | 595 | args.in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : |
626 | sizeof(inarg); | 596 | sizeof(inarg); |
627 | req->in.args[0].value = &inarg; | 597 | args.in.args[0].value = &inarg; |
628 | req->in.args[1].size = entry->d_name.len + 1; | 598 | args.in.args[1].size = entry->d_name.len + 1; |
629 | req->in.args[1].value = entry->d_name.name; | 599 | args.in.args[1].value = entry->d_name.name; |
630 | return create_new_entry(fc, req, dir, entry, mode); | 600 | return create_new_entry(fc, &args, dir, entry, mode); |
631 | } | 601 | } |
632 | 602 | ||
633 | static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, | 603 | static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, |
@@ -640,9 +610,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) | |||
640 | { | 610 | { |
641 | struct fuse_mkdir_in inarg; | 611 | struct fuse_mkdir_in inarg; |
642 | struct fuse_conn *fc = get_fuse_conn(dir); | 612 | struct fuse_conn *fc = get_fuse_conn(dir); |
643 | struct fuse_req *req = fuse_get_req_nopages(fc); | 613 | FUSE_ARGS(args); |
644 | if (IS_ERR(req)) | ||
645 | return PTR_ERR(req); | ||
646 | 614 | ||
647 | if (!fc->dont_mask) | 615 | if (!fc->dont_mask) |
648 | mode &= ~current_umask(); | 616 | mode &= ~current_umask(); |
@@ -650,13 +618,13 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) | |||
650 | memset(&inarg, 0, sizeof(inarg)); | 618 | memset(&inarg, 0, sizeof(inarg)); |
651 | inarg.mode = mode; | 619 | inarg.mode = mode; |
652 | inarg.umask = current_umask(); | 620 | inarg.umask = current_umask(); |
653 | req->in.h.opcode = FUSE_MKDIR; | 621 | args.in.h.opcode = FUSE_MKDIR; |
654 | req->in.numargs = 2; | 622 | args.in.numargs = 2; |
655 | req->in.args[0].size = sizeof(inarg); | 623 | args.in.args[0].size = sizeof(inarg); |
656 | req->in.args[0].value = &inarg; | 624 | args.in.args[0].value = &inarg; |
657 | req->in.args[1].size = entry->d_name.len + 1; | 625 | args.in.args[1].size = entry->d_name.len + 1; |
658 | req->in.args[1].value = entry->d_name.name; | 626 | args.in.args[1].value = entry->d_name.name; |
659 | return create_new_entry(fc, req, dir, entry, S_IFDIR); | 627 | return create_new_entry(fc, &args, dir, entry, S_IFDIR); |
660 | } | 628 | } |
661 | 629 | ||
662 | static int fuse_symlink(struct inode *dir, struct dentry *entry, | 630 | static int fuse_symlink(struct inode *dir, struct dentry *entry, |
@@ -664,17 +632,15 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, | |||
664 | { | 632 | { |
665 | struct fuse_conn *fc = get_fuse_conn(dir); | 633 | struct fuse_conn *fc = get_fuse_conn(dir); |
666 | unsigned len = strlen(link) + 1; | 634 | unsigned len = strlen(link) + 1; |
667 | struct fuse_req *req = fuse_get_req_nopages(fc); | 635 | FUSE_ARGS(args); |
668 | if (IS_ERR(req)) | ||
669 | return PTR_ERR(req); | ||
670 | 636 | ||
671 | req->in.h.opcode = FUSE_SYMLINK; | 637 | args.in.h.opcode = FUSE_SYMLINK; |
672 | req->in.numargs = 2; | 638 | args.in.numargs = 2; |
673 | req->in.args[0].size = entry->d_name.len + 1; | 639 | args.in.args[0].size = entry->d_name.len + 1; |
674 | req->in.args[0].value = entry->d_name.name; | 640 | args.in.args[0].value = entry->d_name.name; |
675 | req->in.args[1].size = len; | 641 | args.in.args[1].size = len; |
676 | req->in.args[1].value = link; | 642 | args.in.args[1].value = link; |
677 | return create_new_entry(fc, req, dir, entry, S_IFLNK); | 643 | return create_new_entry(fc, &args, dir, entry, S_IFLNK); |
678 | } | 644 | } |
679 | 645 | ||
680 | static inline void fuse_update_ctime(struct inode *inode) | 646 | static inline void fuse_update_ctime(struct inode *inode) |
@@ -689,18 +655,14 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
689 | { | 655 | { |
690 | int err; | 656 | int err; |
691 | struct fuse_conn *fc = get_fuse_conn(dir); | 657 | struct fuse_conn *fc = get_fuse_conn(dir); |
692 | struct fuse_req *req = fuse_get_req_nopages(fc); | 658 | FUSE_ARGS(args); |
693 | if (IS_ERR(req)) | 659 | |
694 | return PTR_ERR(req); | 660 | args.in.h.opcode = FUSE_UNLINK; |
695 | 661 | args.in.h.nodeid = get_node_id(dir); | |
696 | req->in.h.opcode = FUSE_UNLINK; | 662 | args.in.numargs = 1; |
697 | req->in.h.nodeid = get_node_id(dir); | 663 | args.in.args[0].size = entry->d_name.len + 1; |
698 | req->in.numargs = 1; | 664 | args.in.args[0].value = entry->d_name.name; |
699 | req->in.args[0].size = entry->d_name.len + 1; | 665 | err = fuse_simple_request(fc, &args); |
700 | req->in.args[0].value = entry->d_name.name; | ||
701 | fuse_request_send(fc, req); | ||
702 | err = req->out.h.error; | ||
703 | fuse_put_request(fc, req); | ||
704 | if (!err) { | 666 | if (!err) { |
705 | struct inode *inode = entry->d_inode; | 667 | struct inode *inode = entry->d_inode; |
706 | struct fuse_inode *fi = get_fuse_inode(inode); | 668 | struct fuse_inode *fi = get_fuse_inode(inode); |
@@ -729,18 +691,14 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) | |||
729 | { | 691 | { |
730 | int err; | 692 | int err; |
731 | struct fuse_conn *fc = get_fuse_conn(dir); | 693 | struct fuse_conn *fc = get_fuse_conn(dir); |
732 | struct fuse_req *req = fuse_get_req_nopages(fc); | 694 | FUSE_ARGS(args); |
733 | if (IS_ERR(req)) | 695 | |
734 | return PTR_ERR(req); | 696 | args.in.h.opcode = FUSE_RMDIR; |
735 | 697 | args.in.h.nodeid = get_node_id(dir); | |
736 | req->in.h.opcode = FUSE_RMDIR; | 698 | args.in.numargs = 1; |
737 | req->in.h.nodeid = get_node_id(dir); | 699 | args.in.args[0].size = entry->d_name.len + 1; |
738 | req->in.numargs = 1; | 700 | args.in.args[0].value = entry->d_name.name; |
739 | req->in.args[0].size = entry->d_name.len + 1; | 701 | err = fuse_simple_request(fc, &args); |
740 | req->in.args[0].value = entry->d_name.name; | ||
741 | fuse_request_send(fc, req); | ||
742 | err = req->out.h.error; | ||
743 | fuse_put_request(fc, req); | ||
744 | if (!err) { | 702 | if (!err) { |
745 | clear_nlink(entry->d_inode); | 703 | clear_nlink(entry->d_inode); |
746 | fuse_invalidate_attr(dir); | 704 | fuse_invalidate_attr(dir); |
@@ -757,27 +715,21 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, | |||
757 | int err; | 715 | int err; |
758 | struct fuse_rename2_in inarg; | 716 | struct fuse_rename2_in inarg; |
759 | struct fuse_conn *fc = get_fuse_conn(olddir); | 717 | struct fuse_conn *fc = get_fuse_conn(olddir); |
760 | struct fuse_req *req; | 718 | FUSE_ARGS(args); |
761 | |||
762 | req = fuse_get_req_nopages(fc); | ||
763 | if (IS_ERR(req)) | ||
764 | return PTR_ERR(req); | ||
765 | 719 | ||
766 | memset(&inarg, 0, argsize); | 720 | memset(&inarg, 0, argsize); |
767 | inarg.newdir = get_node_id(newdir); | 721 | inarg.newdir = get_node_id(newdir); |
768 | inarg.flags = flags; | 722 | inarg.flags = flags; |
769 | req->in.h.opcode = opcode; | 723 | args.in.h.opcode = opcode; |
770 | req->in.h.nodeid = get_node_id(olddir); | 724 | args.in.h.nodeid = get_node_id(olddir); |
771 | req->in.numargs = 3; | 725 | args.in.numargs = 3; |
772 | req->in.args[0].size = argsize; | 726 | args.in.args[0].size = argsize; |
773 | req->in.args[0].value = &inarg; | 727 | args.in.args[0].value = &inarg; |
774 | req->in.args[1].size = oldent->d_name.len + 1; | 728 | args.in.args[1].size = oldent->d_name.len + 1; |
775 | req->in.args[1].value = oldent->d_name.name; | 729 | args.in.args[1].value = oldent->d_name.name; |
776 | req->in.args[2].size = newent->d_name.len + 1; | 730 | args.in.args[2].size = newent->d_name.len + 1; |
777 | req->in.args[2].value = newent->d_name.name; | 731 | args.in.args[2].value = newent->d_name.name; |
778 | fuse_request_send(fc, req); | 732 | err = fuse_simple_request(fc, &args); |
779 | err = req->out.h.error; | ||
780 | fuse_put_request(fc, req); | ||
781 | if (!err) { | 733 | if (!err) { |
782 | /* ctime changes */ | 734 | /* ctime changes */ |
783 | fuse_invalidate_attr(oldent->d_inode); | 735 | fuse_invalidate_attr(oldent->d_inode); |
@@ -849,19 +801,17 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, | |||
849 | struct fuse_link_in inarg; | 801 | struct fuse_link_in inarg; |
850 | struct inode *inode = entry->d_inode; | 802 | struct inode *inode = entry->d_inode; |
851 | struct fuse_conn *fc = get_fuse_conn(inode); | 803 | struct fuse_conn *fc = get_fuse_conn(inode); |
852 | struct fuse_req *req = fuse_get_req_nopages(fc); | 804 | FUSE_ARGS(args); |
853 | if (IS_ERR(req)) | ||
854 | return PTR_ERR(req); | ||
855 | 805 | ||
856 | memset(&inarg, 0, sizeof(inarg)); | 806 | memset(&inarg, 0, sizeof(inarg)); |
857 | inarg.oldnodeid = get_node_id(inode); | 807 | inarg.oldnodeid = get_node_id(inode); |
858 | req->in.h.opcode = FUSE_LINK; | 808 | args.in.h.opcode = FUSE_LINK; |
859 | req->in.numargs = 2; | 809 | args.in.numargs = 2; |
860 | req->in.args[0].size = sizeof(inarg); | 810 | args.in.args[0].size = sizeof(inarg); |
861 | req->in.args[0].value = &inarg; | 811 | args.in.args[0].value = &inarg; |
862 | req->in.args[1].size = newent->d_name.len + 1; | 812 | args.in.args[1].size = newent->d_name.len + 1; |
863 | req->in.args[1].value = newent->d_name.name; | 813 | args.in.args[1].value = newent->d_name.name; |
864 | err = create_new_entry(fc, req, newdir, newent, inode->i_mode); | 814 | err = create_new_entry(fc, &args, newdir, newent, inode->i_mode); |
865 | /* Contrary to "normal" filesystems it can happen that link | 815 | /* Contrary to "normal" filesystems it can happen that link |
866 | makes two "logical" inodes point to the same "physical" | 816 | makes two "logical" inodes point to the same "physical" |
867 | inode. We invalidate the attributes of the old one, so it | 817 | inode. We invalidate the attributes of the old one, so it |
@@ -929,13 +879,9 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
929 | struct fuse_getattr_in inarg; | 879 | struct fuse_getattr_in inarg; |
930 | struct fuse_attr_out outarg; | 880 | struct fuse_attr_out outarg; |
931 | struct fuse_conn *fc = get_fuse_conn(inode); | 881 | struct fuse_conn *fc = get_fuse_conn(inode); |
932 | struct fuse_req *req; | 882 | FUSE_ARGS(args); |
933 | u64 attr_version; | 883 | u64 attr_version; |
934 | 884 | ||
935 | req = fuse_get_req_nopages(fc); | ||
936 | if (IS_ERR(req)) | ||
937 | return PTR_ERR(req); | ||
938 | |||
939 | attr_version = fuse_get_attr_version(fc); | 885 | attr_version = fuse_get_attr_version(fc); |
940 | 886 | ||
941 | memset(&inarg, 0, sizeof(inarg)); | 887 | memset(&inarg, 0, sizeof(inarg)); |
@@ -947,20 +893,18 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
947 | inarg.getattr_flags |= FUSE_GETATTR_FH; | 893 | inarg.getattr_flags |= FUSE_GETATTR_FH; |
948 | inarg.fh = ff->fh; | 894 | inarg.fh = ff->fh; |
949 | } | 895 | } |
950 | req->in.h.opcode = FUSE_GETATTR; | 896 | args.in.h.opcode = FUSE_GETATTR; |
951 | req->in.h.nodeid = get_node_id(inode); | 897 | args.in.h.nodeid = get_node_id(inode); |
952 | req->in.numargs = 1; | 898 | args.in.numargs = 1; |
953 | req->in.args[0].size = sizeof(inarg); | 899 | args.in.args[0].size = sizeof(inarg); |
954 | req->in.args[0].value = &inarg; | 900 | args.in.args[0].value = &inarg; |
955 | req->out.numargs = 1; | 901 | args.out.numargs = 1; |
956 | if (fc->minor < 9) | 902 | if (fc->minor < 9) |
957 | req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; | 903 | args.out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; |
958 | else | 904 | else |
959 | req->out.args[0].size = sizeof(outarg); | 905 | args.out.args[0].size = sizeof(outarg); |
960 | req->out.args[0].value = &outarg; | 906 | args.out.args[0].value = &outarg; |
961 | fuse_request_send(fc, req); | 907 | err = fuse_simple_request(fc, &args); |
962 | err = req->out.h.error; | ||
963 | fuse_put_request(fc, req); | ||
964 | if (!err) { | 908 | if (!err) { |
965 | if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { | 909 | if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { |
966 | make_bad_inode(inode); | 910 | make_bad_inode(inode); |
@@ -1102,7 +1046,7 @@ int fuse_allow_current_process(struct fuse_conn *fc) | |||
1102 | static int fuse_access(struct inode *inode, int mask) | 1046 | static int fuse_access(struct inode *inode, int mask) |
1103 | { | 1047 | { |
1104 | struct fuse_conn *fc = get_fuse_conn(inode); | 1048 | struct fuse_conn *fc = get_fuse_conn(inode); |
1105 | struct fuse_req *req; | 1049 | FUSE_ARGS(args); |
1106 | struct fuse_access_in inarg; | 1050 | struct fuse_access_in inarg; |
1107 | int err; | 1051 | int err; |
1108 | 1052 | ||
@@ -1111,20 +1055,14 @@ static int fuse_access(struct inode *inode, int mask) | |||
1111 | if (fc->no_access) | 1055 | if (fc->no_access) |
1112 | return 0; | 1056 | return 0; |
1113 | 1057 | ||
1114 | req = fuse_get_req_nopages(fc); | ||
1115 | if (IS_ERR(req)) | ||
1116 | return PTR_ERR(req); | ||
1117 | |||
1118 | memset(&inarg, 0, sizeof(inarg)); | 1058 | memset(&inarg, 0, sizeof(inarg)); |
1119 | inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); | 1059 | inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); |
1120 | req->in.h.opcode = FUSE_ACCESS; | 1060 | args.in.h.opcode = FUSE_ACCESS; |
1121 | req->in.h.nodeid = get_node_id(inode); | 1061 | args.in.h.nodeid = get_node_id(inode); |
1122 | req->in.numargs = 1; | 1062 | args.in.numargs = 1; |
1123 | req->in.args[0].size = sizeof(inarg); | 1063 | args.in.args[0].size = sizeof(inarg); |
1124 | req->in.args[0].value = &inarg; | 1064 | args.in.args[0].value = &inarg; |
1125 | fuse_request_send(fc, req); | 1065 | err = fuse_simple_request(fc, &args); |
1126 | err = req->out.h.error; | ||
1127 | fuse_put_request(fc, req); | ||
1128 | if (err == -ENOSYS) { | 1066 | if (err == -ENOSYS) { |
1129 | fc->no_access = 1; | 1067 | fc->no_access = 1; |
1130 | err = 0; | 1068 | err = 0; |
@@ -1445,31 +1383,27 @@ static char *read_link(struct dentry *dentry) | |||
1445 | { | 1383 | { |
1446 | struct inode *inode = dentry->d_inode; | 1384 | struct inode *inode = dentry->d_inode; |
1447 | struct fuse_conn *fc = get_fuse_conn(inode); | 1385 | struct fuse_conn *fc = get_fuse_conn(inode); |
1448 | struct fuse_req *req = fuse_get_req_nopages(fc); | 1386 | FUSE_ARGS(args); |
1449 | char *link; | 1387 | char *link; |
1450 | 1388 | ssize_t ret; | |
1451 | if (IS_ERR(req)) | ||
1452 | return ERR_CAST(req); | ||
1453 | 1389 | ||
1454 | link = (char *) __get_free_page(GFP_KERNEL); | 1390 | link = (char *) __get_free_page(GFP_KERNEL); |
1455 | if (!link) { | 1391 | if (!link) |
1456 | link = ERR_PTR(-ENOMEM); | 1392 | return ERR_PTR(-ENOMEM); |
1457 | goto out; | 1393 | |
1458 | } | 1394 | args.in.h.opcode = FUSE_READLINK; |
1459 | req->in.h.opcode = FUSE_READLINK; | 1395 | args.in.h.nodeid = get_node_id(inode); |
1460 | req->in.h.nodeid = get_node_id(inode); | 1396 | args.out.argvar = 1; |
1461 | req->out.argvar = 1; | 1397 | args.out.numargs = 1; |
1462 | req->out.numargs = 1; | 1398 | args.out.args[0].size = PAGE_SIZE - 1; |
1463 | req->out.args[0].size = PAGE_SIZE - 1; | 1399 | args.out.args[0].value = link; |
1464 | req->out.args[0].value = link; | 1400 | ret = fuse_simple_request(fc, &args); |
1465 | fuse_request_send(fc, req); | 1401 | if (ret < 0) { |
1466 | if (req->out.h.error) { | ||
1467 | free_page((unsigned long) link); | 1402 | free_page((unsigned long) link); |
1468 | link = ERR_PTR(req->out.h.error); | 1403 | link = ERR_PTR(ret); |
1469 | } else | 1404 | } else { |
1470 | link[req->out.args[0].size] = '\0'; | 1405 | link[ret] = '\0'; |
1471 | out: | 1406 | } |
1472 | fuse_put_request(fc, req); | ||
1473 | fuse_invalidate_atime(inode); | 1407 | fuse_invalidate_atime(inode); |
1474 | return link; | 1408 | return link; |
1475 | } | 1409 | } |
@@ -1629,22 +1563,22 @@ void fuse_release_nowrite(struct inode *inode) | |||
1629 | spin_unlock(&fc->lock); | 1563 | spin_unlock(&fc->lock); |
1630 | } | 1564 | } |
1631 | 1565 | ||
1632 | static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req, | 1566 | static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, |
1633 | struct inode *inode, | 1567 | struct inode *inode, |
1634 | struct fuse_setattr_in *inarg_p, | 1568 | struct fuse_setattr_in *inarg_p, |
1635 | struct fuse_attr_out *outarg_p) | 1569 | struct fuse_attr_out *outarg_p) |
1636 | { | 1570 | { |
1637 | req->in.h.opcode = FUSE_SETATTR; | 1571 | args->in.h.opcode = FUSE_SETATTR; |
1638 | req->in.h.nodeid = get_node_id(inode); | 1572 | args->in.h.nodeid = get_node_id(inode); |
1639 | req->in.numargs = 1; | 1573 | args->in.numargs = 1; |
1640 | req->in.args[0].size = sizeof(*inarg_p); | 1574 | args->in.args[0].size = sizeof(*inarg_p); |
1641 | req->in.args[0].value = inarg_p; | 1575 | args->in.args[0].value = inarg_p; |
1642 | req->out.numargs = 1; | 1576 | args->out.numargs = 1; |
1643 | if (fc->minor < 9) | 1577 | if (fc->minor < 9) |
1644 | req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; | 1578 | args->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; |
1645 | else | 1579 | else |
1646 | req->out.args[0].size = sizeof(*outarg_p); | 1580 | args->out.args[0].size = sizeof(*outarg_p); |
1647 | req->out.args[0].value = outarg_p; | 1581 | args->out.args[0].value = outarg_p; |
1648 | } | 1582 | } |
1649 | 1583 | ||
1650 | /* | 1584 | /* |
@@ -1653,14 +1587,9 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req, | |||
1653 | int fuse_flush_times(struct inode *inode, struct fuse_file *ff) | 1587 | int fuse_flush_times(struct inode *inode, struct fuse_file *ff) |
1654 | { | 1588 | { |
1655 | struct fuse_conn *fc = get_fuse_conn(inode); | 1589 | struct fuse_conn *fc = get_fuse_conn(inode); |
1656 | struct fuse_req *req; | 1590 | FUSE_ARGS(args); |
1657 | struct fuse_setattr_in inarg; | 1591 | struct fuse_setattr_in inarg; |
1658 | struct fuse_attr_out outarg; | 1592 | struct fuse_attr_out outarg; |
1659 | int err; | ||
1660 | |||
1661 | req = fuse_get_req_nopages(fc); | ||
1662 | if (IS_ERR(req)) | ||
1663 | return PTR_ERR(req); | ||
1664 | 1593 | ||
1665 | memset(&inarg, 0, sizeof(inarg)); | 1594 | memset(&inarg, 0, sizeof(inarg)); |
1666 | memset(&outarg, 0, sizeof(outarg)); | 1595 | memset(&outarg, 0, sizeof(outarg)); |
@@ -1677,12 +1606,9 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff) | |||
1677 | inarg.valid |= FATTR_FH; | 1606 | inarg.valid |= FATTR_FH; |
1678 | inarg.fh = ff->fh; | 1607 | inarg.fh = ff->fh; |
1679 | } | 1608 | } |
1680 | fuse_setattr_fill(fc, req, inode, &inarg, &outarg); | 1609 | fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); |
1681 | fuse_request_send(fc, req); | ||
1682 | err = req->out.h.error; | ||
1683 | fuse_put_request(fc, req); | ||
1684 | 1610 | ||
1685 | return err; | 1611 | return fuse_simple_request(fc, &args); |
1686 | } | 1612 | } |
1687 | 1613 | ||
1688 | /* | 1614 | /* |
@@ -1698,7 +1624,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1698 | { | 1624 | { |
1699 | struct fuse_conn *fc = get_fuse_conn(inode); | 1625 | struct fuse_conn *fc = get_fuse_conn(inode); |
1700 | struct fuse_inode *fi = get_fuse_inode(inode); | 1626 | struct fuse_inode *fi = get_fuse_inode(inode); |
1701 | struct fuse_req *req; | 1627 | FUSE_ARGS(args); |
1702 | struct fuse_setattr_in inarg; | 1628 | struct fuse_setattr_in inarg; |
1703 | struct fuse_attr_out outarg; | 1629 | struct fuse_attr_out outarg; |
1704 | bool is_truncate = false; | 1630 | bool is_truncate = false; |
@@ -1723,10 +1649,6 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1723 | if (attr->ia_valid & ATTR_SIZE) | 1649 | if (attr->ia_valid & ATTR_SIZE) |
1724 | is_truncate = true; | 1650 | is_truncate = true; |
1725 | 1651 | ||
1726 | req = fuse_get_req_nopages(fc); | ||
1727 | if (IS_ERR(req)) | ||
1728 | return PTR_ERR(req); | ||
1729 | |||
1730 | if (is_truncate) { | 1652 | if (is_truncate) { |
1731 | fuse_set_nowrite(inode); | 1653 | fuse_set_nowrite(inode); |
1732 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); | 1654 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); |
@@ -1747,10 +1669,8 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1747 | inarg.valid |= FATTR_LOCKOWNER; | 1669 | inarg.valid |= FATTR_LOCKOWNER; |
1748 | inarg.lock_owner = fuse_lock_owner_id(fc, current->files); | 1670 | inarg.lock_owner = fuse_lock_owner_id(fc, current->files); |
1749 | } | 1671 | } |
1750 | fuse_setattr_fill(fc, req, inode, &inarg, &outarg); | 1672 | fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); |
1751 | fuse_request_send(fc, req); | 1673 | err = fuse_simple_request(fc, &args); |
1752 | err = req->out.h.error; | ||
1753 | fuse_put_request(fc, req); | ||
1754 | if (err) { | 1674 | if (err) { |
1755 | if (err == -EINTR) | 1675 | if (err == -EINTR) |
1756 | fuse_invalidate_attr(inode); | 1676 | fuse_invalidate_attr(inode); |
@@ -1837,32 +1757,26 @@ static int fuse_setxattr(struct dentry *entry, const char *name, | |||
1837 | { | 1757 | { |
1838 | struct inode *inode = entry->d_inode; | 1758 | struct inode *inode = entry->d_inode; |
1839 | struct fuse_conn *fc = get_fuse_conn(inode); | 1759 | struct fuse_conn *fc = get_fuse_conn(inode); |
1840 | struct fuse_req *req; | 1760 | FUSE_ARGS(args); |
1841 | struct fuse_setxattr_in inarg; | 1761 | struct fuse_setxattr_in inarg; |
1842 | int err; | 1762 | int err; |
1843 | 1763 | ||
1844 | if (fc->no_setxattr) | 1764 | if (fc->no_setxattr) |
1845 | return -EOPNOTSUPP; | 1765 | return -EOPNOTSUPP; |
1846 | 1766 | ||
1847 | req = fuse_get_req_nopages(fc); | ||
1848 | if (IS_ERR(req)) | ||
1849 | return PTR_ERR(req); | ||
1850 | |||
1851 | memset(&inarg, 0, sizeof(inarg)); | 1767 | memset(&inarg, 0, sizeof(inarg)); |
1852 | inarg.size = size; | 1768 | inarg.size = size; |
1853 | inarg.flags = flags; | 1769 | inarg.flags = flags; |
1854 | req->in.h.opcode = FUSE_SETXATTR; | 1770 | args.in.h.opcode = FUSE_SETXATTR; |
1855 | req->in.h.nodeid = get_node_id(inode); | 1771 | args.in.h.nodeid = get_node_id(inode); |
1856 | req->in.numargs = 3; | 1772 | args.in.numargs = 3; |
1857 | req->in.args[0].size = sizeof(inarg); | 1773 | args.in.args[0].size = sizeof(inarg); |
1858 | req->in.args[0].value = &inarg; | 1774 | args.in.args[0].value = &inarg; |
1859 | req->in.args[1].size = strlen(name) + 1; | 1775 | args.in.args[1].size = strlen(name) + 1; |
1860 | req->in.args[1].value = name; | 1776 | args.in.args[1].value = name; |
1861 | req->in.args[2].size = size; | 1777 | args.in.args[2].size = size; |
1862 | req->in.args[2].value = value; | 1778 | args.in.args[2].value = value; |
1863 | fuse_request_send(fc, req); | 1779 | err = fuse_simple_request(fc, &args); |
1864 | err = req->out.h.error; | ||
1865 | fuse_put_request(fc, req); | ||
1866 | if (err == -ENOSYS) { | 1780 | if (err == -ENOSYS) { |
1867 | fc->no_setxattr = 1; | 1781 | fc->no_setxattr = 1; |
1868 | err = -EOPNOTSUPP; | 1782 | err = -EOPNOTSUPP; |
@@ -1879,7 +1793,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, | |||
1879 | { | 1793 | { |
1880 | struct inode *inode = entry->d_inode; | 1794 | struct inode *inode = entry->d_inode; |
1881 | struct fuse_conn *fc = get_fuse_conn(inode); | 1795 | struct fuse_conn *fc = get_fuse_conn(inode); |
1882 | struct fuse_req *req; | 1796 | FUSE_ARGS(args); |
1883 | struct fuse_getxattr_in inarg; | 1797 | struct fuse_getxattr_in inarg; |
1884 | struct fuse_getxattr_out outarg; | 1798 | struct fuse_getxattr_out outarg; |
1885 | ssize_t ret; | 1799 | ssize_t ret; |
@@ -1887,40 +1801,32 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, | |||
1887 | if (fc->no_getxattr) | 1801 | if (fc->no_getxattr) |
1888 | return -EOPNOTSUPP; | 1802 | return -EOPNOTSUPP; |
1889 | 1803 | ||
1890 | req = fuse_get_req_nopages(fc); | ||
1891 | if (IS_ERR(req)) | ||
1892 | return PTR_ERR(req); | ||
1893 | |||
1894 | memset(&inarg, 0, sizeof(inarg)); | 1804 | memset(&inarg, 0, sizeof(inarg)); |
1895 | inarg.size = size; | 1805 | inarg.size = size; |
1896 | req->in.h.opcode = FUSE_GETXATTR; | 1806 | args.in.h.opcode = FUSE_GETXATTR; |
1897 | req->in.h.nodeid = get_node_id(inode); | 1807 | args.in.h.nodeid = get_node_id(inode); |
1898 | req->in.numargs = 2; | 1808 | args.in.numargs = 2; |
1899 | req->in.args[0].size = sizeof(inarg); | 1809 | args.in.args[0].size = sizeof(inarg); |
1900 | req->in.args[0].value = &inarg; | 1810 | args.in.args[0].value = &inarg; |
1901 | req->in.args[1].size = strlen(name) + 1; | 1811 | args.in.args[1].size = strlen(name) + 1; |
1902 | req->in.args[1].value = name; | 1812 | args.in.args[1].value = name; |
1903 | /* This is really two different operations rolled into one */ | 1813 | /* This is really two different operations rolled into one */ |
1904 | req->out.numargs = 1; | 1814 | args.out.numargs = 1; |
1905 | if (size) { | 1815 | if (size) { |
1906 | req->out.argvar = 1; | 1816 | args.out.argvar = 1; |
1907 | req->out.args[0].size = size; | 1817 | args.out.args[0].size = size; |
1908 | req->out.args[0].value = value; | 1818 | args.out.args[0].value = value; |
1909 | } else { | 1819 | } else { |
1910 | req->out.args[0].size = sizeof(outarg); | 1820 | args.out.args[0].size = sizeof(outarg); |
1911 | req->out.args[0].value = &outarg; | 1821 | args.out.args[0].value = &outarg; |
1912 | } | 1822 | } |
1913 | fuse_request_send(fc, req); | 1823 | ret = fuse_simple_request(fc, &args); |
1914 | ret = req->out.h.error; | 1824 | if (!ret && !size) |
1915 | if (!ret) | 1825 | ret = outarg.size; |
1916 | ret = size ? req->out.args[0].size : outarg.size; | 1826 | if (ret == -ENOSYS) { |
1917 | else { | 1827 | fc->no_getxattr = 1; |
1918 | if (ret == -ENOSYS) { | 1828 | ret = -EOPNOTSUPP; |
1919 | fc->no_getxattr = 1; | ||
1920 | ret = -EOPNOTSUPP; | ||
1921 | } | ||
1922 | } | 1829 | } |
1923 | fuse_put_request(fc, req); | ||
1924 | return ret; | 1830 | return ret; |
1925 | } | 1831 | } |
1926 | 1832 | ||
@@ -1928,7 +1834,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) | |||
1928 | { | 1834 | { |
1929 | struct inode *inode = entry->d_inode; | 1835 | struct inode *inode = entry->d_inode; |
1930 | struct fuse_conn *fc = get_fuse_conn(inode); | 1836 | struct fuse_conn *fc = get_fuse_conn(inode); |
1931 | struct fuse_req *req; | 1837 | FUSE_ARGS(args); |
1932 | struct fuse_getxattr_in inarg; | 1838 | struct fuse_getxattr_in inarg; |
1933 | struct fuse_getxattr_out outarg; | 1839 | struct fuse_getxattr_out outarg; |
1934 | ssize_t ret; | 1840 | ssize_t ret; |
@@ -1939,38 +1845,30 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) | |||
1939 | if (fc->no_listxattr) | 1845 | if (fc->no_listxattr) |
1940 | return -EOPNOTSUPP; | 1846 | return -EOPNOTSUPP; |
1941 | 1847 | ||
1942 | req = fuse_get_req_nopages(fc); | ||
1943 | if (IS_ERR(req)) | ||
1944 | return PTR_ERR(req); | ||
1945 | |||
1946 | memset(&inarg, 0, sizeof(inarg)); | 1848 | memset(&inarg, 0, sizeof(inarg)); |
1947 | inarg.size = size; | 1849 | inarg.size = size; |
1948 | req->in.h.opcode = FUSE_LISTXATTR; | 1850 | args.in.h.opcode = FUSE_LISTXATTR; |
1949 | req->in.h.nodeid = get_node_id(inode); | 1851 | args.in.h.nodeid = get_node_id(inode); |
1950 | req->in.numargs = 1; | 1852 | args.in.numargs = 1; |
1951 | req->in.args[0].size = sizeof(inarg); | 1853 | args.in.args[0].size = sizeof(inarg); |
1952 | req->in.args[0].value = &inarg; | 1854 | args.in.args[0].value = &inarg; |
1953 | /* This is really two different operations rolled into one */ | 1855 | /* This is really two different operations rolled into one */ |
1954 | req->out.numargs = 1; | 1856 | args.out.numargs = 1; |
1955 | if (size) { | 1857 | if (size) { |
1956 | req->out.argvar = 1; | 1858 | args.out.argvar = 1; |
1957 | req->out.args[0].size = size; | 1859 | args.out.args[0].size = size; |
1958 | req->out.args[0].value = list; | 1860 | args.out.args[0].value = list; |
1959 | } else { | 1861 | } else { |
1960 | req->out.args[0].size = sizeof(outarg); | 1862 | args.out.args[0].size = sizeof(outarg); |
1961 | req->out.args[0].value = &outarg; | 1863 | args.out.args[0].value = &outarg; |
1962 | } | 1864 | } |
1963 | fuse_request_send(fc, req); | 1865 | ret = fuse_simple_request(fc, &args); |
1964 | ret = req->out.h.error; | 1866 | if (!ret && !size) |
1965 | if (!ret) | 1867 | ret = outarg.size; |
1966 | ret = size ? req->out.args[0].size : outarg.size; | 1868 | if (ret == -ENOSYS) { |
1967 | else { | 1869 | fc->no_listxattr = 1; |
1968 | if (ret == -ENOSYS) { | 1870 | ret = -EOPNOTSUPP; |
1969 | fc->no_listxattr = 1; | ||
1970 | ret = -EOPNOTSUPP; | ||
1971 | } | ||
1972 | } | 1871 | } |
1973 | fuse_put_request(fc, req); | ||
1974 | return ret; | 1872 | return ret; |
1975 | } | 1873 | } |
1976 | 1874 | ||
@@ -1978,24 +1876,18 @@ static int fuse_removexattr(struct dentry *entry, const char *name) | |||
1978 | { | 1876 | { |
1979 | struct inode *inode = entry->d_inode; | 1877 | struct inode *inode = entry->d_inode; |
1980 | struct fuse_conn *fc = get_fuse_conn(inode); | 1878 | struct fuse_conn *fc = get_fuse_conn(inode); |
1981 | struct fuse_req *req; | 1879 | FUSE_ARGS(args); |
1982 | int err; | 1880 | int err; |
1983 | 1881 | ||
1984 | if (fc->no_removexattr) | 1882 | if (fc->no_removexattr) |
1985 | return -EOPNOTSUPP; | 1883 | return -EOPNOTSUPP; |
1986 | 1884 | ||
1987 | req = fuse_get_req_nopages(fc); | 1885 | args.in.h.opcode = FUSE_REMOVEXATTR; |
1988 | if (IS_ERR(req)) | 1886 | args.in.h.nodeid = get_node_id(inode); |
1989 | return PTR_ERR(req); | 1887 | args.in.numargs = 1; |
1990 | 1888 | args.in.args[0].size = strlen(name) + 1; | |
1991 | req->in.h.opcode = FUSE_REMOVEXATTR; | 1889 | args.in.args[0].value = name; |
1992 | req->in.h.nodeid = get_node_id(inode); | 1890 | err = fuse_simple_request(fc, &args); |
1993 | req->in.numargs = 1; | ||
1994 | req->in.args[0].size = strlen(name) + 1; | ||
1995 | req->in.args[0].value = name; | ||
1996 | fuse_request_send(fc, req); | ||
1997 | err = req->out.h.error; | ||
1998 | fuse_put_request(fc, req); | ||
1999 | if (err == -ENOSYS) { | 1891 | if (err == -ENOSYS) { |
2000 | fc->no_removexattr = 1; | 1892 | fc->no_removexattr = 1; |
2001 | err = -EOPNOTSUPP; | 1893 | err = -EOPNOTSUPP; |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index bf50259012ab..760b2c552197 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -24,30 +24,22 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | |||
24 | int opcode, struct fuse_open_out *outargp) | 24 | int opcode, struct fuse_open_out *outargp) |
25 | { | 25 | { |
26 | struct fuse_open_in inarg; | 26 | struct fuse_open_in inarg; |
27 | struct fuse_req *req; | 27 | FUSE_ARGS(args); |
28 | int err; | ||
29 | |||
30 | req = fuse_get_req_nopages(fc); | ||
31 | if (IS_ERR(req)) | ||
32 | return PTR_ERR(req); | ||
33 | 28 | ||
34 | memset(&inarg, 0, sizeof(inarg)); | 29 | memset(&inarg, 0, sizeof(inarg)); |
35 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); | 30 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); |
36 | if (!fc->atomic_o_trunc) | 31 | if (!fc->atomic_o_trunc) |
37 | inarg.flags &= ~O_TRUNC; | 32 | inarg.flags &= ~O_TRUNC; |
38 | req->in.h.opcode = opcode; | 33 | args.in.h.opcode = opcode; |
39 | req->in.h.nodeid = nodeid; | 34 | args.in.h.nodeid = nodeid; |
40 | req->in.numargs = 1; | 35 | args.in.numargs = 1; |
41 | req->in.args[0].size = sizeof(inarg); | 36 | args.in.args[0].size = sizeof(inarg); |
42 | req->in.args[0].value = &inarg; | 37 | args.in.args[0].value = &inarg; |
43 | req->out.numargs = 1; | 38 | args.out.numargs = 1; |
44 | req->out.args[0].size = sizeof(*outargp); | 39 | args.out.args[0].size = sizeof(*outargp); |
45 | req->out.args[0].value = outargp; | 40 | args.out.args[0].value = outargp; |
46 | fuse_request_send(fc, req); | ||
47 | err = req->out.h.error; | ||
48 | fuse_put_request(fc, req); | ||
49 | 41 | ||
50 | return err; | 42 | return fuse_simple_request(fc, &args); |
51 | } | 43 | } |
52 | 44 | ||
53 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | 45 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) |
@@ -89,37 +81,9 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff) | |||
89 | return ff; | 81 | return ff; |
90 | } | 82 | } |
91 | 83 | ||
92 | static void fuse_release_async(struct work_struct *work) | ||
93 | { | ||
94 | struct fuse_req *req; | ||
95 | struct fuse_conn *fc; | ||
96 | struct path path; | ||
97 | |||
98 | req = container_of(work, struct fuse_req, misc.release.work); | ||
99 | path = req->misc.release.path; | ||
100 | fc = get_fuse_conn(path.dentry->d_inode); | ||
101 | |||
102 | fuse_put_request(fc, req); | ||
103 | path_put(&path); | ||
104 | } | ||
105 | |||
106 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) | 84 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) |
107 | { | 85 | { |
108 | if (fc->destroy_req) { | 86 | iput(req->misc.release.inode); |
109 | /* | ||
110 | * If this is a fuseblk mount, then it's possible that | ||
111 | * releasing the path will result in releasing the | ||
112 | * super block and sending the DESTROY request. If | ||
113 | * the server is single threaded, this would hang. | ||
114 | * For this reason do the path_put() in a separate | ||
115 | * thread. | ||
116 | */ | ||
117 | atomic_inc(&req->count); | ||
118 | INIT_WORK(&req->misc.release.work, fuse_release_async); | ||
119 | schedule_work(&req->misc.release.work); | ||
120 | } else { | ||
121 | path_put(&req->misc.release.path); | ||
122 | } | ||
123 | } | 87 | } |
124 | 88 | ||
125 | static void fuse_file_put(struct fuse_file *ff, bool sync) | 89 | static void fuse_file_put(struct fuse_file *ff, bool sync) |
@@ -133,12 +97,12 @@ static void fuse_file_put(struct fuse_file *ff, bool sync) | |||
133 | * implement 'open' | 97 | * implement 'open' |
134 | */ | 98 | */ |
135 | req->background = 0; | 99 | req->background = 0; |
136 | path_put(&req->misc.release.path); | 100 | iput(req->misc.release.inode); |
137 | fuse_put_request(ff->fc, req); | 101 | fuse_put_request(ff->fc, req); |
138 | } else if (sync) { | 102 | } else if (sync) { |
139 | req->background = 0; | 103 | req->background = 0; |
140 | fuse_request_send(ff->fc, req); | 104 | fuse_request_send(ff->fc, req); |
141 | path_put(&req->misc.release.path); | 105 | iput(req->misc.release.inode); |
142 | fuse_put_request(ff->fc, req); | 106 | fuse_put_request(ff->fc, req); |
143 | } else { | 107 | } else { |
144 | req->end = fuse_release_end; | 108 | req->end = fuse_release_end; |
@@ -297,9 +261,8 @@ void fuse_release_common(struct file *file, int opcode) | |||
297 | inarg->lock_owner = fuse_lock_owner_id(ff->fc, | 261 | inarg->lock_owner = fuse_lock_owner_id(ff->fc, |
298 | (fl_owner_t) file); | 262 | (fl_owner_t) file); |
299 | } | 263 | } |
300 | /* Hold vfsmount and dentry until release is finished */ | 264 | /* Hold inode until release is finished */ |
301 | path_get(&file->f_path); | 265 | req->misc.release.inode = igrab(file_inode(file)); |
302 | req->misc.release.path = file->f_path; | ||
303 | 266 | ||
304 | /* | 267 | /* |
305 | * Normally this will send the RELEASE request, however if | 268 | * Normally this will send the RELEASE request, however if |
@@ -480,7 +443,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
480 | struct inode *inode = file->f_mapping->host; | 443 | struct inode *inode = file->f_mapping->host; |
481 | struct fuse_conn *fc = get_fuse_conn(inode); | 444 | struct fuse_conn *fc = get_fuse_conn(inode); |
482 | struct fuse_file *ff = file->private_data; | 445 | struct fuse_file *ff = file->private_data; |
483 | struct fuse_req *req; | 446 | FUSE_ARGS(args); |
484 | struct fuse_fsync_in inarg; | 447 | struct fuse_fsync_in inarg; |
485 | int err; | 448 | int err; |
486 | 449 | ||
@@ -506,23 +469,15 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
506 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) | 469 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) |
507 | goto out; | 470 | goto out; |
508 | 471 | ||
509 | req = fuse_get_req_nopages(fc); | ||
510 | if (IS_ERR(req)) { | ||
511 | err = PTR_ERR(req); | ||
512 | goto out; | ||
513 | } | ||
514 | |||
515 | memset(&inarg, 0, sizeof(inarg)); | 472 | memset(&inarg, 0, sizeof(inarg)); |
516 | inarg.fh = ff->fh; | 473 | inarg.fh = ff->fh; |
517 | inarg.fsync_flags = datasync ? 1 : 0; | 474 | inarg.fsync_flags = datasync ? 1 : 0; |
518 | req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC; | 475 | args.in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC; |
519 | req->in.h.nodeid = get_node_id(inode); | 476 | args.in.h.nodeid = get_node_id(inode); |
520 | req->in.numargs = 1; | 477 | args.in.numargs = 1; |
521 | req->in.args[0].size = sizeof(inarg); | 478 | args.in.args[0].size = sizeof(inarg); |
522 | req->in.args[0].value = &inarg; | 479 | args.in.args[0].value = &inarg; |
523 | fuse_request_send(fc, req); | 480 | err = fuse_simple_request(fc, &args); |
524 | err = req->out.h.error; | ||
525 | fuse_put_request(fc, req); | ||
526 | if (err == -ENOSYS) { | 481 | if (err == -ENOSYS) { |
527 | if (isdir) | 482 | if (isdir) |
528 | fc->no_fsyncdir = 1; | 483 | fc->no_fsyncdir = 1; |
@@ -2156,49 +2111,44 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, | |||
2156 | return 0; | 2111 | return 0; |
2157 | } | 2112 | } |
2158 | 2113 | ||
2159 | static void fuse_lk_fill(struct fuse_req *req, struct file *file, | 2114 | static void fuse_lk_fill(struct fuse_args *args, struct file *file, |
2160 | const struct file_lock *fl, int opcode, pid_t pid, | 2115 | const struct file_lock *fl, int opcode, pid_t pid, |
2161 | int flock) | 2116 | int flock, struct fuse_lk_in *inarg) |
2162 | { | 2117 | { |
2163 | struct inode *inode = file_inode(file); | 2118 | struct inode *inode = file_inode(file); |
2164 | struct fuse_conn *fc = get_fuse_conn(inode); | 2119 | struct fuse_conn *fc = get_fuse_conn(inode); |
2165 | struct fuse_file *ff = file->private_data; | 2120 | struct fuse_file *ff = file->private_data; |
2166 | struct fuse_lk_in *arg = &req->misc.lk_in; | 2121 | |
2167 | 2122 | memset(inarg, 0, sizeof(*inarg)); | |
2168 | arg->fh = ff->fh; | 2123 | inarg->fh = ff->fh; |
2169 | arg->owner = fuse_lock_owner_id(fc, fl->fl_owner); | 2124 | inarg->owner = fuse_lock_owner_id(fc, fl->fl_owner); |
2170 | arg->lk.start = fl->fl_start; | 2125 | inarg->lk.start = fl->fl_start; |
2171 | arg->lk.end = fl->fl_end; | 2126 | inarg->lk.end = fl->fl_end; |
2172 | arg->lk.type = fl->fl_type; | 2127 | inarg->lk.type = fl->fl_type; |
2173 | arg->lk.pid = pid; | 2128 | inarg->lk.pid = pid; |
2174 | if (flock) | 2129 | if (flock) |
2175 | arg->lk_flags |= FUSE_LK_FLOCK; | 2130 | inarg->lk_flags |= FUSE_LK_FLOCK; |
2176 | req->in.h.opcode = opcode; | 2131 | args->in.h.opcode = opcode; |
2177 | req->in.h.nodeid = get_node_id(inode); | 2132 | args->in.h.nodeid = get_node_id(inode); |
2178 | req->in.numargs = 1; | 2133 | args->in.numargs = 1; |
2179 | req->in.args[0].size = sizeof(*arg); | 2134 | args->in.args[0].size = sizeof(*inarg); |
2180 | req->in.args[0].value = arg; | 2135 | args->in.args[0].value = inarg; |
2181 | } | 2136 | } |
2182 | 2137 | ||
2183 | static int fuse_getlk(struct file *file, struct file_lock *fl) | 2138 | static int fuse_getlk(struct file *file, struct file_lock *fl) |
2184 | { | 2139 | { |
2185 | struct inode *inode = file_inode(file); | 2140 | struct inode *inode = file_inode(file); |
2186 | struct fuse_conn *fc = get_fuse_conn(inode); | 2141 | struct fuse_conn *fc = get_fuse_conn(inode); |
2187 | struct fuse_req *req; | 2142 | FUSE_ARGS(args); |
2143 | struct fuse_lk_in inarg; | ||
2188 | struct fuse_lk_out outarg; | 2144 | struct fuse_lk_out outarg; |
2189 | int err; | 2145 | int err; |
2190 | 2146 | ||
2191 | req = fuse_get_req_nopages(fc); | 2147 | fuse_lk_fill(&args, file, fl, FUSE_GETLK, 0, 0, &inarg); |
2192 | if (IS_ERR(req)) | 2148 | args.out.numargs = 1; |
2193 | return PTR_ERR(req); | 2149 | args.out.args[0].size = sizeof(outarg); |
2194 | 2150 | args.out.args[0].value = &outarg; | |
2195 | fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0); | 2151 | err = fuse_simple_request(fc, &args); |
2196 | req->out.numargs = 1; | ||
2197 | req->out.args[0].size = sizeof(outarg); | ||
2198 | req->out.args[0].value = &outarg; | ||
2199 | fuse_request_send(fc, req); | ||
2200 | err = req->out.h.error; | ||
2201 | fuse_put_request(fc, req); | ||
2202 | if (!err) | 2152 | if (!err) |
2203 | err = convert_fuse_file_lock(&outarg.lk, fl); | 2153 | err = convert_fuse_file_lock(&outarg.lk, fl); |
2204 | 2154 | ||
@@ -2209,7 +2159,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
2209 | { | 2159 | { |
2210 | struct inode *inode = file_inode(file); | 2160 | struct inode *inode = file_inode(file); |
2211 | struct fuse_conn *fc = get_fuse_conn(inode); | 2161 | struct fuse_conn *fc = get_fuse_conn(inode); |
2212 | struct fuse_req *req; | 2162 | FUSE_ARGS(args); |
2163 | struct fuse_lk_in inarg; | ||
2213 | int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK; | 2164 | int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK; |
2214 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; | 2165 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; |
2215 | int err; | 2166 | int err; |
@@ -2223,17 +2174,13 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
2223 | if (fl->fl_flags & FL_CLOSE) | 2174 | if (fl->fl_flags & FL_CLOSE) |
2224 | return 0; | 2175 | return 0; |
2225 | 2176 | ||
2226 | req = fuse_get_req_nopages(fc); | 2177 | fuse_lk_fill(&args, file, fl, opcode, pid, flock, &inarg); |
2227 | if (IS_ERR(req)) | 2178 | err = fuse_simple_request(fc, &args); |
2228 | return PTR_ERR(req); | ||
2229 | 2179 | ||
2230 | fuse_lk_fill(req, file, fl, opcode, pid, flock); | ||
2231 | fuse_request_send(fc, req); | ||
2232 | err = req->out.h.error; | ||
2233 | /* locking is restartable */ | 2180 | /* locking is restartable */ |
2234 | if (err == -EINTR) | 2181 | if (err == -EINTR) |
2235 | err = -ERESTARTSYS; | 2182 | err = -ERESTARTSYS; |
2236 | fuse_put_request(fc, req); | 2183 | |
2237 | return err; | 2184 | return err; |
2238 | } | 2185 | } |
2239 | 2186 | ||
@@ -2283,7 +2230,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
2283 | { | 2230 | { |
2284 | struct inode *inode = mapping->host; | 2231 | struct inode *inode = mapping->host; |
2285 | struct fuse_conn *fc = get_fuse_conn(inode); | 2232 | struct fuse_conn *fc = get_fuse_conn(inode); |
2286 | struct fuse_req *req; | 2233 | FUSE_ARGS(args); |
2287 | struct fuse_bmap_in inarg; | 2234 | struct fuse_bmap_in inarg; |
2288 | struct fuse_bmap_out outarg; | 2235 | struct fuse_bmap_out outarg; |
2289 | int err; | 2236 | int err; |
@@ -2291,24 +2238,18 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
2291 | if (!inode->i_sb->s_bdev || fc->no_bmap) | 2238 | if (!inode->i_sb->s_bdev || fc->no_bmap) |
2292 | return 0; | 2239 | return 0; |
2293 | 2240 | ||
2294 | req = fuse_get_req_nopages(fc); | ||
2295 | if (IS_ERR(req)) | ||
2296 | return 0; | ||
2297 | |||
2298 | memset(&inarg, 0, sizeof(inarg)); | 2241 | memset(&inarg, 0, sizeof(inarg)); |
2299 | inarg.block = block; | 2242 | inarg.block = block; |
2300 | inarg.blocksize = inode->i_sb->s_blocksize; | 2243 | inarg.blocksize = inode->i_sb->s_blocksize; |
2301 | req->in.h.opcode = FUSE_BMAP; | 2244 | args.in.h.opcode = FUSE_BMAP; |
2302 | req->in.h.nodeid = get_node_id(inode); | 2245 | args.in.h.nodeid = get_node_id(inode); |
2303 | req->in.numargs = 1; | 2246 | args.in.numargs = 1; |
2304 | req->in.args[0].size = sizeof(inarg); | 2247 | args.in.args[0].size = sizeof(inarg); |
2305 | req->in.args[0].value = &inarg; | 2248 | args.in.args[0].value = &inarg; |
2306 | req->out.numargs = 1; | 2249 | args.out.numargs = 1; |
2307 | req->out.args[0].size = sizeof(outarg); | 2250 | args.out.args[0].size = sizeof(outarg); |
2308 | req->out.args[0].value = &outarg; | 2251 | args.out.args[0].value = &outarg; |
2309 | fuse_request_send(fc, req); | 2252 | err = fuse_simple_request(fc, &args); |
2310 | err = req->out.h.error; | ||
2311 | fuse_put_request(fc, req); | ||
2312 | if (err == -ENOSYS) | 2253 | if (err == -ENOSYS) |
2313 | fc->no_bmap = 1; | 2254 | fc->no_bmap = 1; |
2314 | 2255 | ||
@@ -2776,7 +2717,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
2776 | struct fuse_conn *fc = ff->fc; | 2717 | struct fuse_conn *fc = ff->fc; |
2777 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; | 2718 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; |
2778 | struct fuse_poll_out outarg; | 2719 | struct fuse_poll_out outarg; |
2779 | struct fuse_req *req; | 2720 | FUSE_ARGS(args); |
2780 | int err; | 2721 | int err; |
2781 | 2722 | ||
2782 | if (fc->no_poll) | 2723 | if (fc->no_poll) |
@@ -2794,21 +2735,15 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
2794 | fuse_register_polled_file(fc, ff); | 2735 | fuse_register_polled_file(fc, ff); |
2795 | } | 2736 | } |
2796 | 2737 | ||
2797 | req = fuse_get_req_nopages(fc); | 2738 | args.in.h.opcode = FUSE_POLL; |
2798 | if (IS_ERR(req)) | 2739 | args.in.h.nodeid = ff->nodeid; |
2799 | return POLLERR; | 2740 | args.in.numargs = 1; |
2800 | 2741 | args.in.args[0].size = sizeof(inarg); | |
2801 | req->in.h.opcode = FUSE_POLL; | 2742 | args.in.args[0].value = &inarg; |
2802 | req->in.h.nodeid = ff->nodeid; | 2743 | args.out.numargs = 1; |
2803 | req->in.numargs = 1; | 2744 | args.out.args[0].size = sizeof(outarg); |
2804 | req->in.args[0].size = sizeof(inarg); | 2745 | args.out.args[0].value = &outarg; |
2805 | req->in.args[0].value = &inarg; | 2746 | err = fuse_simple_request(fc, &args); |
2806 | req->out.numargs = 1; | ||
2807 | req->out.args[0].size = sizeof(outarg); | ||
2808 | req->out.args[0].value = &outarg; | ||
2809 | fuse_request_send(fc, req); | ||
2810 | err = req->out.h.error; | ||
2811 | fuse_put_request(fc, req); | ||
2812 | 2747 | ||
2813 | if (!err) | 2748 | if (!err) |
2814 | return outarg.revents; | 2749 | return outarg.revents; |
@@ -2949,10 +2884,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2949 | loff_t length) | 2884 | loff_t length) |
2950 | { | 2885 | { |
2951 | struct fuse_file *ff = file->private_data; | 2886 | struct fuse_file *ff = file->private_data; |
2952 | struct inode *inode = file->f_inode; | 2887 | struct inode *inode = file_inode(file); |
2953 | struct fuse_inode *fi = get_fuse_inode(inode); | 2888 | struct fuse_inode *fi = get_fuse_inode(inode); |
2954 | struct fuse_conn *fc = ff->fc; | 2889 | struct fuse_conn *fc = ff->fc; |
2955 | struct fuse_req *req; | 2890 | FUSE_ARGS(args); |
2956 | struct fuse_fallocate_in inarg = { | 2891 | struct fuse_fallocate_in inarg = { |
2957 | .fh = ff->fh, | 2892 | .fh = ff->fh, |
2958 | .offset = offset, | 2893 | .offset = offset, |
@@ -2985,25 +2920,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2985 | if (!(mode & FALLOC_FL_KEEP_SIZE)) | 2920 | if (!(mode & FALLOC_FL_KEEP_SIZE)) |
2986 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); | 2921 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); |
2987 | 2922 | ||
2988 | req = fuse_get_req_nopages(fc); | 2923 | args.in.h.opcode = FUSE_FALLOCATE; |
2989 | if (IS_ERR(req)) { | 2924 | args.in.h.nodeid = ff->nodeid; |
2990 | err = PTR_ERR(req); | 2925 | args.in.numargs = 1; |
2991 | goto out; | 2926 | args.in.args[0].size = sizeof(inarg); |
2992 | } | 2927 | args.in.args[0].value = &inarg; |
2993 | 2928 | err = fuse_simple_request(fc, &args); | |
2994 | req->in.h.opcode = FUSE_FALLOCATE; | ||
2995 | req->in.h.nodeid = ff->nodeid; | ||
2996 | req->in.numargs = 1; | ||
2997 | req->in.args[0].size = sizeof(inarg); | ||
2998 | req->in.args[0].value = &inarg; | ||
2999 | fuse_request_send(fc, req); | ||
3000 | err = req->out.h.error; | ||
3001 | if (err == -ENOSYS) { | 2929 | if (err == -ENOSYS) { |
3002 | fc->no_fallocate = 1; | 2930 | fc->no_fallocate = 1; |
3003 | err = -EOPNOTSUPP; | 2931 | err = -EOPNOTSUPP; |
3004 | } | 2932 | } |
3005 | fuse_put_request(fc, req); | ||
3006 | |||
3007 | if (err) | 2933 | if (err) |
3008 | goto out; | 2934 | goto out; |
3009 | 2935 | ||
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index e8e47a6ab518..e0fc6725d1d0 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -213,7 +213,7 @@ struct fuse_out { | |||
213 | unsigned numargs; | 213 | unsigned numargs; |
214 | 214 | ||
215 | /** Array of arguments */ | 215 | /** Array of arguments */ |
216 | struct fuse_arg args[3]; | 216 | struct fuse_arg args[2]; |
217 | }; | 217 | }; |
218 | 218 | ||
219 | /** FUSE page descriptor */ | 219 | /** FUSE page descriptor */ |
@@ -222,6 +222,25 @@ struct fuse_page_desc { | |||
222 | unsigned int offset; | 222 | unsigned int offset; |
223 | }; | 223 | }; |
224 | 224 | ||
225 | struct fuse_args { | ||
226 | struct { | ||
227 | struct { | ||
228 | uint32_t opcode; | ||
229 | uint64_t nodeid; | ||
230 | } h; | ||
231 | unsigned numargs; | ||
232 | struct fuse_in_arg args[3]; | ||
233 | |||
234 | } in; | ||
235 | struct { | ||
236 | unsigned argvar:1; | ||
237 | unsigned numargs; | ||
238 | struct fuse_arg args[2]; | ||
239 | } out; | ||
240 | }; | ||
241 | |||
242 | #define FUSE_ARGS(args) struct fuse_args args = {} | ||
243 | |||
225 | /** The request state */ | 244 | /** The request state */ |
226 | enum fuse_req_state { | 245 | enum fuse_req_state { |
227 | FUSE_REQ_INIT = 0, | 246 | FUSE_REQ_INIT = 0, |
@@ -305,11 +324,8 @@ struct fuse_req { | |||
305 | /** Data for asynchronous requests */ | 324 | /** Data for asynchronous requests */ |
306 | union { | 325 | union { |
307 | struct { | 326 | struct { |
308 | union { | 327 | struct fuse_release_in in; |
309 | struct fuse_release_in in; | 328 | struct inode *inode; |
310 | struct work_struct work; | ||
311 | }; | ||
312 | struct path path; | ||
313 | } release; | 329 | } release; |
314 | struct fuse_init_in init_in; | 330 | struct fuse_init_in init_in; |
315 | struct fuse_init_out init_out; | 331 | struct fuse_init_out init_out; |
@@ -324,7 +340,6 @@ struct fuse_req { | |||
324 | struct fuse_req *next; | 340 | struct fuse_req *next; |
325 | } write; | 341 | } write; |
326 | struct fuse_notify_retrieve_in retrieve_in; | 342 | struct fuse_notify_retrieve_in retrieve_in; |
327 | struct fuse_lk_in lk_in; | ||
328 | } misc; | 343 | } misc; |
329 | 344 | ||
330 | /** page vector */ | 345 | /** page vector */ |
@@ -754,15 +769,6 @@ struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc, | |||
754 | void __fuse_get_request(struct fuse_req *req); | 769 | void __fuse_get_request(struct fuse_req *req); |
755 | 770 | ||
756 | /** | 771 | /** |
757 | * Get a request, may fail with -ENOMEM, | ||
758 | * useful for callers who doesn't use req->pages[] | ||
759 | */ | ||
760 | static inline struct fuse_req *fuse_get_req_nopages(struct fuse_conn *fc) | ||
761 | { | ||
762 | return fuse_get_req(fc, 0); | ||
763 | } | ||
764 | |||
765 | /** | ||
766 | * Gets a requests for a file operation, always succeeds | 772 | * Gets a requests for a file operation, always succeeds |
767 | */ | 773 | */ |
768 | struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, | 774 | struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, |
@@ -780,6 +786,11 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); | |||
780 | void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req); | 786 | void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req); |
781 | 787 | ||
782 | /** | 788 | /** |
789 | * Simple request sending that does request allocation and freeing | ||
790 | */ | ||
791 | ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args); | ||
792 | |||
793 | /** | ||
783 | * Send a request in the background | 794 | * Send a request in the background |
784 | */ | 795 | */ |
785 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); | 796 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); |
@@ -804,8 +815,6 @@ void fuse_invalidate_atime(struct inode *inode); | |||
804 | */ | 815 | */ |
805 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); | 816 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); |
806 | 817 | ||
807 | void fuse_conn_kill(struct fuse_conn *fc); | ||
808 | |||
809 | /** | 818 | /** |
810 | * Initialize fuse_conn | 819 | * Initialize fuse_conn |
811 | */ | 820 | */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 03246cd9d47a..6749109f255d 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -376,28 +376,13 @@ static void fuse_bdi_destroy(struct fuse_conn *fc) | |||
376 | bdi_destroy(&fc->bdi); | 376 | bdi_destroy(&fc->bdi); |
377 | } | 377 | } |
378 | 378 | ||
379 | void fuse_conn_kill(struct fuse_conn *fc) | ||
380 | { | ||
381 | spin_lock(&fc->lock); | ||
382 | fc->connected = 0; | ||
383 | fc->blocked = 0; | ||
384 | fc->initialized = 1; | ||
385 | spin_unlock(&fc->lock); | ||
386 | /* Flush all readers on this fs */ | ||
387 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | ||
388 | wake_up_all(&fc->waitq); | ||
389 | wake_up_all(&fc->blocked_waitq); | ||
390 | wake_up_all(&fc->reserved_req_waitq); | ||
391 | } | ||
392 | EXPORT_SYMBOL_GPL(fuse_conn_kill); | ||
393 | |||
394 | static void fuse_put_super(struct super_block *sb) | 379 | static void fuse_put_super(struct super_block *sb) |
395 | { | 380 | { |
396 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 381 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
397 | 382 | ||
398 | fuse_send_destroy(fc); | 383 | fuse_send_destroy(fc); |
399 | 384 | ||
400 | fuse_conn_kill(fc); | 385 | fuse_abort_conn(fc); |
401 | mutex_lock(&fuse_mutex); | 386 | mutex_lock(&fuse_mutex); |
402 | list_del(&fc->entry); | 387 | list_del(&fc->entry); |
403 | fuse_ctl_remove_conn(fc); | 388 | fuse_ctl_remove_conn(fc); |
@@ -425,7 +410,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
425 | { | 410 | { |
426 | struct super_block *sb = dentry->d_sb; | 411 | struct super_block *sb = dentry->d_sb; |
427 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 412 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
428 | struct fuse_req *req; | 413 | FUSE_ARGS(args); |
429 | struct fuse_statfs_out outarg; | 414 | struct fuse_statfs_out outarg; |
430 | int err; | 415 | int err; |
431 | 416 | ||
@@ -434,23 +419,17 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
434 | return 0; | 419 | return 0; |
435 | } | 420 | } |
436 | 421 | ||
437 | req = fuse_get_req_nopages(fc); | ||
438 | if (IS_ERR(req)) | ||
439 | return PTR_ERR(req); | ||
440 | |||
441 | memset(&outarg, 0, sizeof(outarg)); | 422 | memset(&outarg, 0, sizeof(outarg)); |
442 | req->in.numargs = 0; | 423 | args.in.numargs = 0; |
443 | req->in.h.opcode = FUSE_STATFS; | 424 | args.in.h.opcode = FUSE_STATFS; |
444 | req->in.h.nodeid = get_node_id(dentry->d_inode); | 425 | args.in.h.nodeid = get_node_id(dentry->d_inode); |
445 | req->out.numargs = 1; | 426 | args.out.numargs = 1; |
446 | req->out.args[0].size = | 427 | args.out.args[0].size = |
447 | fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); | 428 | fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); |
448 | req->out.args[0].value = &outarg; | 429 | args.out.args[0].value = &outarg; |
449 | fuse_request_send(fc, req); | 430 | err = fuse_simple_request(fc, &args); |
450 | err = req->out.h.error; | ||
451 | if (!err) | 431 | if (!err) |
452 | convert_fuse_statfs(buf, &outarg.st); | 432 | convert_fuse_statfs(buf, &outarg.st); |
453 | fuse_put_request(fc, req); | ||
454 | return err; | 433 | return err; |
455 | } | 434 | } |
456 | 435 | ||