@@ -234,6 +234,35 @@ 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.
+ */
+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 +283,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);
}
@@ -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,
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@kernel.org> --- fs/nfsd/nfs4state.c | 32 ++++++++++++++++++++++++++++++-- fs/nfsd/state.h | 2 ++ 2 files changed, 32 insertions(+), 2 deletions(-)