aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/direct.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-15 16:56:39 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-19 16:53:05 -0400
commitc9d8f89d9816c1d16ada492aa547a4d692508c0d (patch)
treed85339019cff084c11d4fceaf194fc5e34588d61 /fs/nfs/direct.c
parentfdd1e74c89fe39259a29c494209abad63ff76f82 (diff)
NFS: Ensure that the write code cleans up properly when rpc_run_task() fails
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r--fs/nfs/direct.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 9d9085b93a32..abf8e0286e35 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -508,27 +508,34 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
508static void nfs_direct_commit_result(struct rpc_task *task, void *calldata) 508static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
509{ 509{
510 struct nfs_write_data *data = calldata; 510 struct nfs_write_data *data = calldata;
511 struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
512 511
513 /* Call the NFS version-specific code */ 512 /* Call the NFS version-specific code */
514 if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) 513 NFS_PROTO(data->inode)->commit_done(task, data);
515 return; 514}
516 if (unlikely(task->tk_status < 0)) { 515
516static void nfs_direct_commit_release(void *calldata)
517{
518 struct nfs_write_data *data = calldata;
519 struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
520 int status = data->task.tk_status;
521
522 if (status < 0) {
517 dprintk("NFS: %5u commit failed with error %d.\n", 523 dprintk("NFS: %5u commit failed with error %d.\n",
518 task->tk_pid, task->tk_status); 524 data->task.tk_pid, status);
519 dreq->flags = NFS_ODIRECT_RESCHED_WRITES; 525 dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
520 } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { 526 } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) {
521 dprintk("NFS: %5u commit verify failed\n", task->tk_pid); 527 dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid);
522 dreq->flags = NFS_ODIRECT_RESCHED_WRITES; 528 dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
523 } 529 }
524 530
525 dprintk("NFS: %5u commit returned %d\n", task->tk_pid, task->tk_status); 531 dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
526 nfs_direct_write_complete(dreq, data->inode); 532 nfs_direct_write_complete(dreq, data->inode);
533 nfs_commitdata_release(calldata);
527} 534}
528 535
529static const struct rpc_call_ops nfs_commit_direct_ops = { 536static const struct rpc_call_ops nfs_commit_direct_ops = {
530 .rpc_call_done = nfs_direct_commit_result, 537 .rpc_call_done = nfs_direct_commit_result,
531 .rpc_release = nfs_commit_release, 538 .rpc_release = nfs_direct_commit_release,
532}; 539};
533 540
534static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) 541static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
@@ -596,7 +603,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
596 603
597static void nfs_alloc_commit_data(struct nfs_direct_req *dreq) 604static void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
598{ 605{
599 dreq->commit_data = nfs_commit_alloc(); 606 dreq->commit_data = nfs_commitdata_alloc();
600 if (dreq->commit_data != NULL) 607 if (dreq->commit_data != NULL)
601 dreq->commit_data->req = (struct nfs_page *) dreq; 608 dreq->commit_data->req = (struct nfs_page *) dreq;
602} 609}
@@ -617,11 +624,20 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
617static void nfs_direct_write_result(struct rpc_task *task, void *calldata) 624static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
618{ 625{
619 struct nfs_write_data *data = calldata; 626 struct nfs_write_data *data = calldata;
620 struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
621 int status = task->tk_status;
622 627
623 if (nfs_writeback_done(task, data) != 0) 628 if (nfs_writeback_done(task, data) != 0)
624 return; 629 return;
630}
631
632/*
633 * NB: Return the value of the first error return code. Subsequent
634 * errors after the first one are ignored.
635 */
636static void nfs_direct_write_release(void *calldata)
637{
638 struct nfs_write_data *data = calldata;
639 struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
640 int status = data->task.tk_status;
625 641
626 spin_lock(&dreq->lock); 642 spin_lock(&dreq->lock);
627 643
@@ -643,23 +659,13 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
643 break; 659 break;
644 case NFS_ODIRECT_DO_COMMIT: 660 case NFS_ODIRECT_DO_COMMIT:
645 if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) { 661 if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) {
646 dprintk("NFS: %5u write verify failed\n", task->tk_pid); 662 dprintk("NFS: %5u write verify failed\n", data->task.tk_pid);
647 dreq->flags = NFS_ODIRECT_RESCHED_WRITES; 663 dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
648 } 664 }
649 } 665 }
650 } 666 }
651out_unlock: 667out_unlock:
652 spin_unlock(&dreq->lock); 668 spin_unlock(&dreq->lock);
653}
654
655/*
656 * NB: Return the value of the first error return code. Subsequent
657 * errors after the first one are ignored.
658 */
659static void nfs_direct_write_release(void *calldata)
660{
661 struct nfs_write_data *data = calldata;
662 struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
663 669
664 if (put_dreq(dreq)) 670 if (put_dreq(dreq))
665 nfs_direct_write_complete(dreq, data->inode); 671 nfs_direct_write_complete(dreq, data->inode);