Commit 4770d722 authored by Jeff Layton's avatar Jeff Layton Committed by J. Bruce Fields

nfsd4: use cl_lock to synchronize all stateid idr calls

Currently, this is serialized by the client_mutex, which is slated for
removal. Add finer-grained locking here. Also, do some cleanup around
find_stateid to prepare for taking references.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarBenny Halevy <bhalevy@primarydata.com>
Signed-off-by: default avatarJeff Layton <jlayton@primarydata.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 11b9164a
...@@ -467,7 +467,6 @@ static void nfs4_file_put_access(struct nfs4_file *fp, u32 access) ...@@ -467,7 +467,6 @@ static void nfs4_file_put_access(struct nfs4_file *fp, u32 access)
static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
struct kmem_cache *slab) struct kmem_cache *slab)
{ {
struct idr *stateids = &cl->cl_stateids;
struct nfs4_stid *stid; struct nfs4_stid *stid;
int new_id; int new_id;
...@@ -475,7 +474,11 @@ static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, ...@@ -475,7 +474,11 @@ static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
if (!stid) if (!stid)
return NULL; return NULL;
new_id = idr_alloc_cyclic(stateids, stid, 0, 0, GFP_KERNEL); idr_preload(GFP_KERNEL);
spin_lock(&cl->cl_lock);
new_id = idr_alloc_cyclic(&cl->cl_stateids, stid, 0, 0, GFP_NOWAIT);
spin_unlock(&cl->cl_lock);
idr_preload_end();
if (new_id < 0) if (new_id < 0)
goto out_free; goto out_free;
stid->sc_client = cl; stid->sc_client = cl;
...@@ -635,9 +638,12 @@ nfs4_put_stid(struct nfs4_stid *s) ...@@ -635,9 +638,12 @@ nfs4_put_stid(struct nfs4_stid *s)
struct nfs4_file *fp = s->sc_file; struct nfs4_file *fp = s->sc_file;
struct nfs4_client *clp = s->sc_client; struct nfs4_client *clp = s->sc_client;
if (!atomic_dec_and_test(&s->sc_count)) might_lock(&clp->cl_lock);
if (!atomic_dec_and_lock(&s->sc_count, &clp->cl_lock))
return; return;
idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id);
spin_unlock(&clp->cl_lock);
s->sc_free(s); s->sc_free(s);
if (fp) if (fp)
put_nfs4_file(fp); put_nfs4_file(fp);
...@@ -1652,7 +1658,8 @@ static void gen_confirm(struct nfs4_client *clp) ...@@ -1652,7 +1658,8 @@ static void gen_confirm(struct nfs4_client *clp)
memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data)); memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
} }
static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) static struct nfs4_stid *
find_stateid_locked(struct nfs4_client *cl, stateid_t *t)
{ {
struct nfs4_stid *ret; struct nfs4_stid *ret;
...@@ -1662,16 +1669,28 @@ static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) ...@@ -1662,16 +1669,28 @@ static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t)
return ret; return ret;
} }
static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask) static struct nfs4_stid *
find_stateid(struct nfs4_client *cl, stateid_t *t)
{
struct nfs4_stid *ret;
spin_lock(&cl->cl_lock);
ret = find_stateid_locked(cl, t);
spin_unlock(&cl->cl_lock);
return ret;
}
static struct nfs4_stid *
find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask)
{ {
struct nfs4_stid *s; struct nfs4_stid *s;
s = find_stateid(cl, t); spin_lock(&cl->cl_lock);
if (!s) s = find_stateid_locked(cl, t);
return NULL; if (s != NULL && !(typemask & s->sc_type))
if (typemask & s->sc_type) s = NULL;
return s; spin_unlock(&cl->cl_lock);
return NULL; return s;
} }
static struct nfs4_client *create_client(struct xdr_netobj name, static struct nfs4_client *create_client(struct xdr_netobj name,
......
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