diff options
Diffstat (limited to 'net/rds/threads.c')
-rw-r--r-- | net/rds/threads.c | 69 |
1 files changed, 58 insertions, 11 deletions
diff --git a/net/rds/threads.c b/net/rds/threads.c index c52861d77a59..e64f9e4c3cda 100644 --- a/net/rds/threads.c +++ b/net/rds/threads.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 Oracle. All rights reserved. | 2 | * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -82,8 +82,8 @@ void rds_connect_path_complete(struct rds_conn_path *cp, int curr) | |||
82 | return; | 82 | return; |
83 | } | 83 | } |
84 | 84 | ||
85 | rdsdebug("conn %p for %pI4 to %pI4 complete\n", | 85 | rdsdebug("conn %p for %pI6c to %pI6c complete\n", |
86 | cp->cp_conn, &cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr); | 86 | cp->cp_conn, &cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr); |
87 | 87 | ||
88 | cp->cp_reconnect_jiffies = 0; | 88 | cp->cp_reconnect_jiffies = 0; |
89 | set_bit(0, &cp->cp_conn->c_map_queued); | 89 | set_bit(0, &cp->cp_conn->c_map_queued); |
@@ -125,13 +125,13 @@ void rds_queue_reconnect(struct rds_conn_path *cp) | |||
125 | unsigned long rand; | 125 | unsigned long rand; |
126 | struct rds_connection *conn = cp->cp_conn; | 126 | struct rds_connection *conn = cp->cp_conn; |
127 | 127 | ||
128 | rdsdebug("conn %p for %pI4 to %pI4 reconnect jiffies %lu\n", | 128 | rdsdebug("conn %p for %pI6c to %pI6c reconnect jiffies %lu\n", |
129 | conn, &conn->c_laddr, &conn->c_faddr, | 129 | conn, &conn->c_laddr, &conn->c_faddr, |
130 | cp->cp_reconnect_jiffies); | 130 | cp->cp_reconnect_jiffies); |
131 | 131 | ||
132 | /* let peer with smaller addr initiate reconnect, to avoid duels */ | 132 | /* let peer with smaller addr initiate reconnect, to avoid duels */ |
133 | if (conn->c_trans->t_type == RDS_TRANS_TCP && | 133 | if (conn->c_trans->t_type == RDS_TRANS_TCP && |
134 | !IS_CANONICAL(conn->c_laddr, conn->c_faddr)) | 134 | rds_addr_cmp(&conn->c_laddr, &conn->c_faddr) >= 0) |
135 | return; | 135 | return; |
136 | 136 | ||
137 | set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); | 137 | set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); |
@@ -145,7 +145,7 @@ void rds_queue_reconnect(struct rds_conn_path *cp) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | get_random_bytes(&rand, sizeof(rand)); | 147 | get_random_bytes(&rand, sizeof(rand)); |
148 | rdsdebug("%lu delay %lu ceil conn %p for %pI4 -> %pI4\n", | 148 | rdsdebug("%lu delay %lu ceil conn %p for %pI6c -> %pI6c\n", |
149 | rand % cp->cp_reconnect_jiffies, cp->cp_reconnect_jiffies, | 149 | rand % cp->cp_reconnect_jiffies, cp->cp_reconnect_jiffies, |
150 | conn, &conn->c_laddr, &conn->c_faddr); | 150 | conn, &conn->c_laddr, &conn->c_faddr); |
151 | rcu_read_lock(); | 151 | rcu_read_lock(); |
@@ -167,14 +167,14 @@ void rds_connect_worker(struct work_struct *work) | |||
167 | int ret; | 167 | int ret; |
168 | 168 | ||
169 | if (cp->cp_index > 0 && | 169 | if (cp->cp_index > 0 && |
170 | !IS_CANONICAL(cp->cp_conn->c_laddr, cp->cp_conn->c_faddr)) | 170 | rds_addr_cmp(&cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr) >= 0) |
171 | return; | 171 | return; |
172 | clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); | 172 | clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); |
173 | ret = rds_conn_path_transition(cp, RDS_CONN_DOWN, RDS_CONN_CONNECTING); | 173 | ret = rds_conn_path_transition(cp, RDS_CONN_DOWN, RDS_CONN_CONNECTING); |
174 | if (ret) { | 174 | if (ret) { |
175 | ret = conn->c_trans->conn_path_connect(cp); | 175 | ret = conn->c_trans->conn_path_connect(cp); |
176 | rdsdebug("conn %p for %pI4 to %pI4 dispatched, ret %d\n", | 176 | rdsdebug("conn %p for %pI6c to %pI6c dispatched, ret %d\n", |
177 | conn, &conn->c_laddr, &conn->c_faddr, ret); | 177 | conn, &conn->c_laddr, &conn->c_faddr, ret); |
178 | 178 | ||
179 | if (ret) { | 179 | if (ret) { |
180 | if (rds_conn_path_transition(cp, | 180 | if (rds_conn_path_transition(cp, |
@@ -259,3 +259,50 @@ int rds_threads_init(void) | |||
259 | 259 | ||
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | |||
263 | /* Compare two IPv6 addresses. Return 0 if the two addresses are equal. | ||
264 | * Return 1 if the first is greater. Return -1 if the second is greater. | ||
265 | */ | ||
266 | int rds_addr_cmp(const struct in6_addr *addr1, | ||
267 | const struct in6_addr *addr2) | ||
268 | { | ||
269 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 | ||
270 | const __be64 *a1, *a2; | ||
271 | u64 x, y; | ||
272 | |||
273 | a1 = (__be64 *)addr1; | ||
274 | a2 = (__be64 *)addr2; | ||
275 | |||
276 | if (*a1 != *a2) { | ||
277 | if (be64_to_cpu(*a1) < be64_to_cpu(*a2)) | ||
278 | return -1; | ||
279 | else | ||
280 | return 1; | ||
281 | } else { | ||
282 | x = be64_to_cpu(*++a1); | ||
283 | y = be64_to_cpu(*++a2); | ||
284 | if (x < y) | ||
285 | return -1; | ||
286 | else if (x > y) | ||
287 | return 1; | ||
288 | else | ||
289 | return 0; | ||
290 | } | ||
291 | #else | ||
292 | u32 a, b; | ||
293 | int i; | ||
294 | |||
295 | for (i = 0; i < 4; i++) { | ||
296 | if (addr1->s6_addr32[i] != addr2->s6_addr32[i]) { | ||
297 | a = ntohl(addr1->s6_addr32[i]); | ||
298 | b = ntohl(addr2->s6_addr32[i]); | ||
299 | if (a < b) | ||
300 | return -1; | ||
301 | else if (a > b) | ||
302 | return 1; | ||
303 | } | ||
304 | } | ||
305 | return 0; | ||
306 | #endif | ||
307 | } | ||
308 | EXPORT_SYMBOL_GPL(rds_addr_cmp); | ||