Skip to content

Commit f84af33

Browse files
lxindavem330
authored andcommitted
sctp: factor out sctp_sendmsg_to_asoc from sctp_sendmsg
This patch is to move the codes for checking and sending on one asoc after this asoc has been found or created into sctp_sendmsg_to_asoc. Note that 'err != -ESRCH' check is for the case that asoc is freed when waiting for tx buffer in sctp_sendmsg_to_asoc. Signed-off-by: Xin Long <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e4e31cf commit f84af33

File tree

1 file changed

+99
-131
lines changed

1 file changed

+99
-131
lines changed

net/sctp/socket.c

Lines changed: 99 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,100 @@ static int sctp_error(struct sock *sk, int flags, int err)
16061606
static int sctp_msghdr_parse(const struct msghdr *msg,
16071607
struct sctp_cmsgs *cmsgs);
16081608

1609+
static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
1610+
struct msghdr *msg, size_t msg_len,
1611+
struct sctp_transport *transport,
1612+
struct sctp_sndrcvinfo *sinfo)
1613+
{
1614+
struct sock *sk = asoc->base.sk;
1615+
struct net *net = sock_net(sk);
1616+
struct sctp_datamsg *datamsg;
1617+
bool wait_connect = false;
1618+
struct sctp_chunk *chunk;
1619+
long timeo;
1620+
int err;
1621+
1622+
if (sinfo->sinfo_stream >= asoc->stream.outcnt) {
1623+
err = -EINVAL;
1624+
goto err;
1625+
}
1626+
1627+
if (unlikely(!asoc->stream.out[sinfo->sinfo_stream].ext)) {
1628+
err = sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream);
1629+
if (err)
1630+
goto err;
1631+
}
1632+
1633+
if (sctp_sk(sk)->disable_fragments && msg_len > asoc->frag_point) {
1634+
err = -EMSGSIZE;
1635+
goto err;
1636+
}
1637+
1638+
if (sctp_state(asoc, CLOSED)) {
1639+
err = sctp_primitive_ASSOCIATE(net, asoc, NULL);
1640+
if (err)
1641+
goto err;
1642+
1643+
if (sctp_sk(sk)->strm_interleave) {
1644+
timeo = sock_sndtimeo(sk, 0);
1645+
err = sctp_wait_for_connect(asoc, &timeo);
1646+
if (err)
1647+
goto err;
1648+
} else {
1649+
wait_connect = true;
1650+
}
1651+
1652+
pr_debug("%s: we associated primitively\n", __func__);
1653+
}
1654+
1655+
if (asoc->pmtu_pending)
1656+
sctp_assoc_pending_pmtu(asoc);
1657+
1658+
if (sctp_wspace(asoc) < msg_len)
1659+
sctp_prsctp_prune(asoc, sinfo, msg_len - sctp_wspace(asoc));
1660+
1661+
if (!sctp_wspace(asoc)) {
1662+
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1663+
err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
1664+
if (err)
1665+
goto err;
1666+
}
1667+
1668+
datamsg = sctp_datamsg_from_user(asoc, sinfo, &msg->msg_iter);
1669+
if (IS_ERR(datamsg)) {
1670+
err = PTR_ERR(datamsg);
1671+
goto err;
1672+
}
1673+
1674+
asoc->force_delay = !!(msg->msg_flags & MSG_MORE);
1675+
1676+
list_for_each_entry(chunk, &datamsg->chunks, frag_list) {
1677+
sctp_chunk_hold(chunk);
1678+
sctp_set_owner_w(chunk);
1679+
chunk->transport = transport;
1680+
}
1681+
1682+
err = sctp_primitive_SEND(net, asoc, datamsg);
1683+
if (err) {
1684+
sctp_datamsg_free(datamsg);
1685+
goto err;
1686+
}
1687+
1688+
pr_debug("%s: we sent primitively\n", __func__);
1689+
1690+
sctp_datamsg_put(datamsg);
1691+
1692+
if (unlikely(wait_connect)) {
1693+
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1694+
sctp_wait_for_connect(asoc, &timeo);
1695+
}
1696+
1697+
err = msg_len;
1698+
1699+
err:
1700+
return err;
1701+
}
1702+
16091703
static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
16101704
{
16111705
struct net *net = sock_net(sk);
@@ -1622,11 +1716,8 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
16221716
sctp_assoc_t associd = 0;
16231717
struct sctp_cmsgs cmsgs = { NULL };
16241718
enum sctp_scope scope;
1625-
bool fill_sinfo_ttl = false, wait_connect = false;
1626-
struct sctp_datamsg *datamsg;
1627-
int msg_flags = msg->msg_flags;
1719+
bool fill_sinfo_ttl = false;
16281720
__u16 sinfo_flags = 0;
1629-
long timeo;
16301721
int err;
16311722

16321723
err = 0;
@@ -1923,49 +2014,6 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
19232014
goto out_free;
19242015
}
19252016

1926-
if (asoc->pmtu_pending)
1927-
sctp_assoc_pending_pmtu(asoc);
1928-
1929-
/* If fragmentation is disabled and the message length exceeds the
1930-
* association fragmentation point, return EMSGSIZE. The I-D
1931-
* does not specify what this error is, but this looks like
1932-
* a great fit.
1933-
*/
1934-
if (sctp_sk(sk)->disable_fragments && (msg_len > asoc->frag_point)) {
1935-
err = -EMSGSIZE;
1936-
goto out_free;
1937-
}
1938-
1939-
/* Check for invalid stream. */
1940-
if (sinfo->sinfo_stream >= asoc->stream.outcnt) {
1941-
err = -EINVAL;
1942-
goto out_free;
1943-
}
1944-
1945-
/* Allocate sctp_stream_out_ext if not already done */
1946-
if (unlikely(!asoc->stream.out[sinfo->sinfo_stream].ext)) {
1947-
err = sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream);
1948-
if (err)
1949-
goto out_free;
1950-
}
1951-
1952-
if (sctp_wspace(asoc) < msg_len)
1953-
sctp_prsctp_prune(asoc, sinfo, msg_len - sctp_wspace(asoc));
1954-
1955-
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1956-
if (!sctp_wspace(asoc)) {
1957-
/* sk can be changed by peel off when waiting for buf. */
1958-
err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
1959-
if (err) {
1960-
if (err == -ESRCH) {
1961-
/* asoc is already dead. */
1962-
new_asoc = NULL;
1963-
err = -EPIPE;
1964-
}
1965-
goto out_free;
1966-
}
1967-
}
1968-
19692017
/* If an address is passed with the sendto/sendmsg call, it is used
19702018
* to override the primary destination address in the TCP model, or
19712019
* when SCTP_ADDR_OVER flag is set in the UDP model.
@@ -1980,96 +2028,16 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
19802028
} else
19812029
chunk_tp = NULL;
19822030

1983-
/* Auto-connect, if we aren't connected already. */
1984-
if (sctp_state(asoc, CLOSED)) {
1985-
err = sctp_primitive_ASSOCIATE(net, asoc, NULL);
1986-
if (err < 0)
1987-
goto out_free;
1988-
1989-
/* If stream interleave is enabled, wait_connect has to be
1990-
* done earlier than data enqueue, as it needs to make data
1991-
* or idata according to asoc->intl_enable which is set
1992-
* after connection is done.
1993-
*/
1994-
if (sctp_sk(asoc->base.sk)->strm_interleave) {
1995-
timeo = sock_sndtimeo(sk, 0);
1996-
err = sctp_wait_for_connect(asoc, &timeo);
1997-
if (err)
1998-
goto out_unlock;
1999-
} else {
2000-
wait_connect = true;
2001-
}
2002-
2003-
pr_debug("%s: we associated primitively\n", __func__);
2004-
}
2005-
2006-
/* Break the message into multiple chunks of maximum size. */
2007-
datamsg = sctp_datamsg_from_user(asoc, sinfo, &msg->msg_iter);
2008-
if (IS_ERR(datamsg)) {
2009-
err = PTR_ERR(datamsg);
2010-
goto out_free;
2011-
}
2012-
asoc->force_delay = !!(msg->msg_flags & MSG_MORE);
2013-
2014-
/* Now send the (possibly) fragmented message. */
2015-
list_for_each_entry(chunk, &datamsg->chunks, frag_list) {
2016-
sctp_chunk_hold(chunk);
2017-
2018-
/* Do accounting for the write space. */
2019-
sctp_set_owner_w(chunk);
2020-
2021-
chunk->transport = chunk_tp;
2022-
}
2023-
2024-
/* Send it to the lower layers. Note: all chunks
2025-
* must either fail or succeed. The lower layer
2026-
* works that way today. Keep it that way or this
2027-
* breaks.
2028-
*/
2029-
err = sctp_primitive_SEND(net, asoc, datamsg);
2030-
/* Did the lower layer accept the chunk? */
2031-
if (err) {
2032-
sctp_datamsg_free(datamsg);
2033-
goto out_free;
2034-
}
2035-
2036-
pr_debug("%s: we sent primitively\n", __func__);
2037-
2038-
sctp_datamsg_put(datamsg);
2039-
err = msg_len;
2040-
2041-
if (unlikely(wait_connect)) {
2042-
timeo = sock_sndtimeo(sk, msg_flags & MSG_DONTWAIT);
2043-
sctp_wait_for_connect(asoc, &timeo);
2044-
}
2045-
2046-
/* If we are already past ASSOCIATE, the lower
2047-
* layers are responsible for association cleanup.
2048-
*/
2049-
goto out_unlock;
2031+
/* Send msg to the asoc */
2032+
err = sctp_sendmsg_to_asoc(asoc, msg, msg_len, chunk_tp, sinfo);
20502033

20512034
out_free:
2052-
if (new_asoc)
2035+
if (err < 0 && err != -ESRCH && new_asoc)
20532036
sctp_association_free(asoc);
20542037
out_unlock:
20552038
release_sock(sk);
2056-
20572039
out_nounlock:
2058-
return sctp_error(sk, msg_flags, err);
2059-
2060-
#if 0
2061-
do_sock_err:
2062-
if (msg_len)
2063-
err = msg_len;
2064-
else
2065-
err = sock_error(sk);
2066-
goto out;
2067-
2068-
do_interrupted:
2069-
if (msg_len)
2070-
err = msg_len;
2071-
goto out;
2072-
#endif /* 0 */
2040+
return sctp_error(sk, msg->msg_flags, err);
20732041
}
20742042

20752043
/* This is an extended version of skb_pull() that removes the data from the

0 commit comments

Comments
 (0)