Commit d384d7c2 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] nfsd4: reference count stateowners

Reference-counting the nfsd4 stateowner structs will let us fix a race and
simplify some of the xdr code a bit, and may also help us make the nfsd4
locking a little more fine-grained in the future.
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 49398b8c
......@@ -833,6 +833,17 @@ release_all_files(void)
}
}
/* should use a slab cache */
void
nfs4_free_stateowner(struct kref *kref)
{
struct nfs4_stateowner *sop =
container_of(kref, struct nfs4_stateowner, so_ref);
kfree(sop->so_owner.data);
kfree(sop);
free_sowner++;
}
static inline struct nfs4_stateowner *
alloc_stateowner(struct xdr_netobj *owner)
{
......@@ -842,6 +853,7 @@ alloc_stateowner(struct xdr_netobj *owner)
if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
memcpy(sop->so_owner.data, owner->data, owner->len);
sop->so_owner.len = owner->len;
kref_init(&sop->so_ref);
return sop;
}
kfree(sop);
......@@ -849,17 +861,6 @@ alloc_stateowner(struct xdr_netobj *owner)
return NULL;
}
/* should use a slab cache */
static void
free_stateowner(struct nfs4_stateowner *sop) {
if (sop) {
kfree(sop->so_owner.data);
kfree(sop);
sop = NULL;
free_sowner++;
}
}
static struct nfs4_stateowner *
alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) {
struct nfs4_stateowner *sop;
......@@ -932,7 +933,7 @@ release_stateowner(struct nfs4_stateowner *sop)
{
unhash_stateowner(sop);
list_del(&sop->so_close_lru);
free_stateowner(sop);
nfs4_put_stateowner(sop);
}
static inline void
......@@ -1460,7 +1461,7 @@ nfs4_laundromat(void)
dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
sop->so_id);
list_del(&sop->so_close_lru);
free_stateowner(sop);
nfs4_put_stateowner(sop);
}
if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
......
......@@ -38,6 +38,7 @@
#define _NFSD4_STATE_H
#include <linux/list.h>
#include <linux/kref.h>
#include <linux/sunrpc/clnt.h>
#define NFS4_OPAQUE_LIMIT 1024
......@@ -168,6 +169,7 @@ struct nfs4_replay {
* reaped by laundramat thread after lease period.
*/
struct nfs4_stateowner {
struct kref so_ref;
struct list_head so_idhash; /* hash by so_id */
struct list_head so_strhash; /* hash by op_name */
struct list_head so_perclient; /* nfs4_client->cl_perclient */
......@@ -248,4 +250,18 @@ 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 nfs4_free_stateowner(struct kref *kref);
static inline void
nfs4_put_stateowner(struct nfs4_stateowner *so)
{
kref_put(&so->so_ref, nfs4_free_stateowner);
}
static inline void
nfs4_get_stateowner(struct nfs4_stateowner *so)
{
kref_get(&so->so_ref);
}
#endif /* NFSD4_STATE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment