diff options
author | David Teigland <teigland@redhat.com> | 2012-03-30 12:46:08 -0400 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2012-04-26 16:35:38 -0400 |
commit | 513ef596d43cc35a72ae21170075136855641493 (patch) | |
tree | 89a73567803e4cdc910849af388a934923625345 /fs/dlm | |
parent | af3a3ab2966112c0d0a44df7eeb1e95fe32d4495 (diff) |
dlm: prevent connections during shutdown
During lowcomms shutdown, a new connection could possibly
be created, and attempt to use a workqueue that's been
destroyed. Similarly, during startup, a new connection
could attempt to use a workqueue that's not been set up
yet. Add a global variable to indicate when new connections
are allowed.
Based on patch by: Christine Caulfield <ccaulfie@redhat.com>
Reported-by: dann frazier <dann.frazier@canonical.com>
Reviewed-by: dann frazier <dann.frazier@canonical.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm')
-rw-r--r-- | fs/dlm/lowcomms.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 133ef6dc7cb7..5c1b0e38c7a4 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -142,6 +142,7 @@ struct writequeue_entry { | |||
142 | 142 | ||
143 | static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; | 143 | static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; |
144 | static int dlm_local_count; | 144 | static int dlm_local_count; |
145 | static int dlm_allow_conn; | ||
145 | 146 | ||
146 | /* Work queues */ | 147 | /* Work queues */ |
147 | static struct workqueue_struct *recv_workqueue; | 148 | static struct workqueue_struct *recv_workqueue; |
@@ -710,6 +711,13 @@ static int tcp_accept_from_sock(struct connection *con) | |||
710 | struct connection *newcon; | 711 | struct connection *newcon; |
711 | struct connection *addcon; | 712 | struct connection *addcon; |
712 | 713 | ||
714 | mutex_lock(&connections_lock); | ||
715 | if (!dlm_allow_conn) { | ||
716 | mutex_unlock(&connections_lock); | ||
717 | return -1; | ||
718 | } | ||
719 | mutex_unlock(&connections_lock); | ||
720 | |||
713 | memset(&peeraddr, 0, sizeof(peeraddr)); | 721 | memset(&peeraddr, 0, sizeof(peeraddr)); |
714 | result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM, | 722 | result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM, |
715 | IPPROTO_TCP, &newsock); | 723 | IPPROTO_TCP, &newsock); |
@@ -1503,6 +1511,7 @@ void dlm_lowcomms_stop(void) | |||
1503 | socket activity. | 1511 | socket activity. |
1504 | */ | 1512 | */ |
1505 | mutex_lock(&connections_lock); | 1513 | mutex_lock(&connections_lock); |
1514 | dlm_allow_conn = 0; | ||
1506 | foreach_conn(stop_conn); | 1515 | foreach_conn(stop_conn); |
1507 | mutex_unlock(&connections_lock); | 1516 | mutex_unlock(&connections_lock); |
1508 | 1517 | ||
@@ -1530,7 +1539,7 @@ int dlm_lowcomms_start(void) | |||
1530 | if (!dlm_local_count) { | 1539 | if (!dlm_local_count) { |
1531 | error = -ENOTCONN; | 1540 | error = -ENOTCONN; |
1532 | log_print("no local IP address has been set"); | 1541 | log_print("no local IP address has been set"); |
1533 | goto out; | 1542 | goto fail; |
1534 | } | 1543 | } |
1535 | 1544 | ||
1536 | error = -ENOMEM; | 1545 | error = -ENOMEM; |
@@ -1538,7 +1547,13 @@ int dlm_lowcomms_start(void) | |||
1538 | __alignof__(struct connection), 0, | 1547 | __alignof__(struct connection), 0, |
1539 | NULL); | 1548 | NULL); |
1540 | if (!con_cache) | 1549 | if (!con_cache) |
1541 | goto out; | 1550 | goto fail; |
1551 | |||
1552 | error = work_start(); | ||
1553 | if (error) | ||
1554 | goto fail_destroy; | ||
1555 | |||
1556 | dlm_allow_conn = 1; | ||
1542 | 1557 | ||
1543 | /* Start listening */ | 1558 | /* Start listening */ |
1544 | if (dlm_config.ci_protocol == 0) | 1559 | if (dlm_config.ci_protocol == 0) |
@@ -1548,20 +1563,17 @@ int dlm_lowcomms_start(void) | |||
1548 | if (error) | 1563 | if (error) |
1549 | goto fail_unlisten; | 1564 | goto fail_unlisten; |
1550 | 1565 | ||
1551 | error = work_start(); | ||
1552 | if (error) | ||
1553 | goto fail_unlisten; | ||
1554 | |||
1555 | return 0; | 1566 | return 0; |
1556 | 1567 | ||
1557 | fail_unlisten: | 1568 | fail_unlisten: |
1569 | dlm_allow_conn = 0; | ||
1558 | con = nodeid2con(0,0); | 1570 | con = nodeid2con(0,0); |
1559 | if (con) { | 1571 | if (con) { |
1560 | close_connection(con, false); | 1572 | close_connection(con, false); |
1561 | kmem_cache_free(con_cache, con); | 1573 | kmem_cache_free(con_cache, con); |
1562 | } | 1574 | } |
1575 | fail_destroy: | ||
1563 | kmem_cache_destroy(con_cache); | 1576 | kmem_cache_destroy(con_cache); |
1564 | 1577 | fail: | |
1565 | out: | ||
1566 | return error; | 1578 | return error; |
1567 | } | 1579 | } |