diff options
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 16844f98f50e..4757a2b326a1 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -229,14 +229,20 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq) | |||
229 | static void nfs_direct_read_result(struct rpc_task *task, void *calldata) | 229 | static void nfs_direct_read_result(struct rpc_task *task, void *calldata) |
230 | { | 230 | { |
231 | struct nfs_read_data *data = calldata; | 231 | struct nfs_read_data *data = calldata; |
232 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | ||
233 | 232 | ||
234 | if (nfs_readpage_result(task, data) != 0) | 233 | nfs_readpage_result(task, data); |
235 | return; | 234 | } |
235 | |||
236 | static void nfs_direct_read_release(void *calldata) | ||
237 | { | ||
238 | |||
239 | struct nfs_read_data *data = calldata; | ||
240 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | ||
241 | int status = data->task.tk_status; | ||
236 | 242 | ||
237 | spin_lock(&dreq->lock); | 243 | spin_lock(&dreq->lock); |
238 | if (unlikely(task->tk_status < 0)) { | 244 | if (unlikely(status < 0)) { |
239 | dreq->error = task->tk_status; | 245 | dreq->error = status; |
240 | spin_unlock(&dreq->lock); | 246 | spin_unlock(&dreq->lock); |
241 | } else { | 247 | } else { |
242 | dreq->count += data->res.count; | 248 | dreq->count += data->res.count; |
@@ -249,11 +255,12 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata) | |||
249 | 255 | ||
250 | if (put_dreq(dreq)) | 256 | if (put_dreq(dreq)) |
251 | nfs_direct_complete(dreq); | 257 | nfs_direct_complete(dreq); |
258 | nfs_readdata_release(calldata); | ||
252 | } | 259 | } |
253 | 260 | ||
254 | static const struct rpc_call_ops nfs_read_direct_ops = { | 261 | static const struct rpc_call_ops nfs_read_direct_ops = { |
255 | .rpc_call_done = nfs_direct_read_result, | 262 | .rpc_call_done = nfs_direct_read_result, |
256 | .rpc_release = nfs_readdata_release, | 263 | .rpc_release = nfs_direct_read_release, |
257 | }; | 264 | }; |
258 | 265 | ||
259 | /* | 266 | /* |
@@ -280,6 +287,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
280 | .rpc_client = NFS_CLIENT(inode), | 287 | .rpc_client = NFS_CLIENT(inode), |
281 | .rpc_message = &msg, | 288 | .rpc_message = &msg, |
282 | .callback_ops = &nfs_read_direct_ops, | 289 | .callback_ops = &nfs_read_direct_ops, |
290 | .workqueue = nfsiod_workqueue, | ||
283 | .flags = RPC_TASK_ASYNC, | 291 | .flags = RPC_TASK_ASYNC, |
284 | }; | 292 | }; |
285 | unsigned int pgbase; | 293 | unsigned int pgbase; |
@@ -323,7 +331,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
323 | data->inode = inode; | 331 | data->inode = inode; |
324 | data->cred = msg.rpc_cred; | 332 | data->cred = msg.rpc_cred; |
325 | data->args.fh = NFS_FH(inode); | 333 | data->args.fh = NFS_FH(inode); |
326 | data->args.context = ctx; | 334 | data->args.context = get_nfs_open_context(ctx); |
327 | data->args.offset = pos; | 335 | data->args.offset = pos; |
328 | data->args.pgbase = pgbase; | 336 | data->args.pgbase = pgbase; |
329 | data->args.pages = data->pagevec; | 337 | data->args.pages = data->pagevec; |
@@ -339,8 +347,9 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
339 | NFS_PROTO(inode)->read_setup(data, &msg); | 347 | NFS_PROTO(inode)->read_setup(data, &msg); |
340 | 348 | ||
341 | task = rpc_run_task(&task_setup_data); | 349 | task = rpc_run_task(&task_setup_data); |
342 | if (!IS_ERR(task)) | 350 | if (IS_ERR(task)) |
343 | rpc_put_task(task); | 351 | break; |
352 | rpc_put_task(task); | ||
344 | 353 | ||
345 | dprintk("NFS: %5u initiated direct read call " | 354 | dprintk("NFS: %5u initiated direct read call " |
346 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 355 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -446,6 +455,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
446 | struct rpc_task_setup task_setup_data = { | 455 | struct rpc_task_setup task_setup_data = { |
447 | .rpc_client = NFS_CLIENT(inode), | 456 | .rpc_client = NFS_CLIENT(inode), |
448 | .callback_ops = &nfs_write_direct_ops, | 457 | .callback_ops = &nfs_write_direct_ops, |
458 | .workqueue = nfsiod_workqueue, | ||
449 | .flags = RPC_TASK_ASYNC, | 459 | .flags = RPC_TASK_ASYNC, |
450 | }; | 460 | }; |
451 | 461 | ||
@@ -499,27 +509,34 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
499 | static void nfs_direct_commit_result(struct rpc_task *task, void *calldata) | 509 | static void nfs_direct_commit_result(struct rpc_task *task, void *calldata) |
500 | { | 510 | { |
501 | struct nfs_write_data *data = calldata; | 511 | struct nfs_write_data *data = calldata; |
502 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | ||
503 | 512 | ||
504 | /* Call the NFS version-specific code */ | 513 | /* Call the NFS version-specific code */ |
505 | if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) | 514 | NFS_PROTO(data->inode)->commit_done(task, data); |
506 | return; | 515 | } |
507 | if (unlikely(task->tk_status < 0)) { | 516 | |
517 | static void nfs_direct_commit_release(void *calldata) | ||
518 | { | ||
519 | struct nfs_write_data *data = calldata; | ||
520 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | ||
521 | int status = data->task.tk_status; | ||
522 | |||
523 | if (status < 0) { | ||
508 | dprintk("NFS: %5u commit failed with error %d.\n", | 524 | dprintk("NFS: %5u commit failed with error %d.\n", |
509 | task->tk_pid, task->tk_status); | 525 | data->task.tk_pid, status); |
510 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; | 526 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; |
511 | } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { | 527 | } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { |
512 | dprintk("NFS: %5u commit verify failed\n", task->tk_pid); | 528 | dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid); |
513 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; | 529 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; |
514 | } | 530 | } |
515 | 531 | ||
516 | dprintk("NFS: %5u commit returned %d\n", task->tk_pid, task->tk_status); | 532 | dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status); |
517 | nfs_direct_write_complete(dreq, data->inode); | 533 | nfs_direct_write_complete(dreq, data->inode); |
534 | nfs_commitdata_release(calldata); | ||
518 | } | 535 | } |
519 | 536 | ||
520 | static const struct rpc_call_ops nfs_commit_direct_ops = { | 537 | static const struct rpc_call_ops nfs_commit_direct_ops = { |
521 | .rpc_call_done = nfs_direct_commit_result, | 538 | .rpc_call_done = nfs_direct_commit_result, |
522 | .rpc_release = nfs_commit_release, | 539 | .rpc_release = nfs_direct_commit_release, |
523 | }; | 540 | }; |
524 | 541 | ||
525 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | 542 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) |
@@ -537,6 +554,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
537 | .rpc_message = &msg, | 554 | .rpc_message = &msg, |
538 | .callback_ops = &nfs_commit_direct_ops, | 555 | .callback_ops = &nfs_commit_direct_ops, |
539 | .callback_data = data, | 556 | .callback_data = data, |
557 | .workqueue = nfsiod_workqueue, | ||
540 | .flags = RPC_TASK_ASYNC, | 558 | .flags = RPC_TASK_ASYNC, |
541 | }; | 559 | }; |
542 | 560 | ||
@@ -546,6 +564,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
546 | data->args.fh = NFS_FH(data->inode); | 564 | data->args.fh = NFS_FH(data->inode); |
547 | data->args.offset = 0; | 565 | data->args.offset = 0; |
548 | data->args.count = 0; | 566 | data->args.count = 0; |
567 | data->args.context = get_nfs_open_context(dreq->ctx); | ||
549 | data->res.count = 0; | 568 | data->res.count = 0; |
550 | data->res.fattr = &data->fattr; | 569 | data->res.fattr = &data->fattr; |
551 | data->res.verf = &data->verf; | 570 | data->res.verf = &data->verf; |
@@ -585,7 +604,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode | |||
585 | 604 | ||
586 | static void nfs_alloc_commit_data(struct nfs_direct_req *dreq) | 605 | static void nfs_alloc_commit_data(struct nfs_direct_req *dreq) |
587 | { | 606 | { |
588 | dreq->commit_data = nfs_commit_alloc(); | 607 | dreq->commit_data = nfs_commitdata_alloc(); |
589 | if (dreq->commit_data != NULL) | 608 | if (dreq->commit_data != NULL) |
590 | dreq->commit_data->req = (struct nfs_page *) dreq; | 609 | dreq->commit_data->req = (struct nfs_page *) dreq; |
591 | } | 610 | } |
@@ -606,11 +625,20 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode | |||
606 | static void nfs_direct_write_result(struct rpc_task *task, void *calldata) | 625 | static void nfs_direct_write_result(struct rpc_task *task, void *calldata) |
607 | { | 626 | { |
608 | struct nfs_write_data *data = calldata; | 627 | struct nfs_write_data *data = calldata; |
609 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | ||
610 | int status = task->tk_status; | ||
611 | 628 | ||
612 | if (nfs_writeback_done(task, data) != 0) | 629 | if (nfs_writeback_done(task, data) != 0) |
613 | return; | 630 | return; |
631 | } | ||
632 | |||
633 | /* | ||
634 | * NB: Return the value of the first error return code. Subsequent | ||
635 | * errors after the first one are ignored. | ||
636 | */ | ||
637 | static void nfs_direct_write_release(void *calldata) | ||
638 | { | ||
639 | struct nfs_write_data *data = calldata; | ||
640 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | ||
641 | int status = data->task.tk_status; | ||
614 | 642 | ||
615 | spin_lock(&dreq->lock); | 643 | spin_lock(&dreq->lock); |
616 | 644 | ||
@@ -632,23 +660,13 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata) | |||
632 | break; | 660 | break; |
633 | case NFS_ODIRECT_DO_COMMIT: | 661 | case NFS_ODIRECT_DO_COMMIT: |
634 | if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) { | 662 | if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) { |
635 | dprintk("NFS: %5u write verify failed\n", task->tk_pid); | 663 | dprintk("NFS: %5u write verify failed\n", data->task.tk_pid); |
636 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; | 664 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; |
637 | } | 665 | } |
638 | } | 666 | } |
639 | } | 667 | } |
640 | out_unlock: | 668 | out_unlock: |
641 | spin_unlock(&dreq->lock); | 669 | spin_unlock(&dreq->lock); |
642 | } | ||
643 | |||
644 | /* | ||
645 | * NB: Return the value of the first error return code. Subsequent | ||
646 | * errors after the first one are ignored. | ||
647 | */ | ||
648 | static void nfs_direct_write_release(void *calldata) | ||
649 | { | ||
650 | struct nfs_write_data *data = calldata; | ||
651 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | ||
652 | 670 | ||
653 | if (put_dreq(dreq)) | 671 | if (put_dreq(dreq)) |
654 | nfs_direct_write_complete(dreq, data->inode); | 672 | nfs_direct_write_complete(dreq, data->inode); |
@@ -682,6 +700,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
682 | .rpc_client = NFS_CLIENT(inode), | 700 | .rpc_client = NFS_CLIENT(inode), |
683 | .rpc_message = &msg, | 701 | .rpc_message = &msg, |
684 | .callback_ops = &nfs_write_direct_ops, | 702 | .callback_ops = &nfs_write_direct_ops, |
703 | .workqueue = nfsiod_workqueue, | ||
685 | .flags = RPC_TASK_ASYNC, | 704 | .flags = RPC_TASK_ASYNC, |
686 | }; | 705 | }; |
687 | size_t wsize = NFS_SERVER(inode)->wsize; | 706 | size_t wsize = NFS_SERVER(inode)->wsize; |
@@ -728,7 +747,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
728 | data->inode = inode; | 747 | data->inode = inode; |
729 | data->cred = msg.rpc_cred; | 748 | data->cred = msg.rpc_cred; |
730 | data->args.fh = NFS_FH(inode); | 749 | data->args.fh = NFS_FH(inode); |
731 | data->args.context = ctx; | 750 | data->args.context = get_nfs_open_context(ctx); |
732 | data->args.offset = pos; | 751 | data->args.offset = pos; |
733 | data->args.pgbase = pgbase; | 752 | data->args.pgbase = pgbase; |
734 | data->args.pages = data->pagevec; | 753 | data->args.pages = data->pagevec; |
@@ -745,8 +764,9 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
745 | NFS_PROTO(inode)->write_setup(data, &msg); | 764 | NFS_PROTO(inode)->write_setup(data, &msg); |
746 | 765 | ||
747 | task = rpc_run_task(&task_setup_data); | 766 | task = rpc_run_task(&task_setup_data); |
748 | if (!IS_ERR(task)) | 767 | if (IS_ERR(task)) |
749 | rpc_put_task(task); | 768 | break; |
769 | rpc_put_task(task); | ||
750 | 770 | ||
751 | dprintk("NFS: %5u initiated direct write call " | 771 | dprintk("NFS: %5u initiated direct write call " |
752 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 772 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |