diff options
author | J. Bruce Fields <bfields@redhat.com> | 2010-10-21 17:17:31 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-10-24 21:07:07 -0400 |
commit | a663bdd8c5d18d287f7468470816c9e0e66343c1 (patch) | |
tree | 9949b3b2b678c1da67e97ee2c312b1a17b98e4c8 /fs/nfsd/nfs4state.c | |
parent | 5d18c1c2a9a74e0f966c257520b8b7f5136c87b3 (diff) |
nfsd4: fix connection allocation in sequence()
We're doing an allocation under a spinlock, and ignoring the
possibility of allocation failure.
A better fix wouldn't require an unnecessary allocation in the common
case, but we'll leave that for later.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index ce0412fd23eb..d4aa1b59d84b 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1628,33 +1628,25 @@ out: | |||
1628 | return status; | 1628 | return status; |
1629 | } | 1629 | } |
1630 | 1630 | ||
1631 | static struct nfsd4_conn *__nfsd4_find_conn(struct svc_rqst *r, struct nfsd4_session *s) | 1631 | static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s) |
1632 | { | 1632 | { |
1633 | struct nfsd4_conn *c; | 1633 | struct nfsd4_conn *c; |
1634 | 1634 | ||
1635 | list_for_each_entry(c, &s->se_conns, cn_persession) { | 1635 | list_for_each_entry(c, &s->se_conns, cn_persession) { |
1636 | if (c->cn_xprt == r->rq_xprt) { | 1636 | if (c->cn_xprt == xpt) { |
1637 | return c; | 1637 | return c; |
1638 | } | 1638 | } |
1639 | } | 1639 | } |
1640 | return NULL; | 1640 | return NULL; |
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | static void nfsd4_sequence_check_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | 1643 | static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses) |
1644 | { | 1644 | { |
1645 | struct nfs4_client *clp = ses->se_client; | 1645 | struct nfs4_client *clp = ses->se_client; |
1646 | struct nfsd4_conn *c, *new = NULL; | 1646 | struct nfsd4_conn *c; |
1647 | |||
1648 | spin_lock(&clp->cl_lock); | ||
1649 | c = __nfsd4_find_conn(rqstp, ses); | ||
1650 | spin_unlock(&clp->cl_lock); | ||
1651 | if (c) | ||
1652 | return; | ||
1653 | |||
1654 | new = alloc_conn(rqstp, NFS4_CDFC4_FORE); | ||
1655 | 1647 | ||
1656 | spin_lock(&clp->cl_lock); | 1648 | spin_lock(&clp->cl_lock); |
1657 | c = __nfsd4_find_conn(rqstp, ses); | 1649 | c = __nfsd4_find_conn(new->cn_xprt, ses); |
1658 | if (c) { | 1650 | if (c) { |
1659 | spin_unlock(&clp->cl_lock); | 1651 | spin_unlock(&clp->cl_lock); |
1660 | free_conn(new); | 1652 | free_conn(new); |
@@ -1674,11 +1666,20 @@ nfsd4_sequence(struct svc_rqst *rqstp, | |||
1674 | struct nfsd4_compoundres *resp = rqstp->rq_resp; | 1666 | struct nfsd4_compoundres *resp = rqstp->rq_resp; |
1675 | struct nfsd4_session *session; | 1667 | struct nfsd4_session *session; |
1676 | struct nfsd4_slot *slot; | 1668 | struct nfsd4_slot *slot; |
1669 | struct nfsd4_conn *conn; | ||
1677 | int status; | 1670 | int status; |
1678 | 1671 | ||
1679 | if (resp->opcnt != 1) | 1672 | if (resp->opcnt != 1) |
1680 | return nfserr_sequence_pos; | 1673 | return nfserr_sequence_pos; |
1681 | 1674 | ||
1675 | /* | ||
1676 | * Will be either used or freed by nfsd4_sequence_check_conn | ||
1677 | * below. | ||
1678 | */ | ||
1679 | conn = alloc_conn(rqstp, NFS4_CDFC4_FORE); | ||
1680 | if (!conn) | ||
1681 | return nfserr_jukebox; | ||
1682 | |||
1682 | spin_lock(&client_lock); | 1683 | spin_lock(&client_lock); |
1683 | status = nfserr_badsession; | 1684 | status = nfserr_badsession; |
1684 | session = find_in_sessionid_hashtbl(&seq->sessionid); | 1685 | session = find_in_sessionid_hashtbl(&seq->sessionid); |
@@ -1710,7 +1711,8 @@ nfsd4_sequence(struct svc_rqst *rqstp, | |||
1710 | if (status) | 1711 | if (status) |
1711 | goto out; | 1712 | goto out; |
1712 | 1713 | ||
1713 | nfsd4_sequence_check_conn(rqstp, session); | 1714 | nfsd4_sequence_check_conn(conn, session); |
1715 | conn = NULL; | ||
1714 | 1716 | ||
1715 | /* Success! bump slot seqid */ | 1717 | /* Success! bump slot seqid */ |
1716 | slot->sl_inuse = true; | 1718 | slot->sl_inuse = true; |
@@ -1726,6 +1728,7 @@ out: | |||
1726 | nfsd4_get_session(cstate->session); | 1728 | nfsd4_get_session(cstate->session); |
1727 | atomic_inc(&session->se_client->cl_refcount); | 1729 | atomic_inc(&session->se_client->cl_refcount); |
1728 | } | 1730 | } |
1731 | kfree(conn); | ||
1729 | spin_unlock(&client_lock); | 1732 | spin_unlock(&client_lock); |
1730 | dprintk("%s: return %d\n", __func__, ntohl(status)); | 1733 | dprintk("%s: return %d\n", __func__, ntohl(status)); |
1731 | return status; | 1734 | return status; |