aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortsutomu.owa@toshiba.co.jp <tsutomu.owa@toshiba.co.jp>2017-09-12 04:55:50 -0400
committerDavid Teigland <teigland@redhat.com>2017-09-25 13:45:21 -0400
commitb2a6662932c52304eee11323701f8a01aa110e37 (patch)
tree094b58c402c38d5fea012fefd4d029c7c0d4af90
parentf0fb83cb9201a9f272f8ac771eed6b1e5745375c (diff)
DLM: fix race condition between dlm_send and dlm_recv
When kernel_sendpage(in send_to_sock) and kernel_recvmsg (in receive_from_sock) return error, close_connection may works at the same time. At that time, they may wait for each other by cancel_work_sync. Signed-off-by: Tadashi Miyauchi <miayuchi@toshiba-tops.co.jp> Signed-off-by: Tsutomu Owa <tsutomu.owa@toshiba.co.jp> Signed-off-by: David Teigland <teigland@redhat.com>
-rw-r--r--fs/dlm/lowcomms.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 980c58befd53..420946dcb7ca 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -110,6 +110,7 @@ struct connection {
110#define CF_IS_OTHERCON 5 110#define CF_IS_OTHERCON 5
111#define CF_CLOSE 6 111#define CF_CLOSE 6
112#define CF_APP_LIMITED 7 112#define CF_APP_LIMITED 7
113#define CF_CLOSING 8
113 struct list_head writequeue; /* List of outgoing writequeue_entries */ 114 struct list_head writequeue; /* List of outgoing writequeue_entries */
114 spinlock_t writequeue_lock; 115 spinlock_t writequeue_lock;
115 int (*rx_action) (struct connection *); /* What to do when active */ 116 int (*rx_action) (struct connection *); /* What to do when active */
@@ -581,9 +582,11 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
581static void close_connection(struct connection *con, bool and_other, 582static void close_connection(struct connection *con, bool and_other,
582 bool tx, bool rx) 583 bool tx, bool rx)
583{ 584{
584 if (tx && cancel_work_sync(&con->swork)) 585 bool closing = test_and_set_bit(CF_CLOSING, &con->flags);
586
587 if (tx && !closing && cancel_work_sync(&con->swork))
585 log_print("canceled swork for node %d", con->nodeid); 588 log_print("canceled swork for node %d", con->nodeid);
586 if (rx && cancel_work_sync(&con->rwork)) 589 if (rx && !closing && cancel_work_sync(&con->rwork))
587 log_print("canceled rwork for node %d", con->nodeid); 590 log_print("canceled rwork for node %d", con->nodeid);
588 591
589 mutex_lock(&con->sock_mutex); 592 mutex_lock(&con->sock_mutex);
@@ -603,6 +606,7 @@ static void close_connection(struct connection *con, bool and_other,
603 606
604 con->retries = 0; 607 con->retries = 0;
605 mutex_unlock(&con->sock_mutex); 608 mutex_unlock(&con->sock_mutex);
609 clear_bit(CF_CLOSING, &con->flags);
606} 610}
607 611
608/* Data received from remote end */ 612/* Data received from remote end */