diff options
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 113 |
1 files changed, 80 insertions, 33 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 7b994b2fa593..16844f98f50e 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -272,6 +272,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
272 | unsigned long user_addr = (unsigned long)iov->iov_base; | 272 | unsigned long user_addr = (unsigned long)iov->iov_base; |
273 | size_t count = iov->iov_len; | 273 | size_t count = iov->iov_len; |
274 | size_t rsize = NFS_SERVER(inode)->rsize; | 274 | size_t rsize = NFS_SERVER(inode)->rsize; |
275 | struct rpc_task *task; | ||
276 | struct rpc_message msg = { | ||
277 | .rpc_cred = ctx->cred, | ||
278 | }; | ||
279 | struct rpc_task_setup task_setup_data = { | ||
280 | .rpc_client = NFS_CLIENT(inode), | ||
281 | .rpc_message = &msg, | ||
282 | .callback_ops = &nfs_read_direct_ops, | ||
283 | .flags = RPC_TASK_ASYNC, | ||
284 | }; | ||
275 | unsigned int pgbase; | 285 | unsigned int pgbase; |
276 | int result; | 286 | int result; |
277 | ssize_t started = 0; | 287 | ssize_t started = 0; |
@@ -311,7 +321,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
311 | 321 | ||
312 | data->req = (struct nfs_page *) dreq; | 322 | data->req = (struct nfs_page *) dreq; |
313 | data->inode = inode; | 323 | data->inode = inode; |
314 | data->cred = ctx->cred; | 324 | data->cred = msg.rpc_cred; |
315 | data->args.fh = NFS_FH(inode); | 325 | data->args.fh = NFS_FH(inode); |
316 | data->args.context = ctx; | 326 | data->args.context = ctx; |
317 | data->args.offset = pos; | 327 | data->args.offset = pos; |
@@ -321,14 +331,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
321 | data->res.fattr = &data->fattr; | 331 | data->res.fattr = &data->fattr; |
322 | data->res.eof = 0; | 332 | data->res.eof = 0; |
323 | data->res.count = bytes; | 333 | data->res.count = bytes; |
334 | msg.rpc_argp = &data->args; | ||
335 | msg.rpc_resp = &data->res; | ||
324 | 336 | ||
325 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 337 | task_setup_data.task = &data->task; |
326 | &nfs_read_direct_ops, data); | 338 | task_setup_data.callback_data = data; |
327 | NFS_PROTO(inode)->read_setup(data); | 339 | NFS_PROTO(inode)->read_setup(data, &msg); |
328 | 340 | ||
329 | data->task.tk_cookie = (unsigned long) inode; | 341 | task = rpc_run_task(&task_setup_data); |
330 | 342 | if (!IS_ERR(task)) | |
331 | rpc_execute(&data->task); | 343 | rpc_put_task(task); |
332 | 344 | ||
333 | dprintk("NFS: %5u initiated direct read call " | 345 | dprintk("NFS: %5u initiated direct read call " |
334 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 346 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -427,6 +439,15 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
427 | struct inode *inode = dreq->inode; | 439 | struct inode *inode = dreq->inode; |
428 | struct list_head *p; | 440 | struct list_head *p; |
429 | struct nfs_write_data *data; | 441 | struct nfs_write_data *data; |
442 | struct rpc_task *task; | ||
443 | struct rpc_message msg = { | ||
444 | .rpc_cred = dreq->ctx->cred, | ||
445 | }; | ||
446 | struct rpc_task_setup task_setup_data = { | ||
447 | .rpc_client = NFS_CLIENT(inode), | ||
448 | .callback_ops = &nfs_write_direct_ops, | ||
449 | .flags = RPC_TASK_ASYNC, | ||
450 | }; | ||
430 | 451 | ||
431 | dreq->count = 0; | 452 | dreq->count = 0; |
432 | get_dreq(dreq); | 453 | get_dreq(dreq); |
@@ -436,6 +457,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
436 | 457 | ||
437 | get_dreq(dreq); | 458 | get_dreq(dreq); |
438 | 459 | ||
460 | /* Use stable writes */ | ||
461 | data->args.stable = NFS_FILE_SYNC; | ||
462 | |||
439 | /* | 463 | /* |
440 | * Reset data->res. | 464 | * Reset data->res. |
441 | */ | 465 | */ |
@@ -447,17 +471,18 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
447 | * Reuse data->task; data->args should not have changed | 471 | * Reuse data->task; data->args should not have changed |
448 | * since the original request was sent. | 472 | * since the original request was sent. |
449 | */ | 473 | */ |
450 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 474 | task_setup_data.task = &data->task; |
451 | &nfs_write_direct_ops, data); | 475 | task_setup_data.callback_data = data; |
452 | NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE); | 476 | msg.rpc_argp = &data->args; |
453 | 477 | msg.rpc_resp = &data->res; | |
454 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 478 | NFS_PROTO(inode)->write_setup(data, &msg); |
455 | data->task.tk_cookie = (unsigned long) inode; | ||
456 | 479 | ||
457 | /* | 480 | /* |
458 | * We're called via an RPC callback, so BKL is already held. | 481 | * We're called via an RPC callback, so BKL is already held. |
459 | */ | 482 | */ |
460 | rpc_execute(&data->task); | 483 | task = rpc_run_task(&task_setup_data); |
484 | if (!IS_ERR(task)) | ||
485 | rpc_put_task(task); | ||
461 | 486 | ||
462 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", | 487 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", |
463 | data->task.tk_pid, | 488 | data->task.tk_pid, |
@@ -500,9 +525,23 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { | |||
500 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | 525 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) |
501 | { | 526 | { |
502 | struct nfs_write_data *data = dreq->commit_data; | 527 | struct nfs_write_data *data = dreq->commit_data; |
528 | struct rpc_task *task; | ||
529 | struct rpc_message msg = { | ||
530 | .rpc_argp = &data->args, | ||
531 | .rpc_resp = &data->res, | ||
532 | .rpc_cred = dreq->ctx->cred, | ||
533 | }; | ||
534 | struct rpc_task_setup task_setup_data = { | ||
535 | .task = &data->task, | ||
536 | .rpc_client = NFS_CLIENT(dreq->inode), | ||
537 | .rpc_message = &msg, | ||
538 | .callback_ops = &nfs_commit_direct_ops, | ||
539 | .callback_data = data, | ||
540 | .flags = RPC_TASK_ASYNC, | ||
541 | }; | ||
503 | 542 | ||
504 | data->inode = dreq->inode; | 543 | data->inode = dreq->inode; |
505 | data->cred = dreq->ctx->cred; | 544 | data->cred = msg.rpc_cred; |
506 | 545 | ||
507 | data->args.fh = NFS_FH(data->inode); | 546 | data->args.fh = NFS_FH(data->inode); |
508 | data->args.offset = 0; | 547 | data->args.offset = 0; |
@@ -511,18 +550,16 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
511 | data->res.fattr = &data->fattr; | 550 | data->res.fattr = &data->fattr; |
512 | data->res.verf = &data->verf; | 551 | data->res.verf = &data->verf; |
513 | 552 | ||
514 | rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC, | 553 | NFS_PROTO(data->inode)->commit_setup(data, &msg); |
515 | &nfs_commit_direct_ops, data); | ||
516 | NFS_PROTO(data->inode)->commit_setup(data, 0); | ||
517 | 554 | ||
518 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | ||
519 | data->task.tk_cookie = (unsigned long)data->inode; | ||
520 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ | 555 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ |
521 | dreq->commit_data = NULL; | 556 | dreq->commit_data = NULL; |
522 | 557 | ||
523 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 558 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
524 | 559 | ||
525 | rpc_execute(&data->task); | 560 | task = rpc_run_task(&task_setup_data); |
561 | if (!IS_ERR(task)) | ||
562 | rpc_put_task(task); | ||
526 | } | 563 | } |
527 | 564 | ||
528 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 565 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
@@ -637,6 +674,16 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
637 | struct inode *inode = ctx->path.dentry->d_inode; | 674 | struct inode *inode = ctx->path.dentry->d_inode; |
638 | unsigned long user_addr = (unsigned long)iov->iov_base; | 675 | unsigned long user_addr = (unsigned long)iov->iov_base; |
639 | size_t count = iov->iov_len; | 676 | size_t count = iov->iov_len; |
677 | struct rpc_task *task; | ||
678 | struct rpc_message msg = { | ||
679 | .rpc_cred = ctx->cred, | ||
680 | }; | ||
681 | struct rpc_task_setup task_setup_data = { | ||
682 | .rpc_client = NFS_CLIENT(inode), | ||
683 | .rpc_message = &msg, | ||
684 | .callback_ops = &nfs_write_direct_ops, | ||
685 | .flags = RPC_TASK_ASYNC, | ||
686 | }; | ||
640 | size_t wsize = NFS_SERVER(inode)->wsize; | 687 | size_t wsize = NFS_SERVER(inode)->wsize; |
641 | unsigned int pgbase; | 688 | unsigned int pgbase; |
642 | int result; | 689 | int result; |
@@ -679,25 +726,27 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
679 | 726 | ||
680 | data->req = (struct nfs_page *) dreq; | 727 | data->req = (struct nfs_page *) dreq; |
681 | data->inode = inode; | 728 | data->inode = inode; |
682 | data->cred = ctx->cred; | 729 | data->cred = msg.rpc_cred; |
683 | data->args.fh = NFS_FH(inode); | 730 | data->args.fh = NFS_FH(inode); |
684 | data->args.context = ctx; | 731 | data->args.context = ctx; |
685 | data->args.offset = pos; | 732 | data->args.offset = pos; |
686 | data->args.pgbase = pgbase; | 733 | data->args.pgbase = pgbase; |
687 | data->args.pages = data->pagevec; | 734 | data->args.pages = data->pagevec; |
688 | data->args.count = bytes; | 735 | data->args.count = bytes; |
736 | data->args.stable = sync; | ||
689 | data->res.fattr = &data->fattr; | 737 | data->res.fattr = &data->fattr; |
690 | data->res.count = bytes; | 738 | data->res.count = bytes; |
691 | data->res.verf = &data->verf; | 739 | data->res.verf = &data->verf; |
692 | 740 | ||
693 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 741 | task_setup_data.task = &data->task; |
694 | &nfs_write_direct_ops, data); | 742 | task_setup_data.callback_data = data; |
695 | NFS_PROTO(inode)->write_setup(data, sync); | 743 | msg.rpc_argp = &data->args; |
744 | msg.rpc_resp = &data->res; | ||
745 | NFS_PROTO(inode)->write_setup(data, &msg); | ||
696 | 746 | ||
697 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 747 | task = rpc_run_task(&task_setup_data); |
698 | data->task.tk_cookie = (unsigned long) inode; | 748 | if (!IS_ERR(task)) |
699 | 749 | rpc_put_task(task); | |
700 | rpc_execute(&data->task); | ||
701 | 750 | ||
702 | dprintk("NFS: %5u initiated direct write call " | 751 | dprintk("NFS: %5u initiated direct write call " |
703 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 752 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -766,7 +815,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
766 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 815 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
767 | struct nfs_direct_req *dreq; | 816 | struct nfs_direct_req *dreq; |
768 | size_t wsize = NFS_SERVER(inode)->wsize; | 817 | size_t wsize = NFS_SERVER(inode)->wsize; |
769 | int sync = 0; | 818 | int sync = NFS_UNSTABLE; |
770 | 819 | ||
771 | dreq = nfs_direct_req_alloc(); | 820 | dreq = nfs_direct_req_alloc(); |
772 | if (!dreq) | 821 | if (!dreq) |
@@ -774,7 +823,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
774 | nfs_alloc_commit_data(dreq); | 823 | nfs_alloc_commit_data(dreq); |
775 | 824 | ||
776 | if (dreq->commit_data == NULL || count < wsize) | 825 | if (dreq->commit_data == NULL || count < wsize) |
777 | sync = FLUSH_STABLE; | 826 | sync = NFS_FILE_SYNC; |
778 | 827 | ||
779 | dreq->inode = inode; | 828 | dreq->inode = inode; |
780 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 829 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
@@ -886,8 +935,6 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
886 | retval = generic_write_checks(file, &pos, &count, 0); | 935 | retval = generic_write_checks(file, &pos, &count, 0); |
887 | if (retval) | 936 | if (retval) |
888 | goto out; | 937 | goto out; |
889 | if (!count) | ||
890 | goto out; /* return 0 */ | ||
891 | 938 | ||
892 | retval = -EINVAL; | 939 | retval = -EINVAL; |
893 | if ((ssize_t) count < 0) | 940 | if ((ssize_t) count < 0) |