Commit 39a0295f authored by Ying Xue's avatar Ying Xue Committed by David S. Miller

tipc: Don't use iocb argument in socket layer

Currently the iocb argument is used to idenfiy whether or not socket
lock is hold before tipc_sendmsg()/tipc_send_stream() is called. But
this usage prevents iocb argument from being dropped through sendmsg()
at socket common layer. Therefore, in the commit we introduce two new
functions called __tipc_sendmsg() and __tipc_send_stream(). When they
are invoked, it assumes that their callers have taken socket lock,
thereby avoiding the weird usage of iocb argument.

Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6556c385
...@@ -114,6 +114,9 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, ...@@ -114,6 +114,9 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid); static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid);
static int tipc_sk_insert(struct tipc_sock *tsk); static int tipc_sk_insert(struct tipc_sock *tsk);
static void tipc_sk_remove(struct tipc_sock *tsk); static void tipc_sk_remove(struct tipc_sock *tsk);
static int __tipc_send_stream(struct socket *sock, struct msghdr *m,
size_t dsz);
static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz);
static const struct proto_ops packet_ops; static const struct proto_ops packet_ops;
static const struct proto_ops stream_ops; static const struct proto_ops stream_ops;
...@@ -906,6 +909,18 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) ...@@ -906,6 +909,18 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
*/ */
static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t dsz) struct msghdr *m, size_t dsz)
{
struct sock *sk = sock->sk;
int ret;
lock_sock(sk);
ret = __tipc_sendmsg(sock, m, dsz);
release_sock(sk);
return ret;
}
static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
{ {
DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -931,22 +946,13 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -931,22 +946,13 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
if (dsz > TIPC_MAX_USER_MSG_SIZE) if (dsz > TIPC_MAX_USER_MSG_SIZE)
return -EMSGSIZE; return -EMSGSIZE;
if (iocb)
lock_sock(sk);
if (unlikely(sock->state != SS_READY)) { if (unlikely(sock->state != SS_READY)) {
if (sock->state == SS_LISTENING) { if (sock->state == SS_LISTENING)
rc = -EPIPE; return -EPIPE;
goto exit; if (sock->state != SS_UNCONNECTED)
} return -EISCONN;
if (sock->state != SS_UNCONNECTED) { if (tsk->published)
rc = -EISCONN; return -EOPNOTSUPP;
goto exit;
}
if (tsk->published) {
rc = -EOPNOTSUPP;
goto exit;
}
if (dest->addrtype == TIPC_ADDR_NAME) { if (dest->addrtype == TIPC_ADDR_NAME) {
tsk->conn_type = dest->addr.name.name.type; tsk->conn_type = dest->addr.name.name.type;
tsk->conn_instance = dest->addr.name.name.instance; tsk->conn_instance = dest->addr.name.name.instance;
...@@ -956,8 +962,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -956,8 +962,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
if (dest->addrtype == TIPC_ADDR_MCAST) { if (dest->addrtype == TIPC_ADDR_MCAST) {
rc = tipc_sendmcast(sock, seq, m, dsz, timeo); return tipc_sendmcast(sock, seq, m, dsz, timeo);
goto exit;
} else if (dest->addrtype == TIPC_ADDR_NAME) { } else if (dest->addrtype == TIPC_ADDR_NAME) {
u32 type = dest->addr.name.name.type; u32 type = dest->addr.name.name.type;
u32 inst = dest->addr.name.name.instance; u32 inst = dest->addr.name.name.instance;
...@@ -972,10 +977,8 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -972,10 +977,8 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
dport = tipc_nametbl_translate(net, type, inst, &dnode); dport = tipc_nametbl_translate(net, type, inst, &dnode);
msg_set_destnode(mhdr, dnode); msg_set_destnode(mhdr, dnode);
msg_set_destport(mhdr, dport); msg_set_destport(mhdr, dport);
if (unlikely(!dport && !dnode)) { if (unlikely(!dport && !dnode))
rc = -EHOSTUNREACH; return -EHOSTUNREACH;
goto exit;
}
} else if (dest->addrtype == TIPC_ADDR_ID) { } else if (dest->addrtype == TIPC_ADDR_ID) {
dnode = dest->addr.id.node; dnode = dest->addr.id.node;
msg_set_type(mhdr, TIPC_DIRECT_MSG); msg_set_type(mhdr, TIPC_DIRECT_MSG);
...@@ -990,7 +993,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -990,7 +993,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
mtu = tipc_node_get_mtu(net, dnode, tsk->portid); mtu = tipc_node_get_mtu(net, dnode, tsk->portid);
rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, pktchain); rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, pktchain);
if (rc < 0) if (rc < 0)
goto exit; return rc;
do { do {
skb = skb_peek(pktchain); skb = skb_peek(pktchain);
...@@ -1013,9 +1016,6 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1013,9 +1016,6 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
if (rc) if (rc)
__skb_queue_purge(pktchain); __skb_queue_purge(pktchain);
} while (!rc); } while (!rc);
exit:
if (iocb)
release_sock(sk);
return rc; return rc;
} }
...@@ -1064,6 +1064,18 @@ static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) ...@@ -1064,6 +1064,18 @@ static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
*/ */
static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t dsz) struct msghdr *m, size_t dsz)
{
struct sock *sk = sock->sk;
int ret;
lock_sock(sk);
ret = __tipc_send_stream(sock, m, dsz);
release_sock(sk);
return ret;
}
static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
...@@ -1080,7 +1092,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1080,7 +1092,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
/* Handle implied connection establishment */ /* Handle implied connection establishment */
if (unlikely(dest)) { if (unlikely(dest)) {
rc = tipc_sendmsg(iocb, sock, m, dsz); rc = __tipc_sendmsg(sock, m, dsz);
if (dsz && (dsz == rc)) if (dsz && (dsz == rc))
tsk->sent_unacked = 1; tsk->sent_unacked = 1;
return rc; return rc;
...@@ -1088,15 +1100,11 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1088,15 +1100,11 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
if (dsz > (uint)INT_MAX) if (dsz > (uint)INT_MAX)
return -EMSGSIZE; return -EMSGSIZE;
if (iocb)
lock_sock(sk);
if (unlikely(sock->state != SS_CONNECTED)) { if (unlikely(sock->state != SS_CONNECTED)) {
if (sock->state == SS_DISCONNECTING) if (sock->state == SS_DISCONNECTING)
rc = -EPIPE; return -EPIPE;
else else
rc = -ENOTCONN; return -ENOTCONN;
goto exit;
} }
timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
...@@ -1108,7 +1116,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1108,7 +1116,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
send = min_t(uint, dsz - sent, TIPC_MAX_USER_MSG_SIZE); send = min_t(uint, dsz - sent, TIPC_MAX_USER_MSG_SIZE);
rc = tipc_msg_build(mhdr, m, sent, send, mtu, pktchain); rc = tipc_msg_build(mhdr, m, sent, send, mtu, pktchain);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto exit; return rc;
do { do {
if (likely(!tsk_conn_cong(tsk))) { if (likely(!tsk_conn_cong(tsk))) {
rc = tipc_link_xmit(net, pktchain, dnode, portid); rc = tipc_link_xmit(net, pktchain, dnode, portid);
...@@ -1133,9 +1141,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1133,9 +1141,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
if (rc) if (rc)
__skb_queue_purge(pktchain); __skb_queue_purge(pktchain);
} while (!rc); } while (!rc);
exit:
if (iocb)
release_sock(sk);
return sent ? sent : rc; return sent ? sent : rc;
} }
...@@ -1947,7 +1953,7 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest, ...@@ -1947,7 +1953,7 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
if (!timeout) if (!timeout)
m.msg_flags = MSG_DONTWAIT; m.msg_flags = MSG_DONTWAIT;
res = tipc_sendmsg(NULL, sock, &m, 0); res = __tipc_sendmsg(sock, &m, 0);
if ((res < 0) && (res != -EWOULDBLOCK)) if ((res < 0) && (res != -EWOULDBLOCK))
goto exit; goto exit;
...@@ -2103,7 +2109,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags) ...@@ -2103,7 +2109,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
struct msghdr m = {NULL,}; struct msghdr m = {NULL,};
tsk_advance_rx_queue(sk); tsk_advance_rx_queue(sk);
tipc_send_packet(NULL, new_sock, &m, 0); __tipc_send_stream(new_sock, &m, 0);
} else { } else {
__skb_dequeue(&sk->sk_receive_queue); __skb_dequeue(&sk->sk_receive_queue);
__skb_queue_head(&new_sk->sk_receive_queue, buf); __skb_queue_head(&new_sk->sk_receive_queue, buf);
......
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