diff options
Diffstat (limited to 'fs/dlm/lowcomms.c')
-rw-r--r-- | fs/dlm/lowcomms.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 27970a58d29b..9e9d2e82f40f 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -260,7 +260,7 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) static void lowcomms_data_ready(struct sock *sk, int count_unused) { struct connection *con = sock2con(sk); - if (!test_and_set_bit(CF_READ_PENDING, &con->flags)) + if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags)) queue_work(recv_workqueue, &con->rwork); } @@ -268,7 +268,7 @@ static void lowcomms_write_space(struct sock *sk) { struct connection *con = sock2con(sk); - if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) + if (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags)) queue_work(send_workqueue, &con->swork); } @@ -313,6 +313,7 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port, in6_addr->sin6_port = cpu_to_be16(port); *addr_len = sizeof(struct sockaddr_in6); } + memset((char *)saddr + *addr_len, 0, sizeof(struct sockaddr_storage) - *addr_len); } /* Close a remote connection and tidy up */ @@ -332,8 +333,19 @@ static void close_connection(struct connection *con, bool and_other) __free_page(con->rx_page); con->rx_page = NULL; } - con->retries = 0; - mutex_unlock(&con->sock_mutex); + + /* If we are an 'othercon' then NULL the pointer to us + from the parent and tidy ourself up */ + if (test_bit(CF_IS_OTHERCON, &con->flags)) { + struct connection *parent = __nodeid2con(con->nodeid, 0); + parent->othercon = NULL; + kmem_cache_free(con_cache, con); + } + else { + /* Parent connections get reused */ + con->retries = 0; + mutex_unlock(&con->sock_mutex); + } } /* We only send shutdown messages to nodes that are not part of the cluster */ @@ -631,7 +643,7 @@ out_resched: out_close: mutex_unlock(&con->sock_mutex); - if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) { + if (ret != -EAGAIN) { close_connection(con, false); /* Reconnect when there is something to send */ } @@ -720,11 +732,17 @@ static int tcp_accept_from_sock(struct connection *con) INIT_WORK(&othercon->rwork, process_recv_sockets); set_bit(CF_IS_OTHERCON, &othercon->flags); newcon->othercon = othercon; + othercon->sock = newsock; + newsock->sk->sk_user_data = othercon; + add_sock(newsock, othercon); + addcon = othercon; + } + else { + printk("Extra connection from node %d attempted\n", nodeid); + result = -EAGAIN; + mutex_unlock(&newcon->sock_mutex); + goto accept_err; } - othercon->sock = newsock; - newsock->sk->sk_user_data = othercon; - add_sock(newsock, othercon); - addcon = othercon; } else { newsock->sk->sk_user_data = newcon; @@ -1116,8 +1134,6 @@ static int tcp_listen_for_all(void) log_print("Using TCP for communications"); - set_bit(CF_IS_OTHERCON, &con->flags); - sock = tcp_create_listen_sock(con, dlm_local_addr[0]); if (sock) { add_sock(sock, con); @@ -1400,8 +1416,11 @@ void dlm_lowcomms_stop(void) down(&connections_lock); for (i = 0; i <= max_nodeid; i++) { con = __nodeid2con(i, 0); - if (con) - con->flags |= 0xFF; + if (con) { + con->flags |= 0x0F; + if (con->sock) + con->sock->sk->sk_user_data = NULL; + } } up(&connections_lock); @@ -1414,8 +1433,6 @@ void dlm_lowcomms_stop(void) con = __nodeid2con(i, 0); if (con) { close_connection(con, true); - if (con->othercon) - kmem_cache_free(con_cache, con->othercon); kmem_cache_free(con_cache, con); } } @@ -1440,7 +1457,7 @@ int dlm_lowcomms_start(void) error = -ENOMEM; con_cache = kmem_cache_create("dlm_conn", sizeof(struct connection), __alignof__(struct connection), 0, - NULL, NULL); + NULL); if (!con_cache) goto out; |