提交 0d737a8c 编写于 作者: M Marcelo Ricardo Leitner 提交者: David Teigland

dlm: fix race while closing connections

When a connection have issues DLM may need to close it.  Therefore we
should also cancel pending workqueues for such connection at that time,
and not just when dlm is not willing to use this connection anymore.

Also, if we don't clear CF_CONNECT_PENDING flag, the error handling
routines won't be able to re-connect as lowcomms_connect_sock() will
check for it.
Signed-off-by: NMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: NDavid Teigland <teigland@redhat.com>
上级 28926a09
...@@ -514,17 +514,24 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port, ...@@ -514,17 +514,24 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
} }
/* Close a remote connection and tidy up */ /* Close a remote connection and tidy up */
static void close_connection(struct connection *con, bool and_other) static void close_connection(struct connection *con, bool and_other,
bool tx, bool rx)
{ {
mutex_lock(&con->sock_mutex); clear_bit(CF_CONNECT_PENDING, &con->flags);
clear_bit(CF_WRITE_PENDING, &con->flags);
if (tx && cancel_work_sync(&con->swork))
log_print("canceled swork for node %d", con->nodeid);
if (rx && cancel_work_sync(&con->rwork))
log_print("canceled rwork for node %d", con->nodeid);
mutex_lock(&con->sock_mutex);
if (con->sock) { if (con->sock) {
sock_release(con->sock); sock_release(con->sock);
con->sock = NULL; con->sock = NULL;
} }
if (con->othercon && and_other) { if (con->othercon && and_other) {
/* Will only re-enter once. */ /* Will only re-enter once. */
close_connection(con->othercon, false); close_connection(con->othercon, false, true, true);
} }
if (con->rx_page) { if (con->rx_page) {
__free_page(con->rx_page); __free_page(con->rx_page);
...@@ -902,7 +909,7 @@ static int receive_from_sock(struct connection *con) ...@@ -902,7 +909,7 @@ static int receive_from_sock(struct connection *con)
out_close: out_close:
mutex_unlock(&con->sock_mutex); mutex_unlock(&con->sock_mutex);
if (ret != -EAGAIN) { if (ret != -EAGAIN) {
close_connection(con, false); close_connection(con, false, true, false);
/* Reconnect when there is something to send */ /* Reconnect when there is something to send */
} }
/* Don't return success if we really got EOF */ /* Don't return success if we really got EOF */
...@@ -1622,7 +1629,7 @@ static void send_to_sock(struct connection *con) ...@@ -1622,7 +1629,7 @@ static void send_to_sock(struct connection *con)
send_error: send_error:
mutex_unlock(&con->sock_mutex); mutex_unlock(&con->sock_mutex);
close_connection(con, false); close_connection(con, false, false, true);
lowcomms_connect_sock(con); lowcomms_connect_sock(con);
return; return;
...@@ -1654,15 +1661,9 @@ int dlm_lowcomms_close(int nodeid) ...@@ -1654,15 +1661,9 @@ int dlm_lowcomms_close(int nodeid)
log_print("closing connection to node %d", nodeid); log_print("closing connection to node %d", nodeid);
con = nodeid2con(nodeid, 0); con = nodeid2con(nodeid, 0);
if (con) { if (con) {
clear_bit(CF_CONNECT_PENDING, &con->flags);
clear_bit(CF_WRITE_PENDING, &con->flags);
set_bit(CF_CLOSE, &con->flags); set_bit(CF_CLOSE, &con->flags);
if (cancel_work_sync(&con->swork)) close_connection(con, true, true, true);
log_print("canceled swork for node %d", nodeid);
if (cancel_work_sync(&con->rwork))
log_print("canceled rwork for node %d", nodeid);
clean_one_writequeue(con); clean_one_writequeue(con);
close_connection(con, true);
} }
spin_lock(&dlm_node_addrs_spin); spin_lock(&dlm_node_addrs_spin);
...@@ -1745,7 +1746,7 @@ static void stop_conn(struct connection *con) ...@@ -1745,7 +1746,7 @@ static void stop_conn(struct connection *con)
static void free_conn(struct connection *con) static void free_conn(struct connection *con)
{ {
close_connection(con, true); close_connection(con, true, true, true);
if (con->othercon) if (con->othercon)
kmem_cache_free(con_cache, con->othercon); kmem_cache_free(con_cache, con->othercon);
hlist_del(&con->list); hlist_del(&con->list);
...@@ -1816,7 +1817,7 @@ int dlm_lowcomms_start(void) ...@@ -1816,7 +1817,7 @@ int dlm_lowcomms_start(void)
dlm_allow_conn = 0; dlm_allow_conn = 0;
con = nodeid2con(0,0); con = nodeid2con(0,0);
if (con) { if (con) {
close_connection(con, false); close_connection(con, false, true, true);
kmem_cache_free(con_cache, con); kmem_cache_free(con_cache, con);
} }
fail_destroy: fail_destroy:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册