Skip to content

Commit 69cad59

Browse files
committed
Merge branch 'tipc-fixes'
Tuong Lien says: ==================== tipc: add some patches This series adds patches to fix some issues in TIPC streaming & service subscription. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents f3fbc5a + 88690b1 commit 69cad59

File tree

3 files changed

+49
-16
lines changed

3 files changed

+49
-16
lines changed

net/tipc/socket.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,22 +1739,21 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct sk_buff *skb,
17391739
return 0;
17401740
}
17411741

1742-
static void tipc_sk_send_ack(struct tipc_sock *tsk)
1742+
static struct sk_buff *tipc_sk_build_ack(struct tipc_sock *tsk)
17431743
{
17441744
struct sock *sk = &tsk->sk;
1745-
struct net *net = sock_net(sk);
17461745
struct sk_buff *skb = NULL;
17471746
struct tipc_msg *msg;
17481747
u32 peer_port = tsk_peer_port(tsk);
17491748
u32 dnode = tsk_peer_node(tsk);
17501749

17511750
if (!tipc_sk_connected(sk))
1752-
return;
1751+
return NULL;
17531752
skb = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0,
17541753
dnode, tsk_own_node(tsk), peer_port,
17551754
tsk->portid, TIPC_OK);
17561755
if (!skb)
1757-
return;
1756+
return NULL;
17581757
msg = buf_msg(skb);
17591758
msg_set_conn_ack(msg, tsk->rcv_unacked);
17601759
tsk->rcv_unacked = 0;
@@ -1764,7 +1763,19 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk)
17641763
tsk->rcv_win = tsk_adv_blocks(tsk->sk.sk_rcvbuf);
17651764
msg_set_adv_win(msg, tsk->rcv_win);
17661765
}
1767-
tipc_node_xmit_skb(net, skb, dnode, msg_link_selector(msg));
1766+
return skb;
1767+
}
1768+
1769+
static void tipc_sk_send_ack(struct tipc_sock *tsk)
1770+
{
1771+
struct sk_buff *skb;
1772+
1773+
skb = tipc_sk_build_ack(tsk);
1774+
if (!skb)
1775+
return;
1776+
1777+
tipc_node_xmit_skb(sock_net(&tsk->sk), skb, tsk_peer_node(tsk),
1778+
msg_link_selector(buf_msg(skb)));
17681779
}
17691780

17701781
static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
@@ -1938,7 +1949,6 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m,
19381949
bool peek = flags & MSG_PEEK;
19391950
int offset, required, copy, copied = 0;
19401951
int hlen, dlen, err, rc;
1941-
bool ack = false;
19421952
long timeout;
19431953

19441954
/* Catch invalid receive attempts */
@@ -1983,7 +1993,6 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m,
19831993

19841994
/* Copy data if msg ok, otherwise return error/partial data */
19851995
if (likely(!err)) {
1986-
ack = msg_ack_required(hdr);
19871996
offset = skb_cb->bytes_read;
19881997
copy = min_t(int, dlen - offset, buflen - copied);
19891998
rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy);
@@ -2011,7 +2020,7 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m,
20112020

20122021
/* Send connection flow control advertisement when applicable */
20132022
tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen);
2014-
if (ack || tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE)
2023+
if (tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE)
20152024
tipc_sk_send_ack(tsk);
20162025

20172026
/* Exit if all requested data or FIN/error received */
@@ -2105,9 +2114,11 @@ static void tipc_sk_proto_rcv(struct sock *sk,
21052114
* tipc_sk_filter_connect - check incoming message for a connection-based socket
21062115
* @tsk: TIPC socket
21072116
* @skb: pointer to message buffer.
2117+
* @xmitq: for Nagle ACK if any
21082118
* Returns true if message should be added to receive queue, false otherwise
21092119
*/
2110-
static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
2120+
static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb,
2121+
struct sk_buff_head *xmitq)
21112122
{
21122123
struct sock *sk = &tsk->sk;
21132124
struct net *net = sock_net(sk);
@@ -2171,8 +2182,17 @@ static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
21712182
if (!skb_queue_empty(&sk->sk_write_queue))
21722183
tipc_sk_push_backlog(tsk);
21732184
/* Accept only connection-based messages sent by peer */
2174-
if (likely(con_msg && !err && pport == oport && pnode == onode))
2185+
if (likely(con_msg && !err && pport == oport &&
2186+
pnode == onode)) {
2187+
if (msg_ack_required(hdr)) {
2188+
struct sk_buff *skb;
2189+
2190+
skb = tipc_sk_build_ack(tsk);
2191+
if (skb)
2192+
__skb_queue_tail(xmitq, skb);
2193+
}
21752194
return true;
2195+
}
21762196
if (!tsk_peer_msg(tsk, hdr))
21772197
return false;
21782198
if (!err)
@@ -2267,7 +2287,7 @@ static void tipc_sk_filter_rcv(struct sock *sk, struct sk_buff *skb,
22672287
while ((skb = __skb_dequeue(&inputq))) {
22682288
hdr = buf_msg(skb);
22692289
limit = rcvbuf_limit(sk, skb);
2270-
if ((sk_conn && !tipc_sk_filter_connect(tsk, skb)) ||
2290+
if ((sk_conn && !tipc_sk_filter_connect(tsk, skb, xmitq)) ||
22712291
(!sk_conn && msg_connected(hdr)) ||
22722292
(!grp && msg_in_group(hdr)))
22732293
err = TIPC_ERR_NO_PORT;

net/tipc/subscr.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ void tipc_sub_get(struct tipc_subscription *subscription);
9696
(swap_ ? swab32(val__) : val__); \
9797
})
9898

99+
/* tipc_sub_write - write val_ to field_ of struct sub_ in user endian format
100+
*/
101+
#define tipc_sub_write(sub_, field_, val_) \
102+
({ \
103+
struct tipc_subscr *sub__ = sub_; \
104+
u32 val__ = val_; \
105+
int swap_ = !((sub__)->filter & TIPC_FILTER_MASK); \
106+
(sub__)->field_ = swap_ ? swab32(val__) : val__; \
107+
})
108+
99109
/* tipc_evt_write - write val_ to field_ of struct evt_ in user endian format
100110
*/
101111
#define tipc_evt_write(evt_, field_, val_) \

net/tipc/topsrv.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ static void tipc_conn_delete_sub(struct tipc_conn *con, struct tipc_subscr *s)
237237
if (!s || !memcmp(s, &sub->evt.s, sizeof(*s))) {
238238
tipc_sub_unsubscribe(sub);
239239
atomic_dec(&tn->subscription_count);
240-
} else if (s) {
241-
break;
240+
if (s)
241+
break;
242242
}
243243
}
244244
spin_unlock_bh(&con->sub_lock);
@@ -362,9 +362,10 @@ static int tipc_conn_rcv_sub(struct tipc_topsrv *srv,
362362
{
363363
struct tipc_net *tn = tipc_net(srv->net);
364364
struct tipc_subscription *sub;
365+
u32 s_filter = tipc_sub_read(s, filter);
365366

366-
if (tipc_sub_read(s, filter) & TIPC_SUB_CANCEL) {
367-
s->filter &= __constant_ntohl(~TIPC_SUB_CANCEL);
367+
if (s_filter & TIPC_SUB_CANCEL) {
368+
tipc_sub_write(s, filter, s_filter & ~TIPC_SUB_CANCEL);
368369
tipc_conn_delete_sub(con, s);
369370
return 0;
370371
}
@@ -400,7 +401,9 @@ static int tipc_conn_rcv_from_sock(struct tipc_conn *con)
400401
return -EWOULDBLOCK;
401402
if (ret == sizeof(s)) {
402403
read_lock_bh(&sk->sk_callback_lock);
403-
ret = tipc_conn_rcv_sub(srv, con, &s);
404+
/* RACE: the connection can be closed in the meantime */
405+
if (likely(connected(con)))
406+
ret = tipc_conn_rcv_sub(srv, con, &s);
404407
read_unlock_bh(&sk->sk_callback_lock);
405408
if (!ret)
406409
return 0;

0 commit comments

Comments
 (0)