aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/state.h
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-04-01 22:23:49 -0400
committerJ. Bruce Fields <bfields@redhat.com>2013-04-03 11:48:39 -0400
commit221a68766973d7a3afe40a05abd8258b5de016a0 (patch)
treece1770ad1f1cc7227d8b8819101875b8f36a449b /fs/nfsd/state.h
parent4f6e6c17733ecf01c05a693ced8349ccf8101fd8 (diff)
nfsd4: don't destroy in-use clients
When a setclientid_confirm or create_session confirms a client after a client reboot, it also destroys any previous state held by that client. The shutdown of that previous state must be careful not to free the client out from under threads processing other requests that refer to the client. This is a particular problem in the NFSv4.1 case when we hold a reference to a session (hence a client) throughout compound processing. The server attempts to handle this by unhashing the client at the time it's destroyed, then delaying the final free to the end. But this still leaves some races in the current code. I believe it's simpler just to fail the attempt to destroy the client by returning NFS4ERR_DELAY. This is a case that should never happen anyway. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/state.h')
-rw-r--r--fs/nfsd/state.h16
1 files changed, 3 insertions, 13 deletions
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 327552bb6dba..07f8a822a6ce 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -209,6 +209,8 @@ struct nfsd4_session {
209 struct nfsd4_slot *se_slots[]; /* forward channel slots */ 209 struct nfsd4_slot *se_slots[]; /* forward channel slots */
210}; 210};
211 211
212extern void nfsd4_put_session(struct nfsd4_session *ses);
213
212/* formatted contents of nfs4_sessionid */ 214/* formatted contents of nfs4_sessionid */
213struct nfsd4_sessionid { 215struct nfsd4_sessionid {
214 clientid_t clientid; 216 clientid_t clientid;
@@ -284,18 +286,6 @@ struct nfs4_client {
284 struct net *net; 286 struct net *net;
285}; 287};
286 288
287static inline void
288mark_client_expired(struct nfs4_client *clp)
289{
290 clp->cl_time = 0;
291}
292
293static inline bool
294is_client_expired(struct nfs4_client *clp)
295{
296 return clp->cl_time == 0;
297}
298
299/* struct nfs4_client_reset 289/* struct nfs4_client_reset
300 * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl 290 * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl
301 * upon lease reset, or from upcall to state_daemon (to read in state 291 * upon lease reset, or from upcall to state_daemon (to read in state
@@ -484,7 +474,7 @@ extern void nfs4_put_delegation(struct nfs4_delegation *dp);
484extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name, 474extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
485 struct nfsd_net *nn); 475 struct nfsd_net *nn);
486extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn); 476extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
487extern void release_session_client(struct nfsd4_session *); 477extern void put_client_renew(struct nfs4_client *clp);
488extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); 478extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
489 479
490/* nfs4recover operations */ 480/* nfs4recover operations */