]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rds: update correct congestion map for loopback transport
authorMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 5 Feb 2019 00:21:28 +0000 (16:21 -0800)
committerBrian Maly <brian.maly@oracle.com>
Tue, 5 Mar 2019 22:31:36 +0000 (17:31 -0500)
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 <mukesh.kacker@oracle.com>
Reviewed-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
net/rds/loop.c
net/rds/recv.c

index 779bcc0effdb3522234c8a1bcfb2943a22a7fb3c..2e6be3cb141eb56b8985f516b0d04b2de91a8979 100644 (file)
@@ -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,
index 4c5ad749db4b08dc66055e21255a42950ba7f550..eda40435b9f3a3194b0d9d80b5c810f3462bc97c 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/rds.h>
 
 #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);