@@ -137,17 +137,6 @@ static __be32 mark_client_expired_locked(struct nfs4_client *clp)
137137 return nfs_ok ;
138138}
139139
140- static __be32 mark_client_expired (struct nfs4_client * clp )
141- {
142- struct nfsd_net * nn = net_generic (clp -> net , nfsd_net_id );
143- __be32 ret ;
144-
145- spin_lock (& nn -> client_lock );
146- ret = mark_client_expired_locked (clp );
147- spin_unlock (& nn -> client_lock );
148- return ret ;
149- }
150-
151140static __be32 get_client_locked (struct nfs4_client * clp )
152141{
153142 if (is_client_expired (clp ))
@@ -1437,12 +1426,10 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
14371426 new -> se_cb_sec = cses -> cb_sec ;
14381427 atomic_set (& new -> se_ref , 0 );
14391428 idx = hash_sessionid (& new -> se_sessionid );
1440- spin_lock (& nn -> client_lock );
14411429 list_add (& new -> se_hash , & nn -> sessionid_hashtbl [idx ]);
14421430 spin_lock (& clp -> cl_lock );
14431431 list_add (& new -> se_perclnt , & clp -> cl_sessions );
14441432 spin_unlock (& clp -> cl_lock );
1445- spin_unlock (& nn -> client_lock );
14461433
14471434 if (cses -> flags & SESSION4_BACK_CHAN ) {
14481435 struct sockaddr * sa = svc_addr (rqstp );
@@ -2411,6 +2398,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
24112398{
24122399 struct sockaddr * sa = svc_addr (rqstp );
24132400 struct nfs4_client * conf , * unconf ;
2401+ struct nfs4_client * old = NULL ;
24142402 struct nfsd4_session * new ;
24152403 struct nfsd4_conn * conn ;
24162404 struct nfsd4_clid_slot * cs_slot = NULL ;
@@ -2437,6 +2425,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
24372425 goto out_free_session ;
24382426
24392427 nfs4_lock_state ();
2428+ spin_lock (& nn -> client_lock );
24402429 unconf = find_unconfirmed_client (& cr_ses -> clientid , true, nn );
24412430 conf = find_confirmed_client (& cr_ses -> clientid , true, nn );
24422431 WARN_ON_ONCE (conf && unconf );
@@ -2455,7 +2444,6 @@ nfsd4_create_session(struct svc_rqst *rqstp,
24552444 goto out_free_conn ;
24562445 }
24572446 } else if (unconf ) {
2458- struct nfs4_client * old ;
24592447 if (!same_creds (& unconf -> cl_cred , & rqstp -> rq_cred ) ||
24602448 !rpc_cmp_addr (sa , (struct sockaddr * ) & unconf -> cl_addr )) {
24612449 status = nfserr_clid_inuse ;
@@ -2473,10 +2461,10 @@ nfsd4_create_session(struct svc_rqst *rqstp,
24732461 }
24742462 old = find_confirmed_client_by_name (& unconf -> cl_name , nn );
24752463 if (old ) {
2476- status = mark_client_expired (old );
2464+ status = mark_client_expired_locked (old );
24772465 if (status )
24782466 goto out_free_conn ;
2479- expire_client (old );
2467+ unhash_client_locked (old );
24802468 }
24812469 move_to_confirmed (unconf );
24822470 conf = unconf ;
@@ -2492,20 +2480,29 @@ nfsd4_create_session(struct svc_rqst *rqstp,
24922480 cr_ses -> flags &= ~SESSION4_RDMA ;
24932481
24942482 init_session (rqstp , new , conf , cr_ses );
2495- nfsd4_init_conn ( rqstp , conn , new );
2483+ nfsd4_get_session_locked ( new );
24962484
24972485 memcpy (cr_ses -> sessionid .data , new -> se_sessionid .data ,
24982486 NFS4_MAX_SESSIONID_LEN );
24992487 cs_slot -> sl_seqid ++ ;
25002488 cr_ses -> seqid = cs_slot -> sl_seqid ;
25012489
2502- /* cache solo and embedded create sessions under the state lock */
2490+ /* cache solo and embedded create sessions under the client_lock */
25032491 nfsd4_cache_create_session (cr_ses , cs_slot , status );
2492+ spin_unlock (& nn -> client_lock );
2493+ /* init connection and backchannel */
2494+ nfsd4_init_conn (rqstp , conn , new );
2495+ nfsd4_put_session (new );
25042496 nfs4_unlock_state ();
2497+ if (old )
2498+ expire_client (old );
25052499 return status ;
25062500out_free_conn :
2501+ spin_unlock (& nn -> client_lock );
25072502 nfs4_unlock_state ();
25082503 free_conn (conn );
2504+ if (old )
2505+ expire_client (old );
25092506out_free_session :
25102507 __free_session (new );
25112508out_release_drc_mem :
@@ -2965,6 +2962,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
29652962 struct nfsd4_setclientid_confirm * setclientid_confirm )
29662963{
29672964 struct nfs4_client * conf , * unconf ;
2965+ struct nfs4_client * old = NULL ;
29682966 nfs4_verifier confirm = setclientid_confirm -> sc_confirm ;
29692967 clientid_t * clid = & setclientid_confirm -> sc_clientid ;
29702968 __be32 status ;
@@ -2974,6 +2972,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
29742972 return nfserr_stale_clientid ;
29752973 nfs4_lock_state ();
29762974
2975+ spin_lock (& nn -> client_lock );
29772976 conf = find_confirmed_client (clid , false, nn );
29782977 unconf = find_unconfirmed_client (clid , false, nn );
29792978 /*
@@ -2997,21 +2996,29 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
29972996 }
29982997 status = nfs_ok ;
29992998 if (conf ) { /* case 1: callback update */
2999+ old = unconf ;
3000+ unhash_client_locked (old );
30003001 nfsd4_change_callback (conf , & unconf -> cl_cb_conn );
3001- nfsd4_probe_callback (conf );
3002- expire_client (unconf );
30033002 } else { /* case 3: normal case; new or rebooted client */
3004- conf = find_confirmed_client_by_name (& unconf -> cl_name , nn );
3005- if (conf ) {
3006- status = mark_client_expired ( conf );
3003+ old = find_confirmed_client_by_name (& unconf -> cl_name , nn );
3004+ if (old ) {
3005+ status = mark_client_expired_locked ( old );
30073006 if (status )
30083007 goto out ;
3009- expire_client ( conf );
3008+ unhash_client_locked ( old );
30103009 }
30113010 move_to_confirmed (unconf );
3012- nfsd4_probe_callback ( unconf ) ;
3011+ conf = unconf ;
30133012 }
3013+ get_client_locked (conf );
3014+ spin_unlock (& nn -> client_lock );
3015+ nfsd4_probe_callback (conf );
3016+ spin_lock (& nn -> client_lock );
3017+ put_client_renew_locked (conf );
30143018out :
3019+ spin_unlock (& nn -> client_lock );
3020+ if (old )
3021+ expire_client (old );
30153022 nfs4_unlock_state ();
30163023 return status ;
30173024}
@@ -5648,7 +5655,13 @@ nfs4_check_open_reclaim(clientid_t *clid,
56485655
56495656u64 nfsd_forget_client (struct nfs4_client * clp , u64 max )
56505657{
5651- if (mark_client_expired (clp ))
5658+ __be32 ret ;
5659+ struct nfsd_net * nn = net_generic (clp -> net , nfsd_net_id );
5660+
5661+ spin_lock (& nn -> client_lock );
5662+ ret = mark_client_expired_locked (clp );
5663+ spin_unlock (& nn -> client_lock );
5664+ if (ret != nfs_ok )
56525665 return 0 ;
56535666 expire_client (clp );
56545667 return 1 ;
0 commit comments