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/fuse/dir.c | |
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/fuse/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 538 |
1 files changed, 215 insertions, 323 deletions
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; |