diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-10-25 12:30:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-25 12:30:53 -0400 |
commit | 0b9e31e9264f1bad89856afb96da1688292f13b4 (patch) | |
tree | 7a9e9b6456dce993efeed8734de0a15a1f16ae94 /fs/dlm/lowcomms.c | |
parent | cf82ff7ea7695b0e82ba07bc5e9f1bd03a74e1aa (diff) | |
parent | 964fe080d94db82a3268443e9b9ece4c60246414 (diff) |
Merge branch 'linus' into sched/core
Conflicts:
fs/proc/array.c
Merge reason: resolve conflict and queue up dependent patch.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/dlm/lowcomms.c')
-rw-r--r-- | fs/dlm/lowcomms.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 618a60f03886..70736eb4b516 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 | } |
@@ -313,6 +316,10 @@ int dlm_lowcomms_connect_node(int nodeid) | |||
313 | { | 316 | { |
314 | struct connection *con; | 317 | struct connection *con; |
315 | 318 | ||
319 | /* with sctp there's no connecting without sending */ | ||
320 | if (dlm_config.ci_protocol != 0) | ||
321 | return 0; | ||
322 | |||
316 | if (nodeid == dlm_our_nodeid()) | 323 | if (nodeid == dlm_our_nodeid()) |
317 | return 0; | 324 | return 0; |
318 | 325 | ||
@@ -452,9 +459,9 @@ static void process_sctp_notification(struct connection *con, | |||
452 | int prim_len, ret; | 459 | int prim_len, ret; |
453 | int addr_len; | 460 | int addr_len; |
454 | struct connection *new_con; | 461 | struct connection *new_con; |
455 | struct file *file; | ||
456 | sctp_peeloff_arg_t parg; | 462 | sctp_peeloff_arg_t parg; |
457 | int parglen = sizeof(parg); | 463 | int parglen = sizeof(parg); |
464 | int err; | ||
458 | 465 | ||
459 | /* | 466 | /* |
460 | * We get this before any data for an association. | 467 | * We get this before any data for an association. |
@@ -509,19 +516,22 @@ static void process_sctp_notification(struct connection *con, | |||
509 | ret = kernel_getsockopt(con->sock, IPPROTO_SCTP, | 516 | ret = kernel_getsockopt(con->sock, IPPROTO_SCTP, |
510 | SCTP_SOCKOPT_PEELOFF, | 517 | SCTP_SOCKOPT_PEELOFF, |
511 | (void *)&parg, &parglen); | 518 | (void *)&parg, &parglen); |
512 | if (ret) { | 519 | if (ret < 0) { |
513 | log_print("Can't peel off a socket for " | 520 | log_print("Can't peel off a socket for " |
514 | "connection %d to node %d: err=%d\n", | 521 | "connection %d to node %d: err=%d", |
515 | parg.associd, nodeid, ret); | 522 | parg.associd, nodeid, ret); |
523 | return; | ||
524 | } | ||
525 | new_con->sock = sockfd_lookup(parg.sd, &err); | ||
526 | if (!new_con->sock) { | ||
527 | log_print("sockfd_lookup error %d", err); | ||
528 | return; | ||
516 | } | 529 | } |
517 | file = fget(parg.sd); | ||
518 | new_con->sock = SOCKET_I(file->f_dentry->d_inode); | ||
519 | add_sock(new_con->sock, new_con); | 530 | add_sock(new_con->sock, new_con); |
520 | fput(file); | 531 | sockfd_put(new_con->sock); |
521 | put_unused_fd(parg.sd); | ||
522 | 532 | ||
523 | log_print("got new/restarted association %d nodeid %d", | 533 | log_print("connecting to %d sctp association %d", |
524 | (int)sn->sn_assoc_change.sac_assoc_id, nodeid); | 534 | nodeid, (int)sn->sn_assoc_change.sac_assoc_id); |
525 | 535 | ||
526 | /* Send any pending writes */ | 536 | /* Send any pending writes */ |
527 | clear_bit(CF_CONNECT_PENDING, &new_con->flags); | 537 | clear_bit(CF_CONNECT_PENDING, &new_con->flags); |
@@ -834,8 +844,6 @@ static void sctp_init_assoc(struct connection *con) | |||
834 | if (con->retries++ > MAX_CONNECT_RETRIES) | 844 | if (con->retries++ > MAX_CONNECT_RETRIES) |
835 | return; | 845 | return; |
836 | 846 | ||
837 | log_print("Initiating association with node %d", con->nodeid); | ||
838 | |||
839 | if (nodeid_to_addr(con->nodeid, (struct sockaddr *)&rem_addr)) { | 847 | if (nodeid_to_addr(con->nodeid, (struct sockaddr *)&rem_addr)) { |
840 | log_print("no address for nodeid %d", con->nodeid); | 848 | log_print("no address for nodeid %d", con->nodeid); |
841 | return; | 849 | return; |
@@ -852,11 +860,14 @@ static void sctp_init_assoc(struct connection *con) | |||
852 | outmessage.msg_flags = MSG_EOR; | 860 | outmessage.msg_flags = MSG_EOR; |
853 | 861 | ||
854 | spin_lock(&con->writequeue_lock); | 862 | spin_lock(&con->writequeue_lock); |
855 | e = list_entry(con->writequeue.next, struct writequeue_entry, | ||
856 | list); | ||
857 | 863 | ||
858 | BUG_ON((struct list_head *) e == &con->writequeue); | 864 | if (list_empty(&con->writequeue)) { |
865 | spin_unlock(&con->writequeue_lock); | ||
866 | log_print("writequeue empty for nodeid %d", con->nodeid); | ||
867 | return; | ||
868 | } | ||
859 | 869 | ||
870 | e = list_first_entry(&con->writequeue, struct writequeue_entry, list); | ||
860 | len = e->len; | 871 | len = e->len; |
861 | offset = e->offset; | 872 | offset = e->offset; |
862 | spin_unlock(&con->writequeue_lock); | 873 | spin_unlock(&con->writequeue_lock); |
@@ -926,10 +937,8 @@ static void tcp_connect_to_sock(struct connection *con) | |||
926 | goto out_err; | 937 | goto out_err; |
927 | 938 | ||
928 | memset(&saddr, 0, sizeof(saddr)); | 939 | memset(&saddr, 0, sizeof(saddr)); |
929 | if (dlm_nodeid_to_addr(con->nodeid, &saddr)) { | 940 | if (dlm_nodeid_to_addr(con->nodeid, &saddr)) |
930 | sock_release(sock); | ||
931 | goto out_err; | 941 | goto out_err; |
932 | } | ||
933 | 942 | ||
934 | sock->sk->sk_user_data = con; | 943 | sock->sk->sk_user_data = con; |
935 | con->rx_action = receive_from_sock; | 944 | con->rx_action = receive_from_sock; |
@@ -1284,7 +1293,6 @@ out: | |||
1284 | static void send_to_sock(struct connection *con) | 1293 | static void send_to_sock(struct connection *con) |
1285 | { | 1294 | { |
1286 | int ret = 0; | 1295 | int ret = 0; |
1287 | ssize_t(*sendpage) (struct socket *, struct page *, int, size_t, int); | ||
1288 | const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL; | 1296 | const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL; |
1289 | struct writequeue_entry *e; | 1297 | struct writequeue_entry *e; |
1290 | int len, offset; | 1298 | int len, offset; |
@@ -1293,8 +1301,6 @@ static void send_to_sock(struct connection *con) | |||
1293 | if (con->sock == NULL) | 1301 | if (con->sock == NULL) |
1294 | goto out_connect; | 1302 | goto out_connect; |
1295 | 1303 | ||
1296 | sendpage = con->sock->ops->sendpage; | ||
1297 | |||
1298 | spin_lock(&con->writequeue_lock); | 1304 | spin_lock(&con->writequeue_lock); |
1299 | for (;;) { | 1305 | for (;;) { |
1300 | e = list_entry(con->writequeue.next, struct writequeue_entry, | 1306 | e = list_entry(con->writequeue.next, struct writequeue_entry, |
@@ -1309,8 +1315,8 @@ static void send_to_sock(struct connection *con) | |||
1309 | 1315 | ||
1310 | ret = 0; | 1316 | ret = 0; |
1311 | if (len) { | 1317 | if (len) { |
1312 | ret = sendpage(con->sock, e->page, offset, len, | 1318 | ret = kernel_sendpage(con->sock, e->page, offset, len, |
1313 | msg_flags); | 1319 | msg_flags); |
1314 | if (ret == -EAGAIN || ret == 0) { | 1320 | if (ret == -EAGAIN || ret == 0) { |
1315 | cond_resched(); | 1321 | cond_resched(); |
1316 | goto out; | 1322 | goto out; |
@@ -1370,6 +1376,13 @@ int dlm_lowcomms_close(int nodeid) | |||
1370 | log_print("closing connection to node %d", nodeid); | 1376 | log_print("closing connection to node %d", nodeid); |
1371 | con = nodeid2con(nodeid, 0); | 1377 | con = nodeid2con(nodeid, 0); |
1372 | if (con) { | 1378 | if (con) { |
1379 | clear_bit(CF_CONNECT_PENDING, &con->flags); | ||
1380 | clear_bit(CF_WRITE_PENDING, &con->flags); | ||
1381 | set_bit(CF_CLOSE, &con->flags); | ||
1382 | if (cancel_work_sync(&con->swork)) | ||
1383 | log_print("canceled swork for node %d", nodeid); | ||
1384 | if (cancel_work_sync(&con->rwork)) | ||
1385 | log_print("canceled rwork for node %d", nodeid); | ||
1373 | clean_one_writequeue(con); | 1386 | clean_one_writequeue(con); |
1374 | close_connection(con, true); | 1387 | close_connection(con, true); |
1375 | } | 1388 | } |
@@ -1395,9 +1408,10 @@ static void process_send_sockets(struct work_struct *work) | |||
1395 | 1408 | ||
1396 | if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) { | 1409 | if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) { |
1397 | con->connect_action(con); | 1410 | con->connect_action(con); |
1411 | set_bit(CF_WRITE_PENDING, &con->flags); | ||
1398 | } | 1412 | } |
1399 | clear_bit(CF_WRITE_PENDING, &con->flags); | 1413 | if (test_and_clear_bit(CF_WRITE_PENDING, &con->flags)) |
1400 | send_to_sock(con); | 1414 | send_to_sock(con); |
1401 | } | 1415 | } |
1402 | 1416 | ||
1403 | 1417 | ||