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 | ||
