diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-09-22 13:39:11 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2016-09-27 14:34:50 -0400 |
commit | 9c27869d3f0680fa01d15616891a666d9e30fd83 (patch) | |
tree | 20a4f8f3925b4b0568fbeb191e6d788d28512907 /fs/nfs | |
parent | 26f474432a7b4be336ed40d94f5a8245781cfc67 (diff) |
NFSv4: Pass the stateid to the exception handler in nfs4_read/write_done_cb
The actual stateid used in the READ or WRITE can represent a delegation,
a lock or a stateid, so it is useful to pass it as an argument to the
exception handler when an expired/revoked response is received from the
server. It also ensures that we don't re-label the state as needing
recovery if that has already occurred.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Tested-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 446de949f960..d1e60c915a07 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -4525,11 +4525,18 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr) | |||
4525 | struct nfs_server *server = NFS_SERVER(hdr->inode); | 4525 | struct nfs_server *server = NFS_SERVER(hdr->inode); |
4526 | 4526 | ||
4527 | trace_nfs4_read(hdr, task->tk_status); | 4527 | trace_nfs4_read(hdr, task->tk_status); |
4528 | if (nfs4_async_handle_error(task, server, | 4528 | if (task->tk_status < 0) { |
4529 | hdr->args.context->state, | 4529 | struct nfs4_exception exception = { |
4530 | NULL) == -EAGAIN) { | 4530 | .inode = hdr->inode, |
4531 | rpc_restart_call_prepare(task); | 4531 | .state = hdr->args.context->state, |
4532 | return -EAGAIN; | 4532 | .stateid = &hdr->args.stateid, |
4533 | }; | ||
4534 | task->tk_status = nfs4_async_handle_exception(task, | ||
4535 | server, task->tk_status, &exception); | ||
4536 | if (exception.retry) { | ||
4537 | rpc_restart_call_prepare(task); | ||
4538 | return -EAGAIN; | ||
4539 | } | ||
4533 | } | 4540 | } |
4534 | 4541 | ||
4535 | __nfs4_read_done_cb(hdr); | 4542 | __nfs4_read_done_cb(hdr); |
@@ -4598,11 +4605,19 @@ static int nfs4_write_done_cb(struct rpc_task *task, | |||
4598 | struct inode *inode = hdr->inode; | 4605 | struct inode *inode = hdr->inode; |
4599 | 4606 | ||
4600 | trace_nfs4_write(hdr, task->tk_status); | 4607 | trace_nfs4_write(hdr, task->tk_status); |
4601 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), | 4608 | if (task->tk_status < 0) { |
4602 | hdr->args.context->state, | 4609 | struct nfs4_exception exception = { |
4603 | NULL) == -EAGAIN) { | 4610 | .inode = hdr->inode, |
4604 | rpc_restart_call_prepare(task); | 4611 | .state = hdr->args.context->state, |
4605 | return -EAGAIN; | 4612 | .stateid = &hdr->args.stateid, |
4613 | }; | ||
4614 | task->tk_status = nfs4_async_handle_exception(task, | ||
4615 | NFS_SERVER(inode), task->tk_status, | ||
4616 | &exception); | ||
4617 | if (exception.retry) { | ||
4618 | rpc_restart_call_prepare(task); | ||
4619 | return -EAGAIN; | ||
4620 | } | ||
4606 | } | 4621 | } |
4607 | if (task->tk_status >= 0) { | 4622 | if (task->tk_status >= 0) { |
4608 | renew_lease(NFS_SERVER(inode), hdr->timestamp); | 4623 | renew_lease(NFS_SERVER(inode), hdr->timestamp); |