|
@@ -1926,41 +1926,35 @@ nfsd4_destroy_session(struct svc_rqst *r,
|
|
|
struct nfsd4_destroy_session *sessionid)
|
|
|
{
|
|
|
struct nfsd4_session *ses;
|
|
|
- __be32 status = nfserr_badsession;
|
|
|
+ __be32 status;
|
|
|
struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
|
|
|
|
|
|
- /* Notes:
|
|
|
- * - The confirmed nfs4_client->cl_sessionid holds destroyed sessinid
|
|
|
- * - Should we return nfserr_back_chan_busy if waiting for
|
|
|
- * callbacks on to-be-destroyed session?
|
|
|
- * - Do we need to clear any callback info from previous session?
|
|
|
- */
|
|
|
-
|
|
|
+ nfs4_lock_state();
|
|
|
+ status = nfserr_not_only_op;
|
|
|
if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
|
|
|
if (!nfsd4_last_compound_op(r))
|
|
|
- return nfserr_not_only_op;
|
|
|
+ goto out;
|
|
|
}
|
|
|
dump_sessionid(__func__, &sessionid->sessionid);
|
|
|
spin_lock(&nn->client_lock);
|
|
|
ses = find_in_sessionid_hashtbl(&sessionid->sessionid, SVC_NET(r));
|
|
|
- if (!ses) {
|
|
|
- spin_unlock(&nn->client_lock);
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ status = nfserr_badsession;
|
|
|
+ if (!ses)
|
|
|
+ goto out_client_lock;
|
|
|
|
|
|
unhash_session(ses);
|
|
|
spin_unlock(&nn->client_lock);
|
|
|
|
|
|
- nfs4_lock_state();
|
|
|
nfsd4_probe_callback_sync(ses->se_client);
|
|
|
- nfs4_unlock_state();
|
|
|
|
|
|
spin_lock(&nn->client_lock);
|
|
|
nfsd4_del_conns(ses);
|
|
|
nfsd4_put_session_locked(ses);
|
|
|
- spin_unlock(&nn->client_lock);
|
|
|
status = nfs_ok;
|
|
|
+out_client_lock:
|
|
|
+ spin_unlock(&nn->client_lock);
|
|
|
out:
|
|
|
+ nfs4_unlock_state();
|
|
|
return status;
|
|
|
}
|
|
|
|