aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dlm/config.c79
-rw-r--r--fs/dlm/config.h2
-rw-r--r--fs/dlm/lowcomms.c205
-rw-r--r--fs/dlm/lowcomms.h2
-rw-r--r--fs/dlm/main.c2
5 files changed, 200 insertions, 90 deletions
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 9ccf7346834a..a0387dd8b1f0 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -750,6 +750,7 @@ static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
750static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) 750static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
751{ 751{
752 struct sockaddr_storage *addr; 752 struct sockaddr_storage *addr;
753 int rv;
753 754
754 if (len != sizeof(struct sockaddr_storage)) 755 if (len != sizeof(struct sockaddr_storage))
755 return -EINVAL; 756 return -EINVAL;
@@ -762,6 +763,13 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
762 return -ENOMEM; 763 return -ENOMEM;
763 764
764 memcpy(addr, buf, len); 765 memcpy(addr, buf, len);
766
767 rv = dlm_lowcomms_addr(cm->nodeid, addr, len);
768 if (rv) {
769 kfree(addr);
770 return rv;
771 }
772
765 cm->addr[cm->addr_count++] = addr; 773 cm->addr[cm->addr_count++] = addr;
766 return len; 774 return len;
767} 775}
@@ -878,34 +886,7 @@ static void put_space(struct dlm_space *sp)
878 config_item_put(&sp->group.cg_item); 886 config_item_put(&sp->group.cg_item);
879} 887}
880 888
881static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y) 889static struct dlm_comm *get_comm(int nodeid)
882{
883 switch (x->ss_family) {
884 case AF_INET: {
885 struct sockaddr_in *sinx = (struct sockaddr_in *)x;
886 struct sockaddr_in *siny = (struct sockaddr_in *)y;
887 if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
888 return 0;
889 if (sinx->sin_port != siny->sin_port)
890 return 0;
891 break;
892 }
893 case AF_INET6: {
894 struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
895 struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
896 if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
897 return 0;
898 if (sinx->sin6_port != siny->sin6_port)
899 return 0;
900 break;
901 }
902 default:
903 return 0;
904 }
905 return 1;
906}
907
908static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
909{ 890{
910 struct config_item *i; 891 struct config_item *i;
911 struct dlm_comm *cm = NULL; 892 struct dlm_comm *cm = NULL;
@@ -919,19 +900,11 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
919 list_for_each_entry(i, &comm_list->cg_children, ci_entry) { 900 list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
920 cm = config_item_to_comm(i); 901 cm = config_item_to_comm(i);
921 902
922 if (nodeid) { 903 if (cm->nodeid != nodeid)
923 if (cm->nodeid != nodeid) 904 continue;
924 continue; 905 found = 1;
925 found = 1; 906 config_item_get(i);
926 config_item_get(i); 907 break;
927 break;
928 } else {
929 if (!cm->addr_count || !addr_compare(cm->addr[0], addr))
930 continue;
931 found = 1;
932 config_item_get(i);
933 break;
934 }
935 } 908 }
936 mutex_unlock(&clusters_root.subsys.su_mutex); 909 mutex_unlock(&clusters_root.subsys.su_mutex);
937 910
@@ -995,7 +968,7 @@ int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
995 968
996int dlm_comm_seq(int nodeid, uint32_t *seq) 969int dlm_comm_seq(int nodeid, uint32_t *seq)
997{ 970{
998 struct dlm_comm *cm = get_comm(nodeid, NULL); 971 struct dlm_comm *cm = get_comm(nodeid);
999 if (!cm) 972 if (!cm)
1000 return -EEXIST; 973 return -EEXIST;
1001 *seq = cm->seq; 974 *seq = cm->seq;
@@ -1003,28 +976,6 @@ int dlm_comm_seq(int nodeid, uint32_t *seq)
1003 return 0; 976 return 0;
1004} 977}
1005 978
1006int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr)
1007{
1008 struct dlm_comm *cm = get_comm(nodeid, NULL);
1009 if (!cm)
1010 return -EEXIST;
1011 if (!cm->addr_count)
1012 return -ENOENT;
1013 memcpy(addr, cm->addr[0], sizeof(*addr));
1014 put_comm(cm);
1015 return 0;
1016}
1017
1018int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid)
1019{
1020 struct dlm_comm *cm = get_comm(0, addr);
1021 if (!cm)
1022 return -EEXIST;
1023 *nodeid = cm->nodeid;
1024 put_comm(cm);
1025 return 0;
1026}
1027
1028int dlm_our_nodeid(void) 979int dlm_our_nodeid(void)
1029{ 980{
1030 return local_comm ? local_comm->nodeid : 0; 981 return local_comm ? local_comm->nodeid : 0;
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index dbd35a08f3a5..f30697bc2780 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -46,8 +46,6 @@ void dlm_config_exit(void);
46int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, 46int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
47 int *count_out); 47 int *count_out);
48int dlm_comm_seq(int nodeid, uint32_t *seq); 48int dlm_comm_seq(int nodeid, uint32_t *seq);
49int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
50int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
51int dlm_our_nodeid(void); 49int dlm_our_nodeid(void);
52int dlm_our_addr(struct sockaddr_storage *addr, int num); 50int dlm_our_addr(struct sockaddr_storage *addr, int num);
53 51
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 5c1b0e38c7a4..522a69fccd84 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -140,6 +140,16 @@ struct writequeue_entry {
140 struct connection *con; 140 struct connection *con;
141}; 141};
142 142
143struct dlm_node_addr {
144 struct list_head list;
145 int nodeid;
146 int addr_count;
147 struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
148};
149
150static LIST_HEAD(dlm_node_addrs);
151static DEFINE_SPINLOCK(dlm_node_addrs_spin);
152
143static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; 153static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
144static int dlm_local_count; 154static int dlm_local_count;
145static int dlm_allow_conn; 155static int dlm_allow_conn;
@@ -264,31 +274,146 @@ static struct connection *assoc2con(int assoc_id)
264 return NULL; 274 return NULL;
265} 275}
266 276
267static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) 277static struct dlm_node_addr *find_node_addr(int nodeid)
278{
279 struct dlm_node_addr *na;
280
281 list_for_each_entry(na, &dlm_node_addrs, list) {
282 if (na->nodeid == nodeid)
283 return na;
284 }
285 return NULL;
286}
287
288static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y)
268{ 289{
269 struct sockaddr_storage addr; 290 switch (x->ss_family) {
270 int error; 291 case AF_INET: {
292 struct sockaddr_in *sinx = (struct sockaddr_in *)x;
293 struct sockaddr_in *siny = (struct sockaddr_in *)y;
294 if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
295 return 0;
296 if (sinx->sin_port != siny->sin_port)
297 return 0;
298 break;
299 }
300 case AF_INET6: {
301 struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
302 struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
303 if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
304 return 0;
305 if (sinx->sin6_port != siny->sin6_port)
306 return 0;
307 break;
308 }
309 default:
310 return 0;
311 }
312 return 1;
313}
314
315static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out,
316 struct sockaddr *sa_out)
317{
318 struct sockaddr_storage sas;
319 struct dlm_node_addr *na;
271 320
272 if (!dlm_local_count) 321 if (!dlm_local_count)
273 return -1; 322 return -1;
274 323
275 error = dlm_nodeid_to_addr(nodeid, &addr); 324 spin_lock(&dlm_node_addrs_spin);
276 if (error) 325 na = find_node_addr(nodeid);
277 return error; 326 if (na && na->addr_count)
327 memcpy(&sas, na->addr[0], sizeof(struct sockaddr_storage));
328 spin_unlock(&dlm_node_addrs_spin);
329
330 if (!na)
331 return -EEXIST;
332
333 if (!na->addr_count)
334 return -ENOENT;
335
336 if (sas_out)
337 memcpy(sas_out, &sas, sizeof(struct sockaddr_storage));
338
339 if (!sa_out)
340 return 0;
278 341
279 if (dlm_local_addr[0]->ss_family == AF_INET) { 342 if (dlm_local_addr[0]->ss_family == AF_INET) {
280 struct sockaddr_in *in4 = (struct sockaddr_in *) &addr; 343 struct sockaddr_in *in4 = (struct sockaddr_in *) &sas;
281 struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr; 344 struct sockaddr_in *ret4 = (struct sockaddr_in *) sa_out;
282 ret4->sin_addr.s_addr = in4->sin_addr.s_addr; 345 ret4->sin_addr.s_addr = in4->sin_addr.s_addr;
283 } else { 346 } else {
284 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &addr; 347 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &sas;
285 struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr; 348 struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) sa_out;
286 ret6->sin6_addr = in6->sin6_addr; 349 ret6->sin6_addr = in6->sin6_addr;
287 } 350 }
288 351
289 return 0; 352 return 0;
290} 353}
291 354
355static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid)
356{
357 struct dlm_node_addr *na;
358 int rv = -EEXIST;
359
360 spin_lock(&dlm_node_addrs_spin);
361 list_for_each_entry(na, &dlm_node_addrs, list) {
362 if (!na->addr_count)
363 continue;
364
365 if (!addr_compare(na->addr[0], addr))
366 continue;
367
368 *nodeid = na->nodeid;
369 rv = 0;
370 break;
371 }
372 spin_unlock(&dlm_node_addrs_spin);
373 return rv;
374}
375
376int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len)
377{
378 struct sockaddr_storage *new_addr;
379 struct dlm_node_addr *new_node, *na;
380
381 new_node = kzalloc(sizeof(struct dlm_node_addr), GFP_NOFS);
382 if (!new_node)
383 return -ENOMEM;
384
385 new_addr = kzalloc(sizeof(struct sockaddr_storage), GFP_NOFS);
386 if (!new_addr) {
387 kfree(new_node);
388 return -ENOMEM;
389 }
390
391 memcpy(new_addr, addr, len);
392
393 spin_lock(&dlm_node_addrs_spin);
394 na = find_node_addr(nodeid);
395 if (!na) {
396 new_node->nodeid = nodeid;
397 new_node->addr[0] = new_addr;
398 new_node->addr_count = 1;
399 list_add(&new_node->list, &dlm_node_addrs);
400 spin_unlock(&dlm_node_addrs_spin);
401 return 0;
402 }
403
404 if (na->addr_count >= DLM_MAX_ADDR_COUNT) {
405 spin_unlock(&dlm_node_addrs_spin);
406 kfree(new_addr);
407 kfree(new_node);
408 return -ENOSPC;
409 }
410
411 na->addr[na->addr_count++] = new_addr;
412 spin_unlock(&dlm_node_addrs_spin);
413 kfree(new_node);
414 return 0;
415}
416
292/* Data available on socket or listen socket received a connect */ 417/* Data available on socket or listen socket received a connect */
293static void lowcomms_data_ready(struct sock *sk, int count_unused) 418static void lowcomms_data_ready(struct sock *sk, int count_unused)
294{ 419{
@@ -510,7 +635,7 @@ static void process_sctp_notification(struct connection *con,
510 return; 635 return;
511 } 636 }
512 make_sockaddr(&prim.ssp_addr, 0, &addr_len); 637 make_sockaddr(&prim.ssp_addr, 0, &addr_len);
513 if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) { 638 if (addr_to_nodeid(&prim.ssp_addr, &nodeid)) {
514 unsigned char *b=(unsigned char *)&prim.ssp_addr; 639 unsigned char *b=(unsigned char *)&prim.ssp_addr;
515 log_print("reject connect from unknown addr"); 640 log_print("reject connect from unknown addr");
516 print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, 641 print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE,
@@ -747,7 +872,7 @@ static int tcp_accept_from_sock(struct connection *con)
747 872
748 /* Get the new node's NODEID */ 873 /* Get the new node's NODEID */
749 make_sockaddr(&peeraddr, 0, &len); 874 make_sockaddr(&peeraddr, 0, &len);
750 if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) { 875 if (addr_to_nodeid(&peeraddr, &nodeid)) {
751 unsigned char *b=(unsigned char *)&peeraddr; 876 unsigned char *b=(unsigned char *)&peeraddr;
752 log_print("connect from non cluster node"); 877 log_print("connect from non cluster node");
753 print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, 878 print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE,
@@ -862,7 +987,7 @@ static void sctp_init_assoc(struct connection *con)
862 if (con->retries++ > MAX_CONNECT_RETRIES) 987 if (con->retries++ > MAX_CONNECT_RETRIES)
863 return; 988 return;
864 989
865 if (nodeid_to_addr(con->nodeid, (struct sockaddr *)&rem_addr)) { 990 if (nodeid_to_addr(con->nodeid, NULL, (struct sockaddr *)&rem_addr)) {
866 log_print("no address for nodeid %d", con->nodeid); 991 log_print("no address for nodeid %d", con->nodeid);
867 return; 992 return;
868 } 993 }
@@ -928,11 +1053,11 @@ static void sctp_init_assoc(struct connection *con)
928/* Connect a new socket to its peer */ 1053/* Connect a new socket to its peer */
929static void tcp_connect_to_sock(struct connection *con) 1054static void tcp_connect_to_sock(struct connection *con)
930{ 1055{
931 int result = -EHOSTUNREACH;
932 struct sockaddr_storage saddr, src_addr; 1056 struct sockaddr_storage saddr, src_addr;
933 int addr_len; 1057 int addr_len;
934 struct socket *sock = NULL; 1058 struct socket *sock = NULL;
935 int one = 1; 1059 int one = 1;
1060 int result;
936 1061
937 if (con->nodeid == 0) { 1062 if (con->nodeid == 0) {
938 log_print("attempt to connect sock 0 foiled"); 1063 log_print("attempt to connect sock 0 foiled");
@@ -944,10 +1069,8 @@ static void tcp_connect_to_sock(struct connection *con)
944 goto out; 1069 goto out;
945 1070
946 /* Some odd races can cause double-connects, ignore them */ 1071 /* Some odd races can cause double-connects, ignore them */
947 if (con->sock) { 1072 if (con->sock)
948 result = 0;
949 goto out; 1073 goto out;
950 }
951 1074
952 /* Create a socket to communicate with */ 1075 /* Create a socket to communicate with */
953 result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM, 1076 result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
@@ -956,8 +1079,11 @@ static void tcp_connect_to_sock(struct connection *con)
956 goto out_err; 1079 goto out_err;
957 1080
958 memset(&saddr, 0, sizeof(saddr)); 1081 memset(&saddr, 0, sizeof(saddr));
959 if (dlm_nodeid_to_addr(con->nodeid, &saddr)) 1082 result = nodeid_to_addr(con->nodeid, &saddr, NULL);
1083 if (result < 0) {
1084 log_print("no address for nodeid %d", con->nodeid);
960 goto out_err; 1085 goto out_err;
1086 }
961 1087
962 sock->sk->sk_user_data = con; 1088 sock->sk->sk_user_data = con;
963 con->rx_action = receive_from_sock; 1089 con->rx_action = receive_from_sock;
@@ -983,8 +1109,7 @@ static void tcp_connect_to_sock(struct connection *con)
983 kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one, 1109 kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one,
984 sizeof(one)); 1110 sizeof(one));
985 1111
986 result = 1112 result = sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
987 sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
988 O_NONBLOCK); 1113 O_NONBLOCK);
989 if (result == -EINPROGRESS) 1114 if (result == -EINPROGRESS)
990 result = 0; 1115 result = 0;
@@ -1002,11 +1127,17 @@ out_err:
1002 * Some errors are fatal and this list might need adjusting. For other 1127 * Some errors are fatal and this list might need adjusting. For other
1003 * errors we try again until the max number of retries is reached. 1128 * errors we try again until the max number of retries is reached.
1004 */ 1129 */
1005 if (result != -EHOSTUNREACH && result != -ENETUNREACH && 1130 if (result != -EHOSTUNREACH &&
1006 result != -ENETDOWN && result != -EINVAL 1131 result != -ENETUNREACH &&
1007 && result != -EPROTONOSUPPORT) { 1132 result != -ENETDOWN &&
1133 result != -EINVAL &&
1134 result != -EPROTONOSUPPORT) {
1135 log_print("connect %d try %d error %d", con->nodeid,
1136 con->retries, result);
1137 mutex_unlock(&con->sock_mutex);
1138 msleep(1000);
1008 lowcomms_connect_sock(con); 1139 lowcomms_connect_sock(con);
1009 result = 0; 1140 return;
1010 } 1141 }
1011out: 1142out:
1012 mutex_unlock(&con->sock_mutex); 1143 mutex_unlock(&con->sock_mutex);
@@ -1414,6 +1545,7 @@ static void clean_one_writequeue(struct connection *con)
1414int dlm_lowcomms_close(int nodeid) 1545int dlm_lowcomms_close(int nodeid)
1415{ 1546{
1416 struct connection *con; 1547 struct connection *con;
1548 struct dlm_node_addr *na;
1417 1549
1418 log_print("closing connection to node %d", nodeid); 1550 log_print("closing connection to node %d", nodeid);
1419 con = nodeid2con(nodeid, 0); 1551 con = nodeid2con(nodeid, 0);
@@ -1428,6 +1560,17 @@ int dlm_lowcomms_close(int nodeid)
1428 clean_one_writequeue(con); 1560 clean_one_writequeue(con);
1429 close_connection(con, true); 1561 close_connection(con, true);
1430 } 1562 }
1563
1564 spin_lock(&dlm_node_addrs_spin);
1565 na = find_node_addr(nodeid);
1566 if (na) {
1567 list_del(&na->list);
1568 while (na->addr_count--)
1569 kfree(na->addr[na->addr_count]);
1570 kfree(na);
1571 }
1572 spin_unlock(&dlm_node_addrs_spin);
1573
1431 return 0; 1574 return 0;
1432} 1575}
1433 1576
@@ -1577,3 +1720,17 @@ fail_destroy:
1577fail: 1720fail:
1578 return error; 1721 return error;
1579} 1722}
1723
1724void dlm_lowcomms_exit(void)
1725{
1726 struct dlm_node_addr *na, *safe;
1727
1728 spin_lock(&dlm_node_addrs_spin);
1729 list_for_each_entry_safe(na, safe, &dlm_node_addrs, list) {
1730 list_del(&na->list);
1731 while (na->addr_count--)
1732 kfree(na->addr[na->addr_count]);
1733 kfree(na);
1734 }
1735 spin_unlock(&dlm_node_addrs_spin);
1736}
diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h
index 1311e6426287..67462e54fc2f 100644
--- a/fs/dlm/lowcomms.h
+++ b/fs/dlm/lowcomms.h
@@ -16,10 +16,12 @@
16 16
17int dlm_lowcomms_start(void); 17int dlm_lowcomms_start(void);
18void dlm_lowcomms_stop(void); 18void dlm_lowcomms_stop(void);
19void dlm_lowcomms_exit(void);
19int dlm_lowcomms_close(int nodeid); 20int dlm_lowcomms_close(int nodeid);
20void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc); 21void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc);
21void dlm_lowcomms_commit_buffer(void *mh); 22void dlm_lowcomms_commit_buffer(void *mh);
22int dlm_lowcomms_connect_node(int nodeid); 23int dlm_lowcomms_connect_node(int nodeid);
24int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len);
23 25
24#endif /* __LOWCOMMS_DOT_H__ */ 26#endif /* __LOWCOMMS_DOT_H__ */
25 27
diff --git a/fs/dlm/main.c b/fs/dlm/main.c
index 5a59efa0bb46..079c0bd71ab7 100644
--- a/fs/dlm/main.c
+++ b/fs/dlm/main.c
@@ -17,6 +17,7 @@
17#include "user.h" 17#include "user.h"
18#include "memory.h" 18#include "memory.h"
19#include "config.h" 19#include "config.h"
20#include "lowcomms.h"
20 21
21static int __init init_dlm(void) 22static int __init init_dlm(void)
22{ 23{
@@ -78,6 +79,7 @@ static void __exit exit_dlm(void)
78 dlm_config_exit(); 79 dlm_config_exit();
79 dlm_memory_exit(); 80 dlm_memory_exit();
80 dlm_lockspace_exit(); 81 dlm_lockspace_exit();
82 dlm_lowcomms_exit();
81 dlm_unregister_debugfs(); 83 dlm_unregister_debugfs();
82} 84}
83 85