aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2012-07-26 13:44:30 -0400
committerDavid Teigland <teigland@redhat.com>2012-08-08 12:33:35 -0400
commit36b71a8bfbc92e1ba164e9aec840c0180ee933b5 (patch)
tree6cda578ba4e7e4c9de16e333ffdc032717348b81
parent42a579a0f960081cd16fc945036e4780c3ad3202 (diff)
dlm: fix deadlock between dlm_send and dlm_controld
A deadlock sometimes occurs between dlm_controld closing a lowcomms connection through configfs and dlm_send looking up the address for a new connection in configfs. dlm_controld does a configfs rmdir which calls dlm_lowcomms_close which waits for dlm_send to cancel work on the workqueues. The dlm_send workqueue thread has called tcp_connect_to_sock which calls dlm_nodeid_to_addr which does a configfs lookup and blocks on a lock held by dlm_controld in the rmdir path. The solution here is to save the node addresses within the lowcomms code so that the lowcomms workqueue does not need to step through configfs to get a node address. dlm_controld: wait_for_completion+0x1d/0x20 __cancel_work_timer+0x1b3/0x1e0 cancel_work_sync+0x10/0x20 dlm_lowcomms_close+0x4c/0xb0 [dlm] drop_comm+0x22/0x60 [dlm] client_drop_item+0x26/0x50 [configfs] configfs_rmdir+0x180/0x230 [configfs] vfs_rmdir+0xbd/0xf0 do_rmdir+0x103/0x120 sys_rmdir+0x16/0x20 dlm_send: mutex_lock+0x2b/0x50 get_comm+0x34/0x140 [dlm] dlm_nodeid_to_addr+0x18/0xd0 [dlm] tcp_connect_to_sock+0xf4/0x2d0 [dlm] process_send_sockets+0x1d2/0x260 [dlm] worker_thread+0x170/0x2a0 Signed-off-by: David Teigland <teigland@redhat.com>
-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