Skip to content

Commit fb5f7f2

Browse files
author
Trond Myklebust
committed
NFS: commit errors should be fatal
Fix the O_DIRECT code to avoid retries if the COMMIT fails with a fatal error. Signed-off-by: Trond Myklebust <[email protected]>
1 parent 18f4129 commit fb5f7f2

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

fs/nfs/direct.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct nfs_direct_req {
9494
#define NFS_ODIRECT_RESCHED_WRITES (2) /* write verification failed */
9595
/* for read */
9696
#define NFS_ODIRECT_SHOULD_DIRTY (3) /* dirty user-space page after read */
97+
#define NFS_ODIRECT_DONE INT_MAX /* write verification failed */
9798
struct nfs_writeverf verf; /* unstable write verifier */
9899
};
99100

@@ -678,8 +679,17 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
678679
struct nfs_page *req;
679680
int status = data->task.tk_status;
680681

682+
if (status < 0) {
683+
/* Errors in commit are fatal */
684+
dreq->error = status;
685+
dreq->max_count = 0;
686+
dreq->count = 0;
687+
dreq->flags = NFS_ODIRECT_DONE;
688+
} else if (dreq->flags == NFS_ODIRECT_DONE)
689+
status = dreq->error;
690+
681691
nfs_init_cinfo_from_dreq(&cinfo, dreq);
682-
if (status < 0 || nfs_direct_cmp_commit_data_verf(dreq, data))
692+
if (nfs_direct_cmp_commit_data_verf(dreq, data))
683693
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
684694

685695
while (!list_empty(&data->pages)) {
@@ -708,7 +718,8 @@ static void nfs_direct_resched_write(struct nfs_commit_info *cinfo,
708718
struct nfs_direct_req *dreq = cinfo->dreq;
709719

710720
spin_lock(&dreq->lock);
711-
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
721+
if (dreq->flags != NFS_ODIRECT_DONE)
722+
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
712723
spin_unlock(&dreq->lock);
713724
nfs_mark_request_commit(req, NULL, cinfo, 0);
714725
}
@@ -731,6 +742,22 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
731742
nfs_direct_write_reschedule(dreq);
732743
}
733744

745+
static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
746+
{
747+
struct nfs_commit_info cinfo;
748+
struct nfs_page *req;
749+
LIST_HEAD(reqs);
750+
751+
nfs_init_cinfo_from_dreq(&cinfo, dreq);
752+
nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
753+
754+
while (!list_empty(&reqs)) {
755+
req = nfs_list_entry(reqs.next);
756+
nfs_list_remove_request(req);
757+
nfs_unlock_and_release_request(req);
758+
}
759+
}
760+
734761
static void nfs_direct_write_schedule_work(struct work_struct *work)
735762
{
736763
struct nfs_direct_req *dreq = container_of(work, struct nfs_direct_req, work);
@@ -745,6 +772,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work)
745772
nfs_direct_write_reschedule(dreq);
746773
break;
747774
default:
775+
nfs_direct_write_clear_reqs(dreq);
748776
nfs_zap_mapping(dreq->inode, dreq->inode->i_mapping);
749777
nfs_direct_complete(dreq);
750778
}

0 commit comments

Comments
 (0)