diff options
-rw-r--r-- | fs/dlm/lowcomms.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 618a60f03886..240cef14fe58 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -106,6 +106,7 @@ struct connection { | |||
106 | #define CF_CONNECT_PENDING 3 | 106 | #define CF_CONNECT_PENDING 3 |
107 | #define CF_INIT_PENDING 4 | 107 | #define CF_INIT_PENDING 4 |
108 | #define CF_IS_OTHERCON 5 | 108 | #define CF_IS_OTHERCON 5 |
109 | #define CF_CLOSE 6 | ||
109 | struct list_head writequeue; /* List of outgoing writequeue_entries */ | 110 | struct list_head writequeue; /* List of outgoing writequeue_entries */ |
110 | spinlock_t writequeue_lock; | 111 | spinlock_t writequeue_lock; |
111 | int (*rx_action) (struct connection *); /* What to do when active */ | 112 | int (*rx_action) (struct connection *); /* What to do when active */ |
@@ -299,6 +300,8 @@ static void lowcomms_write_space(struct sock *sk) | |||
299 | 300 | ||
300 | static inline void lowcomms_connect_sock(struct connection *con) | 301 | static inline void lowcomms_connect_sock(struct connection *con) |
301 | { | 302 | { |
303 | if (test_bit(CF_CLOSE, &con->flags)) | ||
304 | return; | ||
302 | if (!test_and_set_bit(CF_CONNECT_PENDING, &con->flags)) | 305 | if (!test_and_set_bit(CF_CONNECT_PENDING, &con->flags)) |
303 | queue_work(send_workqueue, &con->swork); | 306 | queue_work(send_workqueue, &con->swork); |
304 | } | 307 | } |
@@ -926,10 +929,8 @@ static void tcp_connect_to_sock(struct connection *con) | |||
926 | goto out_err; | 929 | goto out_err; |
927 | 930 | ||
928 | memset(&saddr, 0, sizeof(saddr)); | 931 | memset(&saddr, 0, sizeof(saddr)); |
929 | if (dlm_nodeid_to_addr(con->nodeid, &saddr)) { | 932 | if (dlm_nodeid_to_addr(con->nodeid, &saddr)) |
930 | sock_release(sock); | ||
931 | goto out_err; | 933 | goto out_err; |
932 | } | ||
933 | 934 | ||
934 | sock->sk->sk_user_data = con; | 935 | sock->sk->sk_user_data = con; |
935 | con->rx_action = receive_from_sock; | 936 | con->rx_action = receive_from_sock; |
@@ -1284,7 +1285,6 @@ out: | |||
1284 | static void send_to_sock(struct connection *con) | 1285 | static void send_to_sock(struct connection *con) |
1285 | { | 1286 | { |
1286 | int ret = 0; | 1287 | int ret = 0; |
1287 | ssize_t(*sendpage) (struct socket *, struct page *, int, size_t, int); | ||
1288 | const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL; | 1288 | const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL; |
1289 | struct writequeue_entry *e; | 1289 | struct writequeue_entry *e; |
1290 | int len, offset; | 1290 | int len, offset; |
@@ -1293,8 +1293,6 @@ static void send_to_sock(struct connection *con) | |||
1293 | if (con->sock == NULL) | 1293 | if (con->sock == NULL) |
1294 | goto out_connect; | 1294 | goto out_connect; |
1295 | 1295 | ||
1296 | sendpage = con->sock->ops->sendpage; | ||
1297 | |||
1298 | spin_lock(&con->writequeue_lock); | 1296 | spin_lock(&con->writequeue_lock); |
1299 | for (;;) { | 1297 | for (;;) { |
1300 | e = list_entry(con->writequeue.next, struct writequeue_entry, | 1298 | e = list_entry(con->writequeue.next, struct writequeue_entry, |
@@ -1309,8 +1307,8 @@ static void send_to_sock(struct connection *con) | |||
1309 | 1307 | ||
1310 | ret = 0; | 1308 | ret = 0; |
1311 | if (len) { | 1309 | if (len) { |
1312 | ret = sendpage(con->sock, e->page, offset, len, | 1310 | ret = kernel_sendpage(con->sock, e->page, offset, len, |
1313 | msg_flags); | 1311 | msg_flags); |
1314 | if (ret == -EAGAIN || ret == 0) { | 1312 | if (ret == -EAGAIN || ret == 0) { |
1315 | cond_resched(); | 1313 | cond_resched(); |
1316 | goto out; | 1314 | goto out; |
@@ -1370,6 +1368,13 @@ int dlm_lowcomms_close(int nodeid) | |||
1370 | log_print("closing connection to node %d", nodeid); | 1368 | log_print("closing connection to node %d", nodeid); |
1371 | con = nodeid2con(nodeid, 0); | 1369 | con = nodeid2con(nodeid, 0); |
1372 | if (con) { | 1370 | if (con) { |
1371 | clear_bit(CF_CONNECT_PENDING, &con->flags); | ||
1372 | clear_bit(CF_WRITE_PENDING, &con->flags); | ||
1373 | set_bit(CF_CLOSE, &con->flags); | ||
1374 | if (cancel_work_sync(&con->swork)) | ||
1375 | log_print("canceled swork for node %d", nodeid); | ||
1376 | if (cancel_work_sync(&con->rwork)) | ||
1377 | log_print("canceled rwork for node %d", nodeid); | ||
1373 | clean_one_writequeue(con); | 1378 | clean_one_writequeue(con); |
1374 | close_connection(con, true); | 1379 | close_connection(con, true); |
1375 | } | 1380 | } |
@@ -1395,9 +1400,10 @@ static void process_send_sockets(struct work_struct *work) | |||
1395 | 1400 | ||
1396 | if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) { | 1401 | if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) { |
1397 | con->connect_action(con); | 1402 | con->connect_action(con); |
1403 | set_bit(CF_WRITE_PENDING, &con->flags); | ||
1398 | } | 1404 | } |
1399 | clear_bit(CF_WRITE_PENDING, &con->flags); | 1405 | if (test_and_clear_bit(CF_WRITE_PENDING, &con->flags)) |
1400 | send_to_sock(con); | 1406 | send_to_sock(con); |
1401 | } | 1407 | } |
1402 | 1408 | ||
1403 | 1409 | ||