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 | |
| 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()
| -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 | ||
