diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-03-03 20:35:31 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-03-03 21:52:30 -0500 |
commit | e11259f920d8cb3550e0f311c064bdabe1bc3aaf (patch) | |
tree | 2b07c087911fe9c2db2f38943af888c693efe163 /fs | |
parent | 48d66b9749e39e0d4cc37d635df3f18906af38a6 (diff) |
NFSv4.1: Clear the old state by our client id before establishing a new lease
If the call to exchange-id returns with the EXCHGID4_FLAG_CONFIRMED_R flag
set, then that means our lease was established by a previous mount instance.
Ensure that we detect this situation, and that we clear the state held by
that mount.
Reported-by: Jorge Mora <Jorge.Mora@netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 15 | ||||
-rw-r--r-- | fs/nfs/nfs4session.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 6 |
3 files changed, 17 insertions, 5 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 732526e04cd5..627f37c44456 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -6897,9 +6897,13 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, | |||
6897 | 6897 | ||
6898 | if (status == 0) { | 6898 | if (status == 0) { |
6899 | clp->cl_clientid = res.clientid; | 6899 | clp->cl_clientid = res.clientid; |
6900 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); | 6900 | clp->cl_exchange_flags = res.flags; |
6901 | if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) | 6901 | /* Client ID is not confirmed */ |
6902 | if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) { | ||
6903 | clear_bit(NFS4_SESSION_ESTABLISHED, | ||
6904 | &clp->cl_session->session_state); | ||
6902 | clp->cl_seqid = res.seqid; | 6905 | clp->cl_seqid = res.seqid; |
6906 | } | ||
6903 | 6907 | ||
6904 | kfree(clp->cl_serverowner); | 6908 | kfree(clp->cl_serverowner); |
6905 | clp->cl_serverowner = res.server_owner; | 6909 | clp->cl_serverowner = res.server_owner; |
@@ -7231,6 +7235,9 @@ static void nfs4_update_session(struct nfs4_session *session, | |||
7231 | struct nfs41_create_session_res *res) | 7235 | struct nfs41_create_session_res *res) |
7232 | { | 7236 | { |
7233 | nfs4_copy_sessionid(&session->sess_id, &res->sessionid); | 7237 | nfs4_copy_sessionid(&session->sess_id, &res->sessionid); |
7238 | /* Mark client id and session as being confirmed */ | ||
7239 | session->clp->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R; | ||
7240 | set_bit(NFS4_SESSION_ESTABLISHED, &session->session_state); | ||
7234 | session->flags = res->flags; | 7241 | session->flags = res->flags; |
7235 | memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs)); | 7242 | memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs)); |
7236 | if (res->flags & SESSION4_BACK_CHAN) | 7243 | if (res->flags & SESSION4_BACK_CHAN) |
@@ -7326,8 +7333,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, | |||
7326 | dprintk("--> nfs4_proc_destroy_session\n"); | 7333 | dprintk("--> nfs4_proc_destroy_session\n"); |
7327 | 7334 | ||
7328 | /* session is still being setup */ | 7335 | /* session is still being setup */ |
7329 | if (session->clp->cl_cons_state != NFS_CS_READY) | 7336 | if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state)) |
7330 | return status; | 7337 | return 0; |
7331 | 7338 | ||
7332 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 7339 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
7333 | trace_nfs4_destroy_session(session->clp, status); | 7340 | trace_nfs4_destroy_session(session->clp, status); |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index fc46c7455898..e3ea2c5324d6 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
@@ -70,6 +70,7 @@ struct nfs4_session { | |||
70 | 70 | ||
71 | enum nfs4_session_state { | 71 | enum nfs4_session_state { |
72 | NFS4_SESSION_INITING, | 72 | NFS4_SESSION_INITING, |
73 | NFS4_SESSION_ESTABLISHED, | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, | 76 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index d8b43f0e08fc..f95e3b58bbc3 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -353,7 +353,11 @@ int nfs41_discover_server_trunking(struct nfs_client *clp, | |||
353 | if (clp != *result) | 353 | if (clp != *result) |
354 | return 0; | 354 | return 0; |
355 | 355 | ||
356 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 356 | /* Purge state if the client id was established in a prior instance */ |
357 | if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) | ||
358 | set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | ||
359 | else | ||
360 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
357 | nfs4_schedule_state_manager(clp); | 361 | nfs4_schedule_state_manager(clp); |
358 | status = nfs_wait_client_init_complete(clp); | 362 | status = nfs_wait_client_init_complete(clp); |
359 | if (status < 0) | 363 | if (status < 0) |