The existing session reference counting is too heavyweight for callbacks. There is an atomic refcount in nfsd4_session (se_ref), but the existing functions take a client reference alongside it, and require the nn->client_lock. This is unnecessary for callbacks as they are already owned by the client. Add new nfsd4_cb_get_session() and nfsd4_cb_put_session() calls that take and put a session reference on behalf of a callback. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/nfsd/nfs4state.c | 34 ++++++++++++++++++++++++++++++++-- fs/nfsd/state.h | 2 ++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index cc819b8e8acdf5dcfe44c5bae45c6233f7b695e9..db68fd579ff0454153537817ee3cca71303654b4 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -234,6 +234,37 @@ static void put_client_renew(struct nfs4_client *clp) spin_unlock(&nn->client_lock); } +/** + * nfsd4_cb_get_session - get a session reference for a callback + * @ses: session of which to get a reference + * + * Callbacks are different than client-driven RPCs. The caller doesn't + * need a reference to the nfs4_client, and doesn't want to renew the + * lease when putting the reference. Returns true if a session was + * acquired, or false otherwise (which indicates that the session is + * dead). + */ +bool nfsd4_cb_get_session(struct nfsd4_session *ses) +{ + if (is_session_dead(ses)) + return false; + return atomic_inc_not_zero(&ses->se_ref); +} + +/** + * nfsd4_cb_put_session - put a session reference for a callback + * @ses: session of which to put a reference + * + * Callbacks are different than client-driven RPCs. The caller doesn't + * need a reference to the nfs4_client, and doesn't want to renew the + * lease when putting the reference. + */ +void nfsd4_cb_put_session(struct nfsd4_session *ses) +{ + if (ses && atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses)) + free_session(ses); +} + static __be32 nfsd4_get_session_locked(struct nfsd4_session *ses) { __be32 status; @@ -254,8 +285,7 @@ static void nfsd4_put_session_locked(struct nfsd4_session *ses) lockdep_assert_held(&nn->client_lock); - if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses)) - free_session(ses); + nfsd4_cb_put_session(ses); put_client_renew_locked(clp); } diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 74d2d7b42676d907bec9159b927aeed223d668c3..79d985d2a656e1a5b22a6a9c88f309515725e847 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -753,6 +753,8 @@ struct nfsd4_compound_state; struct nfsd_net; struct nfsd4_copy; +bool nfsd4_cb_get_session(struct nfsd4_session *ses); +void nfsd4_cb_put_session(struct nfsd4_session *ses); extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct svc_fh *fhp, stateid_t *stateid, int flags, struct nfsd_file **filp, -- 2.48.1