aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSowmini Varadhan <sowmini.varadhan@oracle.com>2016-06-13 12:44:26 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-15 02:50:41 -0400
commit0cb43965d42a21a7af41f88f1021b478dc102425 (patch)
tree628e5ac505d94dd9cf1f2551737d9139eb58662f
parentdcf1158b275f9d51d6a742cf7166edc764ee4718 (diff)
RDS: split out connection specific state from rds_connection to rds_conn_path
In preparation for multipath RDS, split the rds_connection structure into a base structure, and a per-path struct rds_conn_path. The base structure tracks information and locks common to all paths. The workqs for send/recv/shutdown etc are tracked per rds_conn_path. Thus the workq callbacks now work with rds_conn_path. This commit allows for one rds_conn_path per rds_connection, and will be extended into multiple conn_paths in subsequent commits. Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/rds/cong.c3
-rw-r--r--net/rds/connection.c18
-rw-r--r--net/rds/ib.c1
-rw-r--r--net/rds/ib_cm.c1
-rw-r--r--net/rds/ib_rdma.c1
-rw-r--r--net/rds/ib_recv.c1
-rw-r--r--net/rds/ib_send.c1
-rw-r--r--net/rds/loop.c1
-rw-r--r--net/rds/rdma_transport.c1
-rw-r--r--net/rds/rds.h122
-rw-r--r--net/rds/rds_single_path.h30
-rw-r--r--net/rds/recv.c1
-rw-r--r--net/rds/send.c1
-rw-r--r--net/rds/tcp.c1
-rw-r--r--net/rds/tcp_connect.c4
-rw-r--r--net/rds/tcp_listen.c11
-rw-r--r--net/rds/tcp_recv.c1
-rw-r--r--net/rds/tcp_send.c1
-rw-r--r--net/rds/threads.c92
19 files changed, 199 insertions, 93 deletions
diff --git a/net/rds/cong.c b/net/rds/cong.c
index 6641bcf7c185..8398fee7c866 100644
--- a/net/rds/cong.c
+++ b/net/rds/cong.c
@@ -235,7 +235,8 @@ void rds_cong_queue_updates(struct rds_cong_map *map)
235 * therefore trigger warnings. 235 * therefore trigger warnings.
236 * Defer the xmit to rds_send_worker() instead. 236 * Defer the xmit to rds_send_worker() instead.
237 */ 237 */
238 queue_delayed_work(rds_wq, &conn->c_send_w, 0); 238 queue_delayed_work(rds_wq,
239 &conn->c_path[0].cp_send_w, 0);
239 } 240 }
240 } 241 }
241 242
diff --git a/net/rds/connection.c b/net/rds/connection.c
index e3b118cae81d..6fa2074044b9 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -36,6 +36,7 @@
36#include <linux/export.h> 36#include <linux/export.h>
37#include <net/inet_hashtables.h> 37#include <net/inet_hashtables.h>
38 38
39#include "rds_single_path.h"
39#include "rds.h" 40#include "rds.h"
40#include "loop.h" 41#include "loop.h"
41 42
@@ -155,6 +156,7 @@ static struct rds_connection *__rds_conn_create(struct net *net,
155 conn->c_faddr = faddr; 156 conn->c_faddr = faddr;
156 spin_lock_init(&conn->c_lock); 157 spin_lock_init(&conn->c_lock);
157 conn->c_next_tx_seq = 1; 158 conn->c_next_tx_seq = 1;
159 conn->c_path[0].cp_conn = conn;
158 rds_conn_net_set(conn, net); 160 rds_conn_net_set(conn, net);
159 161
160 init_waitqueue_head(&conn->c_waitq); 162 init_waitqueue_head(&conn->c_waitq);
@@ -197,7 +199,7 @@ static struct rds_connection *__rds_conn_create(struct net *net,
197 199
198 atomic_set(&conn->c_state, RDS_CONN_DOWN); 200 atomic_set(&conn->c_state, RDS_CONN_DOWN);
199 conn->c_send_gen = 0; 201 conn->c_send_gen = 0;
200 conn->c_outgoing = (is_outgoing ? 1 : 0); 202 conn->c_path[0].cp_outgoing = (is_outgoing ? 1 : 0);
201 conn->c_reconnect_jiffies = 0; 203 conn->c_reconnect_jiffies = 0;
202 INIT_DELAYED_WORK(&conn->c_send_w, rds_send_worker); 204 INIT_DELAYED_WORK(&conn->c_send_w, rds_send_worker);
203 INIT_DELAYED_WORK(&conn->c_recv_w, rds_recv_worker); 205 INIT_DELAYED_WORK(&conn->c_recv_w, rds_recv_worker);
@@ -320,8 +322,8 @@ void rds_conn_shutdown(struct rds_connection *conn)
320 if (!hlist_unhashed(&conn->c_hash_node)) { 322 if (!hlist_unhashed(&conn->c_hash_node)) {
321 rcu_read_unlock(); 323 rcu_read_unlock();
322 if (conn->c_trans->t_type != RDS_TRANS_TCP || 324 if (conn->c_trans->t_type != RDS_TRANS_TCP ||
323 conn->c_outgoing == 1) 325 conn->c_path[0].cp_outgoing == 1)
324 rds_queue_reconnect(conn); 326 rds_queue_reconnect(&conn->c_path[0]);
325 } else { 327 } else {
326 rcu_read_unlock(); 328 rcu_read_unlock();
327 } 329 }
@@ -553,10 +555,16 @@ void rds_conn_exit(void)
553/* 555/*
554 * Force a disconnect 556 * Force a disconnect
555 */ 557 */
558void rds_conn_path_drop(struct rds_conn_path *cp)
559{
560 atomic_set(&cp->cp_state, RDS_CONN_ERROR);
561 queue_work(rds_wq, &cp->cp_down_w);
562}
563EXPORT_SYMBOL_GPL(rds_conn_path_drop);
564
556void rds_conn_drop(struct rds_connection *conn) 565void rds_conn_drop(struct rds_connection *conn)
557{ 566{
558 atomic_set(&conn->c_state, RDS_CONN_ERROR); 567 rds_conn_path_drop(&conn->c_path[0]);
559 queue_work(rds_wq, &conn->c_down_w);
560} 568}
561EXPORT_SYMBOL_GPL(rds_conn_drop); 569EXPORT_SYMBOL_GPL(rds_conn_drop);
562 570
diff --git a/net/rds/ib.c b/net/rds/ib.c
index b5342fddaf98..44946a681a8c 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -40,6 +40,7 @@
40#include <linux/slab.h> 40#include <linux/slab.h>
41#include <linux/module.h> 41#include <linux/module.h>
42 42
43#include "rds_single_path.h"
43#include "rds.h" 44#include "rds.h"
44#include "ib.h" 45#include "ib.h"
45#include "ib_mr.h" 46#include "ib_mr.h"
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index 310cabce2311..4de5a35f5c40 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -36,6 +36,7 @@
36#include <linux/vmalloc.h> 36#include <linux/vmalloc.h>
37#include <linux/ratelimit.h> 37#include <linux/ratelimit.h>
38 38
39#include "rds_single_path.h"
39#include "rds.h" 40#include "rds.h"
40#include "ib.h" 41#include "ib.h"
41 42
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index a0f21b65a83c..977f69886c00 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -35,6 +35,7 @@
35#include <linux/rculist.h> 35#include <linux/rculist.h>
36#include <linux/llist.h> 36#include <linux/llist.h>
37 37
38#include "rds_single_path.h"
38#include "ib_mr.h" 39#include "ib_mr.h"
39 40
40struct workqueue_struct *rds_ib_mr_wq; 41struct workqueue_struct *rds_ib_mr_wq;
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index abc8cc805e8d..4ea8cb17cc7a 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -36,6 +36,7 @@
36#include <linux/dma-mapping.h> 36#include <linux/dma-mapping.h>
37#include <rdma/rdma_cm.h> 37#include <rdma/rdma_cm.h>
38 38
39#include "rds_single_path.h"
39#include "rds.h" 40#include "rds.h"
40#include "ib.h" 41#include "ib.h"
41 42
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c
index f27d2c82b036..6e4110aa5135 100644
--- a/net/rds/ib_send.c
+++ b/net/rds/ib_send.c
@@ -36,6 +36,7 @@
36#include <linux/dmapool.h> 36#include <linux/dmapool.h>
37#include <linux/ratelimit.h> 37#include <linux/ratelimit.h>
38 38
39#include "rds_single_path.h"
39#include "rds.h" 40#include "rds.h"
40#include "ib.h" 41#include "ib.h"
41 42
diff --git a/net/rds/loop.c b/net/rds/loop.c
index 6b12b68541ae..268f07faaa1a 100644
--- a/net/rds/loop.c
+++ b/net/rds/loop.c
@@ -34,6 +34,7 @@
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/in.h> 35#include <linux/in.h>
36 36
37#include "rds_single_path.h"
37#include "rds.h" 38#include "rds.h"
38#include "loop.h" 39#include "loop.h"
39 40
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c
index 7220bebcf558..345f09059e9f 100644
--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -33,6 +33,7 @@
33#include <linux/module.h> 33#include <linux/module.h>
34#include <rdma/rdma_cm.h> 34#include <rdma/rdma_cm.h>
35 35
36#include "rds_single_path.h"
36#include "rdma_transport.h" 37#include "rdma_transport.h"
37#include "ib.h" 38#include "ib.h"
38 39
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 387df5f32e49..ca31a07f70f5 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -84,56 +84,69 @@ enum {
84#define RDS_IN_XMIT 2 84#define RDS_IN_XMIT 2
85#define RDS_RECV_REFILL 3 85#define RDS_RECV_REFILL 3
86 86
87/* Max number of multipaths per RDS connection. Must be a power of 2 */
88#define RDS_MPATH_WORKERS 1
89
90/* Per mpath connection state */
91struct rds_conn_path {
92 struct rds_connection *cp_conn;
93 struct rds_message *cp_xmit_rm;
94 unsigned long cp_xmit_sg;
95 unsigned int cp_xmit_hdr_off;
96 unsigned int cp_xmit_data_off;
97 unsigned int cp_xmit_atomic_sent;
98 unsigned int cp_xmit_rdma_sent;
99 unsigned int cp_xmit_data_sent;
100
101 spinlock_t cp_lock; /* protect msg queues */
102 u64 cp_next_tx_seq;
103 struct list_head cp_send_queue;
104 struct list_head cp_retrans;
105
106 u64 cp_next_rx_seq;
107
108 void *cp_transport_data;
109
110 atomic_t cp_state;
111 unsigned long cp_send_gen;
112 unsigned long cp_flags;
113 unsigned long cp_reconnect_jiffies;
114 struct delayed_work cp_send_w;
115 struct delayed_work cp_recv_w;
116 struct delayed_work cp_conn_w;
117 struct work_struct cp_down_w;
118 struct mutex cp_cm_lock; /* protect cp_state & cm */
119 wait_queue_head_t cp_waitq;
120
121 unsigned int cp_unacked_packets;
122 unsigned int cp_unacked_bytes;
123 unsigned int cp_outgoing:1,
124 cp_pad_to_32:31;
125 unsigned int cp_index;
126};
127
128/* One rds_connection per RDS address pair */
87struct rds_connection { 129struct rds_connection {
88 struct hlist_node c_hash_node; 130 struct hlist_node c_hash_node;
89 __be32 c_laddr; 131 __be32 c_laddr;
90 __be32 c_faddr; 132 __be32 c_faddr;
91 unsigned int c_loopback:1, 133 unsigned int c_loopback:1,
92 c_outgoing:1, 134 c_pad_to_32:31;
93 c_pad_to_32:30; 135 int c_npaths;
94 struct rds_connection *c_passive; 136 struct rds_connection *c_passive;
137 struct rds_transport *c_trans;
95 138
96 struct rds_cong_map *c_lcong; 139 struct rds_cong_map *c_lcong;
97 struct rds_cong_map *c_fcong; 140 struct rds_cong_map *c_fcong;
98 141
99 struct rds_message *c_xmit_rm; 142 /* Protocol version */
100 unsigned long c_xmit_sg; 143 unsigned int c_version;
101 unsigned int c_xmit_hdr_off; 144 possible_net_t c_net;
102 unsigned int c_xmit_data_off;
103 unsigned int c_xmit_atomic_sent;
104 unsigned int c_xmit_rdma_sent;
105 unsigned int c_xmit_data_sent;
106
107 spinlock_t c_lock; /* protect msg queues */
108 u64 c_next_tx_seq;
109 struct list_head c_send_queue;
110 struct list_head c_retrans;
111
112 u64 c_next_rx_seq;
113
114 struct rds_transport *c_trans;
115 void *c_transport_data;
116
117 atomic_t c_state;
118 unsigned long c_send_gen;
119 unsigned long c_flags;
120 unsigned long c_reconnect_jiffies;
121 struct delayed_work c_send_w;
122 struct delayed_work c_recv_w;
123 struct delayed_work c_conn_w;
124 struct work_struct c_down_w;
125 struct mutex c_cm_lock; /* protect conn state & cm */
126 wait_queue_head_t c_waitq;
127 145
128 struct list_head c_map_item; 146 struct list_head c_map_item;
129 unsigned long c_map_queued; 147 unsigned long c_map_queued;
130 148
131 unsigned int c_unacked_packets; 149 struct rds_conn_path c_path[RDS_MPATH_WORKERS];
132 unsigned int c_unacked_bytes;
133
134 /* Protocol version */
135 unsigned int c_version;
136 possible_net_t c_net;
137}; 150};
138 151
139static inline 152static inline
@@ -639,6 +652,7 @@ struct rds_connection *rds_conn_create_outgoing(struct net *net,
639void rds_conn_shutdown(struct rds_connection *conn); 652void rds_conn_shutdown(struct rds_connection *conn);
640void rds_conn_destroy(struct rds_connection *conn); 653void rds_conn_destroy(struct rds_connection *conn);
641void rds_conn_drop(struct rds_connection *conn); 654void rds_conn_drop(struct rds_connection *conn);
655void rds_conn_path_drop(struct rds_conn_path *cpath);
642void rds_conn_connect_if_down(struct rds_connection *conn); 656void rds_conn_connect_if_down(struct rds_connection *conn);
643void rds_for_each_conn_info(struct socket *sock, unsigned int len, 657void rds_for_each_conn_info(struct socket *sock, unsigned int len,
644 struct rds_info_iterator *iter, 658 struct rds_info_iterator *iter,
@@ -651,27 +665,51 @@ void __rds_conn_error(struct rds_connection *conn, const char *, ...);
651 __rds_conn_error(conn, KERN_WARNING "RDS: " fmt) 665 __rds_conn_error(conn, KERN_WARNING "RDS: " fmt)
652 666
653static inline int 667static inline int
668rds_conn_path_transition(struct rds_conn_path *cp, int old, int new)
669{
670 return atomic_cmpxchg(&cp->cp_state, old, new) == old;
671}
672
673static inline int
654rds_conn_transition(struct rds_connection *conn, int old, int new) 674rds_conn_transition(struct rds_connection *conn, int old, int new)
655{ 675{
656 return atomic_cmpxchg(&conn->c_state, old, new) == old; 676 return rds_conn_path_transition(&conn->c_path[0], old, new);
677}
678
679static inline int
680rds_conn_path_state(struct rds_conn_path *cp)
681{
682 return atomic_read(&cp->cp_state);
657} 683}
658 684
659static inline int 685static inline int
660rds_conn_state(struct rds_connection *conn) 686rds_conn_state(struct rds_connection *conn)
661{ 687{
662 return atomic_read(&conn->c_state); 688 return rds_conn_path_state(&conn->c_path[0]);
689}
690
691static inline int
692rds_conn_path_up(struct rds_conn_path *cp)
693{
694 return atomic_read(&cp->cp_state) == RDS_CONN_UP;
663} 695}
664 696
665static inline int 697static inline int
666rds_conn_up(struct rds_connection *conn) 698rds_conn_up(struct rds_connection *conn)
667{ 699{
668 return atomic_read(&conn->c_state) == RDS_CONN_UP; 700 return rds_conn_path_up(&conn->c_path[0]);
701}
702
703static inline int
704rds_conn_path_connecting(struct rds_conn_path *cp)
705{
706 return atomic_read(&cp->cp_state) == RDS_CONN_CONNECTING;
669} 707}
670 708
671static inline int 709static inline int
672rds_conn_connecting(struct rds_connection *conn) 710rds_conn_connecting(struct rds_connection *conn)
673{ 711{
674 return atomic_read(&conn->c_state) == RDS_CONN_CONNECTING; 712 return rds_conn_path_connecting(&conn->c_path[0]);
675} 713}
676 714
677/* message.c */ 715/* message.c */
@@ -809,12 +847,12 @@ extern unsigned int rds_sysctl_trace_level;
809int rds_threads_init(void); 847int rds_threads_init(void);
810void rds_threads_exit(void); 848void rds_threads_exit(void);
811extern struct workqueue_struct *rds_wq; 849extern struct workqueue_struct *rds_wq;
812void rds_queue_reconnect(struct rds_connection *conn); 850void rds_queue_reconnect(struct rds_conn_path *cp);
813void rds_connect_worker(struct work_struct *); 851void rds_connect_worker(struct work_struct *);
814void rds_shutdown_worker(struct work_struct *); 852void rds_shutdown_worker(struct work_struct *);
815void rds_send_worker(struct work_struct *); 853void rds_send_worker(struct work_struct *);
816void rds_recv_worker(struct work_struct *); 854void rds_recv_worker(struct work_struct *);
817void rds_connect_path_complete(struct rds_connection *conn, int curr); 855void rds_connect_path_complete(struct rds_conn_path *conn, int curr);
818void rds_connect_complete(struct rds_connection *conn); 856void rds_connect_complete(struct rds_connection *conn);
819 857
820/* transport.c */ 858/* transport.c */
diff --git a/net/rds/rds_single_path.h b/net/rds/rds_single_path.h
new file mode 100644
index 000000000000..e1241af7c1ad
--- /dev/null
+++ b/net/rds/rds_single_path.h
@@ -0,0 +1,30 @@
1#ifndef _RDS_RDS_SINGLE_H
2#define _RDS_RDS_SINGLE_H
3
4#define c_xmit_rm c_path[0].cp_xmit_rm
5#define c_xmit_sg c_path[0].cp_xmit_sg
6#define c_xmit_hdr_off c_path[0].cp_xmit_hdr_off
7#define c_xmit_data_off c_path[0].cp_xmit_data_off
8#define c_xmit_atomic_sent c_path[0].cp_xmit_atomic_sent
9#define c_xmit_rdma_sent c_path[0].cp_xmit_rdma_sent
10#define c_xmit_data_sent c_path[0].cp_xmit_data_sent
11#define c_lock c_path[0].cp_lock
12#define c_next_tx_seq c_path[0].cp_next_tx_seq
13#define c_send_queue c_path[0].cp_send_queue
14#define c_retrans c_path[0].cp_retrans
15#define c_next_rx_seq c_path[0].cp_next_rx_seq
16#define c_transport_data c_path[0].cp_transport_data
17#define c_state c_path[0].cp_state
18#define c_send_gen c_path[0].cp_send_gen
19#define c_flags c_path[0].cp_flags
20#define c_reconnect_jiffies c_path[0].cp_reconnect_jiffies
21#define c_send_w c_path[0].cp_send_w
22#define c_recv_w c_path[0].cp_recv_w
23#define c_conn_w c_path[0].cp_conn_w
24#define c_down_w c_path[0].cp_down_w
25#define c_cm_lock c_path[0].cp_cm_lock
26#define c_waitq c_path[0].cp_waitq
27#define c_unacked_packets c_path[0].cp_unacked_packets
28#define c_unacked_bytes c_path[0].cp_unacked_bytes
29
30#endif /* _RDS_RDS_SINGLE_H */
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 8413f6c99e13..78b5c430324d 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -38,6 +38,7 @@
38#include <linux/time.h> 38#include <linux/time.h>
39#include <linux/rds.h> 39#include <linux/rds.h>
40 40
41#include "rds_single_path.h"
41#include "rds.h" 42#include "rds.h"
42 43
43void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn, 44void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
diff --git a/net/rds/send.c b/net/rds/send.c
index b1962f8e30f7..a3b3b35ad57a 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -40,6 +40,7 @@
40#include <linux/export.h> 40#include <linux/export.h>
41#include <linux/sizes.h> 41#include <linux/sizes.h>
42 42
43#include "rds_single_path.h"
43#include "rds.h" 44#include "rds.h"
44 45
45/* When transmitting messages in rds_send_xmit, we need to emerge from 46/* When transmitting messages in rds_send_xmit, we need to emerge from
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 74ee126a6fe6..4bc1c153e93a 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -38,6 +38,7 @@
38#include <net/net_namespace.h> 38#include <net/net_namespace.h>
39#include <net/netns/generic.h> 39#include <net/netns/generic.h>
40 40
41#include "rds_single_path.h"
41#include "rds.h" 42#include "rds.h"
42#include "tcp.h" 43#include "tcp.h"
43 44
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c
index fba13d0305fb..ba9ec67f4e41 100644
--- a/net/rds/tcp_connect.c
+++ b/net/rds/tcp_connect.c
@@ -34,6 +34,7 @@
34#include <linux/in.h> 34#include <linux/in.h>
35#include <net/tcp.h> 35#include <net/tcp.h>
36 36
37#include "rds_single_path.h"
37#include "rds.h" 38#include "rds.h"
38#include "tcp.h" 39#include "tcp.h"
39 40
@@ -60,7 +61,8 @@ void rds_tcp_state_change(struct sock *sk)
60 case TCP_SYN_RECV: 61 case TCP_SYN_RECV:
61 break; 62 break;
62 case TCP_ESTABLISHED: 63 case TCP_ESTABLISHED:
63 rds_connect_path_complete(conn, RDS_CONN_CONNECTING); 64 rds_connect_path_complete(&conn->c_path[0],
65 RDS_CONN_CONNECTING);
64 break; 66 break;
65 case TCP_CLOSE_WAIT: 67 case TCP_CLOSE_WAIT:
66 case TCP_CLOSE: 68 case TCP_CLOSE:
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index 686b1d03a558..22d9bb15f731 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -35,6 +35,7 @@
35#include <linux/in.h> 35#include <linux/in.h>
36#include <net/tcp.h> 36#include <net/tcp.h>
37 37
38#include "rds_single_path.h"
38#include "rds.h" 39#include "rds.h"
39#include "tcp.h" 40#include "tcp.h"
40 41
@@ -132,17 +133,19 @@ int rds_tcp_accept_one(struct socket *sock)
132 * c_transport_data. 133 * c_transport_data.
133 */ 134 */
134 if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr) || 135 if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr) ||
135 !conn->c_outgoing) { 136 !conn->c_path[0].cp_outgoing) {
136 goto rst_nsk; 137 goto rst_nsk;
137 } else { 138 } else {
138 rds_tcp_reset_callbacks(new_sock, conn); 139 rds_tcp_reset_callbacks(new_sock, conn);
139 conn->c_outgoing = 0; 140 conn->c_path[0].cp_outgoing = 0;
140 /* rds_connect_path_complete() marks RDS_CONN_UP */ 141 /* rds_connect_path_complete() marks RDS_CONN_UP */
141 rds_connect_path_complete(conn, RDS_CONN_DISCONNECTING); 142 rds_connect_path_complete(&conn->c_path[0],
143 RDS_CONN_DISCONNECTING);
142 } 144 }
143 } else { 145 } else {
144 rds_tcp_set_callbacks(new_sock, conn); 146 rds_tcp_set_callbacks(new_sock, conn);
145 rds_connect_path_complete(conn, RDS_CONN_CONNECTING); 147 rds_connect_path_complete(&conn->c_path[0],
148 RDS_CONN_CONNECTING);
146 } 149 }
147 new_sock = NULL; 150 new_sock = NULL;
148 ret = 0; 151 ret = 0;
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c
index c3196f9d070a..3f8fb38996c7 100644
--- a/net/rds/tcp_recv.c
+++ b/net/rds/tcp_recv.c
@@ -34,6 +34,7 @@
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <net/tcp.h> 35#include <net/tcp.h>
36 36
37#include "rds_single_path.h"
37#include "rds.h" 38#include "rds.h"
38#include "tcp.h" 39#include "tcp.h"
39 40
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c
index 22d0f2020a79..2b3414f3c45c 100644
--- a/net/rds/tcp_send.c
+++ b/net/rds/tcp_send.c
@@ -34,6 +34,7 @@
34#include <linux/in.h> 34#include <linux/in.h>
35#include <net/tcp.h> 35#include <net/tcp.h>
36 36
37#include "rds_single_path.h"
37#include "rds.h" 38#include "rds.h"
38#include "tcp.h" 39#include "tcp.h"
39 40
diff --git a/net/rds/threads.c b/net/rds/threads.c
index 4a323045719b..6d0979b8dc63 100644
--- a/net/rds/threads.c
+++ b/net/rds/threads.c
@@ -71,30 +71,30 @@
71struct workqueue_struct *rds_wq; 71struct workqueue_struct *rds_wq;
72EXPORT_SYMBOL_GPL(rds_wq); 72EXPORT_SYMBOL_GPL(rds_wq);
73 73
74void rds_connect_path_complete(struct rds_connection *conn, int curr) 74void rds_connect_path_complete(struct rds_conn_path *cp, int curr)
75{ 75{
76 if (!rds_conn_transition(conn, curr, RDS_CONN_UP)) { 76 if (!rds_conn_path_transition(cp, curr, RDS_CONN_UP)) {
77 printk(KERN_WARNING "%s: Cannot transition to state UP, " 77 printk(KERN_WARNING "%s: Cannot transition to state UP, "
78 "current state is %d\n", 78 "current state is %d\n",
79 __func__, 79 __func__,
80 atomic_read(&conn->c_state)); 80 atomic_read(&cp->cp_state));
81 rds_conn_drop(conn); 81 rds_conn_path_drop(cp);
82 return; 82 return;
83 } 83 }
84 84
85 rdsdebug("conn %p for %pI4 to %pI4 complete\n", 85 rdsdebug("conn %p for %pI4 to %pI4 complete\n",
86 conn, &conn->c_laddr, &conn->c_faddr); 86 cp->cp_conn, &cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr);
87 87
88 conn->c_reconnect_jiffies = 0; 88 cp->cp_reconnect_jiffies = 0;
89 set_bit(0, &conn->c_map_queued); 89 set_bit(0, &cp->cp_conn->c_map_queued);
90 queue_delayed_work(rds_wq, &conn->c_send_w, 0); 90 queue_delayed_work(rds_wq, &cp->cp_send_w, 0);
91 queue_delayed_work(rds_wq, &conn->c_recv_w, 0); 91 queue_delayed_work(rds_wq, &cp->cp_recv_w, 0);
92} 92}
93EXPORT_SYMBOL_GPL(rds_connect_path_complete); 93EXPORT_SYMBOL_GPL(rds_connect_path_complete);
94 94
95void rds_connect_complete(struct rds_connection *conn) 95void rds_connect_complete(struct rds_connection *conn)
96{ 96{
97 rds_connect_path_complete(conn, RDS_CONN_CONNECTING); 97 rds_connect_path_complete(&conn->c_path[0], RDS_CONN_CONNECTING);
98} 98}
99EXPORT_SYMBOL_GPL(rds_connect_complete); 99EXPORT_SYMBOL_GPL(rds_connect_complete);
100 100
@@ -116,46 +116,52 @@ EXPORT_SYMBOL_GPL(rds_connect_complete);
116 * We should *always* start with a random backoff; otherwise a broken connection 116 * We should *always* start with a random backoff; otherwise a broken connection
117 * will always take several iterations to be re-established. 117 * will always take several iterations to be re-established.
118 */ 118 */
119void rds_queue_reconnect(struct rds_connection *conn) 119void rds_queue_reconnect(struct rds_conn_path *cp)
120{ 120{
121 unsigned long rand; 121 unsigned long rand;
122 struct rds_connection *conn = cp->cp_conn;
122 123
123 rdsdebug("conn %p for %pI4 to %pI4 reconnect jiffies %lu\n", 124 rdsdebug("conn %p for %pI4 to %pI4 reconnect jiffies %lu\n",
124 conn, &conn->c_laddr, &conn->c_faddr, 125 conn, &conn->c_laddr, &conn->c_faddr,
125 conn->c_reconnect_jiffies); 126 cp->cp_reconnect_jiffies);
126 127
127 set_bit(RDS_RECONNECT_PENDING, &conn->c_flags); 128 set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
128 if (conn->c_reconnect_jiffies == 0) { 129 if (cp->cp_reconnect_jiffies == 0) {
129 conn->c_reconnect_jiffies = rds_sysctl_reconnect_min_jiffies; 130 cp->cp_reconnect_jiffies = rds_sysctl_reconnect_min_jiffies;
130 queue_delayed_work(rds_wq, &conn->c_conn_w, 0); 131 queue_delayed_work(rds_wq, &cp->cp_conn_w, 0);
131 return; 132 return;
132 } 133 }
133 134
134 get_random_bytes(&rand, sizeof(rand)); 135 get_random_bytes(&rand, sizeof(rand));
135 rdsdebug("%lu delay %lu ceil conn %p for %pI4 -> %pI4\n", 136 rdsdebug("%lu delay %lu ceil conn %p for %pI4 -> %pI4\n",
136 rand % conn->c_reconnect_jiffies, conn->c_reconnect_jiffies, 137 rand % cp->cp_reconnect_jiffies, cp->cp_reconnect_jiffies,
137 conn, &conn->c_laddr, &conn->c_faddr); 138 conn, &conn->c_laddr, &conn->c_faddr);
138 queue_delayed_work(rds_wq, &conn->c_conn_w, 139 queue_delayed_work(rds_wq, &cp->cp_conn_w,
139 rand % conn->c_reconnect_jiffies); 140 rand % cp->cp_reconnect_jiffies);
140 141
141 conn->c_reconnect_jiffies = min(conn->c_reconnect_jiffies * 2, 142 cp->cp_reconnect_jiffies = min(cp->cp_reconnect_jiffies * 2,
142 rds_sysctl_reconnect_max_jiffies); 143 rds_sysctl_reconnect_max_jiffies);
143} 144}
144 145
145void rds_connect_worker(struct work_struct *work) 146void rds_connect_worker(struct work_struct *work)
146{ 147{
147 struct rds_connection *conn = container_of(work, struct rds_connection, c_conn_w.work); 148 struct rds_conn_path *cp = container_of(work,
149 struct rds_conn_path,
150 cp_conn_w.work);
151 struct rds_connection *conn = cp->cp_conn;
148 int ret; 152 int ret;
149 153
150 clear_bit(RDS_RECONNECT_PENDING, &conn->c_flags); 154 clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
151 if (rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING)) { 155 if (rds_conn_path_transition(cp, RDS_CONN_DOWN, RDS_CONN_CONNECTING)) {
152 ret = conn->c_trans->conn_connect(conn); 156 ret = conn->c_trans->conn_connect(conn);
153 rdsdebug("conn %p for %pI4 to %pI4 dispatched, ret %d\n", 157 rdsdebug("conn %p for %pI4 to %pI4 dispatched, ret %d\n",
154 conn, &conn->c_laddr, &conn->c_faddr, ret); 158 conn, &conn->c_laddr, &conn->c_faddr, ret);
155 159
156 if (ret) { 160 if (ret) {
157 if (rds_conn_transition(conn, RDS_CONN_CONNECTING, RDS_CONN_DOWN)) 161 if (rds_conn_path_transition(cp,
158 rds_queue_reconnect(conn); 162 RDS_CONN_CONNECTING,
163 RDS_CONN_DOWN))
164 rds_queue_reconnect(cp);
159 else 165 else
160 rds_conn_error(conn, "RDS: connect failed\n"); 166 rds_conn_error(conn, "RDS: connect failed\n");
161 } 167 }
@@ -164,22 +170,24 @@ void rds_connect_worker(struct work_struct *work)
164 170
165void rds_send_worker(struct work_struct *work) 171void rds_send_worker(struct work_struct *work)
166{ 172{
167 struct rds_connection *conn = container_of(work, struct rds_connection, c_send_w.work); 173 struct rds_conn_path *cp = container_of(work,
174 struct rds_conn_path,
175 cp_send_w.work);
168 int ret; 176 int ret;
169 177
170 if (rds_conn_state(conn) == RDS_CONN_UP) { 178 if (rds_conn_path_state(cp) == RDS_CONN_UP) {
171 clear_bit(RDS_LL_SEND_FULL, &conn->c_flags); 179 clear_bit(RDS_LL_SEND_FULL, &cp->cp_flags);
172 ret = rds_send_xmit(conn); 180 ret = rds_send_xmit(cp->cp_conn);
173 cond_resched(); 181 cond_resched();
174 rdsdebug("conn %p ret %d\n", conn, ret); 182 rdsdebug("conn %p ret %d\n", cp->cp_conn, ret);
175 switch (ret) { 183 switch (ret) {
176 case -EAGAIN: 184 case -EAGAIN:
177 rds_stats_inc(s_send_immediate_retry); 185 rds_stats_inc(s_send_immediate_retry);
178 queue_delayed_work(rds_wq, &conn->c_send_w, 0); 186 queue_delayed_work(rds_wq, &cp->cp_send_w, 0);
179 break; 187 break;
180 case -ENOMEM: 188 case -ENOMEM:
181 rds_stats_inc(s_send_delayed_retry); 189 rds_stats_inc(s_send_delayed_retry);
182 queue_delayed_work(rds_wq, &conn->c_send_w, 2); 190 queue_delayed_work(rds_wq, &cp->cp_send_w, 2);
183 default: 191 default:
184 break; 192 break;
185 } 193 }
@@ -188,20 +196,22 @@ void rds_send_worker(struct work_struct *work)
188 196
189void rds_recv_worker(struct work_struct *work) 197void rds_recv_worker(struct work_struct *work)
190{ 198{
191 struct rds_connection *conn = container_of(work, struct rds_connection, c_recv_w.work); 199 struct rds_conn_path *cp = container_of(work,
200 struct rds_conn_path,
201 cp_recv_w.work);
192 int ret; 202 int ret;
193 203
194 if (rds_conn_state(conn) == RDS_CONN_UP) { 204 if (rds_conn_path_state(cp) == RDS_CONN_UP) {
195 ret = conn->c_trans->recv(conn); 205 ret = cp->cp_conn->c_trans->recv(cp->cp_conn);
196 rdsdebug("conn %p ret %d\n", conn, ret); 206 rdsdebug("conn %p ret %d\n", cp->cp_conn, ret);
197 switch (ret) { 207 switch (ret) {
198 case -EAGAIN: 208 case -EAGAIN:
199 rds_stats_inc(s_recv_immediate_retry); 209 rds_stats_inc(s_recv_immediate_retry);
200 queue_delayed_work(rds_wq, &conn->c_recv_w, 0); 210 queue_delayed_work(rds_wq, &cp->cp_recv_w, 0);
201 break; 211 break;
202 case -ENOMEM: 212 case -ENOMEM:
203 rds_stats_inc(s_recv_delayed_retry); 213 rds_stats_inc(s_recv_delayed_retry);
204 queue_delayed_work(rds_wq, &conn->c_recv_w, 2); 214 queue_delayed_work(rds_wq, &cp->cp_recv_w, 2);
205 default: 215 default:
206 break; 216 break;
207 } 217 }
@@ -210,9 +220,11 @@ void rds_recv_worker(struct work_struct *work)
210 220
211void rds_shutdown_worker(struct work_struct *work) 221void rds_shutdown_worker(struct work_struct *work)
212{ 222{
213 struct rds_connection *conn = container_of(work, struct rds_connection, c_down_w); 223 struct rds_conn_path *cp = container_of(work,
224 struct rds_conn_path,
225 cp_down_w);
214 226
215 rds_conn_shutdown(conn); 227 rds_conn_shutdown(cp->cp_conn);
216} 228}
217 229
218void rds_threads_exit(void) 230void rds_threads_exit(void)