diff options
author | Jeff Layton <jlayton@primarydata.com> | 2014-07-29 21:34:10 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-07-31 14:19:25 -0400 |
commit | 4770d722014b99e5438c0d1dc44db31ac4547af1 (patch) | |
tree | 8718b531a52c2a578a1d5ba1421897a7f8206998 /fs/nfsd/nfs4state.c | |
parent | 11b9164adad7cd119b82b1f2c911a6d9bc67f1cc (diff) |
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: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Benny Halevy <bhalevy@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 344cd1ac3f67..bb37cc4dd573 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -467,7 +467,6 @@ static void nfs4_file_put_access(struct nfs4_file *fp, u32 access) | |||
467 | static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, | 467 | static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, |
468 | struct kmem_cache *slab) | 468 | struct kmem_cache *slab) |
469 | { | 469 | { |
470 | struct idr *stateids = &cl->cl_stateids; | ||
471 | struct nfs4_stid *stid; | 470 | struct nfs4_stid *stid; |
472 | int new_id; | 471 | int new_id; |
473 | 472 | ||
@@ -475,7 +474,11 @@ static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, | |||
475 | if (!stid) | 474 | if (!stid) |
476 | return NULL; | 475 | return NULL; |
477 | 476 | ||
478 | new_id = idr_alloc_cyclic(stateids, stid, 0, 0, GFP_KERNEL); | 477 | idr_preload(GFP_KERNEL); |
478 | spin_lock(&cl->cl_lock); | ||
479 | new_id = idr_alloc_cyclic(&cl->cl_stateids, stid, 0, 0, GFP_NOWAIT); | ||
480 | spin_unlock(&cl->cl_lock); | ||
481 | idr_preload_end(); | ||
479 | if (new_id < 0) | 482 | if (new_id < 0) |
480 | goto out_free; | 483 | goto out_free; |
481 | stid->sc_client = cl; | 484 | stid->sc_client = cl; |
@@ -635,9 +638,12 @@ nfs4_put_stid(struct nfs4_stid *s) | |||
635 | struct nfs4_file *fp = s->sc_file; | 638 | struct nfs4_file *fp = s->sc_file; |
636 | struct nfs4_client *clp = s->sc_client; | 639 | struct nfs4_client *clp = s->sc_client; |
637 | 640 | ||
638 | if (!atomic_dec_and_test(&s->sc_count)) | 641 | might_lock(&clp->cl_lock); |
642 | |||
643 | if (!atomic_dec_and_lock(&s->sc_count, &clp->cl_lock)) | ||
639 | return; | 644 | return; |
640 | idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); | 645 | idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); |
646 | spin_unlock(&clp->cl_lock); | ||
641 | s->sc_free(s); | 647 | s->sc_free(s); |
642 | if (fp) | 648 | if (fp) |
643 | put_nfs4_file(fp); | 649 | put_nfs4_file(fp); |
@@ -1652,7 +1658,8 @@ static void gen_confirm(struct nfs4_client *clp) | |||
1652 | memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data)); | 1658 | memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data)); |
1653 | } | 1659 | } |
1654 | 1660 | ||
1655 | static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) | 1661 | static struct nfs4_stid * |
1662 | find_stateid_locked(struct nfs4_client *cl, stateid_t *t) | ||
1656 | { | 1663 | { |
1657 | struct nfs4_stid *ret; | 1664 | struct nfs4_stid *ret; |
1658 | 1665 | ||
@@ -1662,16 +1669,28 @@ static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) | |||
1662 | return ret; | 1669 | return ret; |
1663 | } | 1670 | } |
1664 | 1671 | ||
1665 | static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask) | 1672 | static struct nfs4_stid * |
1673 | find_stateid(struct nfs4_client *cl, stateid_t *t) | ||
1674 | { | ||
1675 | struct nfs4_stid *ret; | ||
1676 | |||
1677 | spin_lock(&cl->cl_lock); | ||
1678 | ret = find_stateid_locked(cl, t); | ||
1679 | spin_unlock(&cl->cl_lock); | ||
1680 | return ret; | ||
1681 | } | ||
1682 | |||
1683 | static struct nfs4_stid * | ||
1684 | find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask) | ||
1666 | { | 1685 | { |
1667 | struct nfs4_stid *s; | 1686 | struct nfs4_stid *s; |
1668 | 1687 | ||
1669 | s = find_stateid(cl, t); | 1688 | spin_lock(&cl->cl_lock); |
1670 | if (!s) | 1689 | s = find_stateid_locked(cl, t); |
1671 | return NULL; | 1690 | if (s != NULL && !(typemask & s->sc_type)) |
1672 | if (typemask & s->sc_type) | 1691 | s = NULL; |
1673 | return s; | 1692 | spin_unlock(&cl->cl_lock); |
1674 | return NULL; | 1693 | return s; |
1675 | } | 1694 | } |
1676 | 1695 | ||
1677 | static struct nfs4_client *create_client(struct xdr_netobj name, | 1696 | static struct nfs4_client *create_client(struct xdr_netobj name, |