aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-03-14 16:57:48 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-03-25 12:04:10 -0400
commit5d422301f97b821301efcdb6fc9d1a83a5c102d6 (patch)
treeed7117feb89a0a804669f9f017d2ce3ef7fee10c /fs/nfs/nfs4proc.c
parent3ed5e2a2c394df4e03a680842c2d07a8680f133b (diff)
NFSv4: Fail I/O if the state recovery fails irrevocably
If state recovery fails with an ESTALE or a ENOENT, then we shouldn't keep retrying. Instead, mark the stateid as being invalid and fail the I/O with an EIO error. For other operations such as POSIX and BSD file locking, truncate etc, fail with an EBADF to indicate that this file descriptor is no longer valid. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 26431cf62ddb..c3bbb6c53d61 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -295,7 +295,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
295 } 295 }
296 if (state == NULL) 296 if (state == NULL)
297 break; 297 break;
298 nfs4_schedule_stateid_recovery(server, state); 298 ret = nfs4_schedule_stateid_recovery(server, state);
299 if (ret < 0)
300 break;
299 goto wait_on_recovery; 301 goto wait_on_recovery;
300 case -NFS4ERR_DELEG_REVOKED: 302 case -NFS4ERR_DELEG_REVOKED:
301 case -NFS4ERR_ADMIN_REVOKED: 303 case -NFS4ERR_ADMIN_REVOKED:
@@ -303,11 +305,16 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
303 if (state == NULL) 305 if (state == NULL)
304 break; 306 break;
305 nfs_remove_bad_delegation(state->inode); 307 nfs_remove_bad_delegation(state->inode);
306 nfs4_schedule_stateid_recovery(server, state); 308 ret = nfs4_schedule_stateid_recovery(server, state);
309 if (ret < 0)
310 break;
307 goto wait_on_recovery; 311 goto wait_on_recovery;
308 case -NFS4ERR_EXPIRED: 312 case -NFS4ERR_EXPIRED:
309 if (state != NULL) 313 if (state != NULL) {
310 nfs4_schedule_stateid_recovery(server, state); 314 ret = nfs4_schedule_stateid_recovery(server, state);
315 if (ret < 0)
316 break;
317 }
311 case -NFS4ERR_STALE_STATEID: 318 case -NFS4ERR_STALE_STATEID:
312 case -NFS4ERR_STALE_CLIENTID: 319 case -NFS4ERR_STALE_CLIENTID:
313 nfs4_schedule_lease_recovery(clp); 320 nfs4_schedule_lease_recovery(clp);
@@ -2053,7 +2060,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
2053 2060
2054 nfs_fattr_init(fattr); 2061 nfs_fattr_init(fattr);
2055 2062
2056 if (state != NULL) { 2063 if (state != NULL && nfs4_valid_open_stateid(state)) {
2057 struct nfs_lockowner lockowner = { 2064 struct nfs_lockowner lockowner = {
2058 .l_owner = current->files, 2065 .l_owner = current->files,
2059 .l_pid = current->tgid, 2066 .l_pid = current->tgid,
@@ -2201,6 +2208,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
2201 calldata->arg.fmode &= ~FMODE_WRITE; 2208 calldata->arg.fmode &= ~FMODE_WRITE;
2202 } 2209 }
2203 } 2210 }
2211 if (!nfs4_valid_open_stateid(state))
2212 call_close = 0;
2204 spin_unlock(&state->owner->so_lock); 2213 spin_unlock(&state->owner->so_lock);
2205 2214
2206 if (!call_close) { 2215 if (!call_close) {
@@ -3980,11 +3989,14 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
3980 case -NFS4ERR_OPENMODE: 3989 case -NFS4ERR_OPENMODE:
3981 if (state == NULL) 3990 if (state == NULL)
3982 break; 3991 break;
3983 nfs4_schedule_stateid_recovery(server, state); 3992 if (nfs4_schedule_stateid_recovery(server, state) < 0)
3993 goto stateid_invalid;
3984 goto wait_on_recovery; 3994 goto wait_on_recovery;
3985 case -NFS4ERR_EXPIRED: 3995 case -NFS4ERR_EXPIRED:
3986 if (state != NULL) 3996 if (state != NULL) {
3987 nfs4_schedule_stateid_recovery(server, state); 3997 if (nfs4_schedule_stateid_recovery(server, state) < 0)
3998 goto stateid_invalid;
3999 }
3988 case -NFS4ERR_STALE_STATEID: 4000 case -NFS4ERR_STALE_STATEID:
3989 case -NFS4ERR_STALE_CLIENTID: 4001 case -NFS4ERR_STALE_CLIENTID:
3990 nfs4_schedule_lease_recovery(clp); 4002 nfs4_schedule_lease_recovery(clp);
@@ -4016,6 +4028,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
4016 } 4028 }
4017 task->tk_status = nfs4_map_errors(task->tk_status); 4029 task->tk_status = nfs4_map_errors(task->tk_status);
4018 return 0; 4030 return 0;
4031stateid_invalid:
4032 task->tk_status = -EIO;
4033 return 0;
4019wait_on_recovery: 4034wait_on_recovery:
4020 rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); 4035 rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
4021 if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) 4036 if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
@@ -4632,12 +4647,18 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
4632 data->res.open_seqid = data->arg.open_seqid; 4647 data->res.open_seqid = data->arg.open_seqid;
4633 } else 4648 } else
4634 data->arg.new_lock_owner = 0; 4649 data->arg.new_lock_owner = 0;
4650 if (!nfs4_valid_open_stateid(state)) {
4651 data->rpc_status = -EBADF;
4652 task->tk_action = NULL;
4653 goto out_release_open_seqid;
4654 }
4635 data->timestamp = jiffies; 4655 data->timestamp = jiffies;
4636 if (nfs4_setup_sequence(data->server, 4656 if (nfs4_setup_sequence(data->server,
4637 &data->arg.seq_args, 4657 &data->arg.seq_args,
4638 &data->res.seq_res, 4658 &data->res.seq_res,
4639 task) == 0) 4659 task) == 0)
4640 return; 4660 return;
4661out_release_open_seqid:
4641 nfs_release_seqid(data->arg.open_seqid); 4662 nfs_release_seqid(data->arg.open_seqid);
4642out_release_lock_seqid: 4663out_release_lock_seqid:
4643 nfs_release_seqid(data->arg.lock_seqid); 4664 nfs_release_seqid(data->arg.lock_seqid);