From: Mukesh Kacker Date: Tue, 5 Feb 2019 00:21:28 +0000 (-0800) Subject: rds: update correct congestion map for loopback transport X-Git-Tag: v4.1.12-124.31.3~253 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7d3d00fa8582608951aaa6e8a4ed0caeab82aa0e;p=users%2Fjedix%2Flinux-maple.git rds: update correct congestion map for loopback transport Loopback transport delivers data directly to the destination socket since destination is always local to the machine. The connection data structure passed to an internal initializer API rds_inc_init() is from send side (unlike the usual call to APIs from receive path when receive side connection data structure is passed). This inconsistency causes an update of the incorrect congestion map when marking destination port congested when loopback transport is used (which is when one or both end(s) of a RDS connection has an IP loopback address). The fix it to ensure correct map is updated, that of the destination IP regardless of delivery coming from send side of loopback transport or receive side of other transports. Orabug: 29175685 Signed-off-by: Mukesh Kacker Reviewed-by: HÃ¥kon Bugge Signed-off-by: Brian Maly --- diff --git a/net/rds/loop.c b/net/rds/loop.c index 779bcc0effdb..2e6be3cb141e 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c @@ -70,8 +70,16 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm, BUG_ON(hdr_off || sg || off); + /* Note: This call to rds_inc_init() initializes the + * rm->m_inc but the embedded rm->m_inc->i_conn is + * the sending conn. (All other call instances embed + * the receiving conn as rm->m_inc->i_conn). Any code + * that uses local/remote struct fields of i_conn to + * imply sending/receiving side needs care! + */ rds_inc_init(&rm->m_inc, conn, &conn->c_laddr); /* For the embedded inc. Matching put is in loop_inc_free() */ + rds_message_addref(rm); rds_recv_incoming(conn, &conn->c_laddr, &conn->c_faddr, &rm->m_inc, diff --git a/net/rds/recv.c b/net/rds/recv.c index 4c5ad749db4b..eda40435b9f3 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -39,6 +39,7 @@ #include #include "rds.h" +#include "loop.h" /* forward prototypes */ static void @@ -136,14 +137,26 @@ void rds_inc_put(struct rds_incoming *inc) EXPORT_SYMBOL_GPL(rds_inc_put); static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk, - struct rds_cong_map *map, + struct rds_connection *conn, int delta, __be16 port) { int now_congested; + struct rds_cong_map *map; if (delta == 0) return; + /* Note: For loopback transport, the 'conn' passed is the + * sending endpoint, not the receiving endpoint. + * We want the congestion that corresponds to the + * destination(receiving)endpoint which is "local" for the + * receiving endpoint but "foreign" for the sending endpoint. + */ + if (conn->c_loopback && conn->c_trans == &rds_loop_transport) + map = conn->c_fcong; + else + map = conn->c_lcong; + rs->rs_rcv_bytes += delta; if (delta > 0) rds_stats_add(s_recv_bytes_added_to_socket, delta); @@ -726,9 +739,9 @@ rds_recv_local(struct rds_conn_path *cp, struct in6_addr *saddr, rdsdebug("adding inc %p to rs %p's recv queue\n", inc, rs); rds_stats_inc(s_recv_queued); - rds_recv_rcvbuf_delta(rs, sk, inc->i_conn->c_lcong, - be32_to_cpu(inc->i_hdr.h_len), - inc->i_hdr.h_dport); + rds_recv_rcvbuf_delta(rs, sk, inc->i_conn, + be32_to_cpu(inc->i_hdr.h_len), + inc->i_hdr.h_dport); if (sock_flag(sk, SOCK_RCVTSTAMP)) do_gettimeofday(&inc->i_rx_tstamp); rds_inc_addref(inc); @@ -780,7 +793,7 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc, ret = 1; if (drop) { /* XXX make sure this i_conn is reliable */ - rds_recv_rcvbuf_delta(rs, sk, inc->i_conn->c_lcong, + rds_recv_rcvbuf_delta(rs, sk, inc->i_conn, -be32_to_cpu(inc->i_hdr.h_len), inc->i_hdr.h_dport); list_del_init(&inc->i_item); @@ -1078,7 +1091,7 @@ void rds_clear_recv_queue(struct rds_sock *rs) write_lock_irqsave(&rs->rs_recv_lock, flags); list_for_each_entry_safe(inc, tmp, &rs->rs_recv_queue, i_item) { - rds_recv_rcvbuf_delta(rs, sk, inc->i_conn->c_lcong, + rds_recv_rcvbuf_delta(rs, sk, inc->i_conn, -be32_to_cpu(inc->i_hdr.h_len), inc->i_hdr.h_dport); list_del_init(&inc->i_item);