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,
#include <linux/rds.h>
#include "rds.h"
+#include "loop.h"
/* forward prototypes */
static void
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);
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);
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);
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);