From: NeilBrown ... to protect the null (probe) callback asynchronous rpc's reference. Atomically inc and set the cb_set flag. Signed-off-by: Andy Adamson Signed-off-by: Neil Brown Signed-off-by: Andrew Morton --- 25-akpm/fs/nfsd/nfs4state.c | 14 ++++++++++++-- 25-akpm/include/linux/nfsd/state.h | 4 +++- 2 files changed, 15 insertions(+), 3 deletions(-) diff -puN fs/nfsd/nfs4state.c~knfsd-count-the-nfs4_client-structure-usage fs/nfsd/nfs4state.c --- 25/fs/nfsd/nfs4state.c~knfsd-count-the-nfs4_client-structure-usage Fri Dec 17 15:08:28 2004 +++ 25-akpm/fs/nfsd/nfs4state.c Fri Dec 17 15:08:28 2004 @@ -213,12 +213,19 @@ free_client(struct nfs4_client *clp) kfree(clp); } +void +put_nfs4_client(struct nfs4_client *clp) +{ + if (atomic_dec_and_test(&clp->cl_count)) + free_client(clp); +} + static void expire_client(struct nfs4_client *clp) { struct nfs4_stateowner *sop; - dprintk("NFSD: expire_client\n"); + dprintk("NFSD: expire_client cl_count %d\n",atomic_read(&clp->cl_count)); list_del(&clp->cl_idhash); list_del(&clp->cl_strhash); list_del(&clp->cl_lru); @@ -226,7 +233,7 @@ expire_client(struct nfs4_client *clp) sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient); release_stateowner(sop); } - free_client(clp); + put_nfs4_client(clp); } static struct nfs4_client * @@ -235,6 +242,9 @@ create_client(struct xdr_netobj name) { if (!(clp = alloc_client(name))) goto out; + atomic_set(&clp->cl_count, 1); + atomic_set(&clp->cl_callback.cb_set, 0); + clp->cl_callback.cb_parsed = 0; INIT_LIST_HEAD(&clp->cl_idhash); INIT_LIST_HEAD(&clp->cl_strhash); INIT_LIST_HEAD(&clp->cl_perclient); diff -puN include/linux/nfsd/state.h~knfsd-count-the-nfs4_client-structure-usage include/linux/nfsd/state.h --- 25/include/linux/nfsd/state.h~knfsd-count-the-nfs4_client-structure-usage Fri Dec 17 15:08:28 2004 +++ 25-akpm/include/linux/nfsd/state.h Fri Dec 17 15:08:28 2004 @@ -76,7 +76,7 @@ struct nfs4_callback { u32 cb_prog; u32 cb_ident; /* RPC client info */ - u32 cb_set; /* successful CB_NULL call */ + atomic_t cb_set; /* successful CB_NULL call */ struct rpc_program cb_program; struct rpc_stat cb_stat; struct rpc_clnt * cb_client; @@ -106,6 +106,7 @@ struct nfs4_client { nfs4_verifier cl_confirm; /* generated by server */ struct nfs4_callback cl_callback; /* callback info */ time_t cl_first_state; /* first state aquisition*/ + atomic_t cl_count; /* ref count */ }; /* struct nfs4_client_reset @@ -250,6 +251,7 @@ extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); extern int nfs4_in_grace(void); extern int nfs4_check_open_reclaim(clientid_t *clid); +extern void put_nfs4_client(struct nfs4_client *clp); extern void nfs4_free_stateowner(struct kref *kref); static inline void _