diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-04-01 13:28:15 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-04-01 13:28:15 -0400 |
commit | cc85906110e26fe8537c3bdbc08a74ae8110030b (patch) | |
tree | 891813098ede3dba4d5ff3b83b1f7b491367ad2f /net/sunrpc/xprtsock.c | |
parent | c09bca786ff941ed17c5f381c4eca5b106808c51 (diff) | |
parent | c69da774b28e01e062e0a3aba7509f2dcfd2a11a (diff) |
Merge branch 'devel' into for-linus
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 363 |
1 files changed, 228 insertions, 135 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 568330eebbfe..d40ff50887aa 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -49,6 +49,9 @@ unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE; | |||
49 | unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; | 49 | unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; |
50 | unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; | 50 | unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; |
51 | 51 | ||
52 | #define XS_TCP_LINGER_TO (15U * HZ) | ||
53 | static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO; | ||
54 | |||
52 | /* | 55 | /* |
53 | * We can register our own files under /proc/sys/sunrpc by | 56 | * We can register our own files under /proc/sys/sunrpc by |
54 | * calling register_sysctl_table() again. The files in that | 57 | * calling register_sysctl_table() again. The files in that |
@@ -117,6 +120,14 @@ static ctl_table xs_tunables_table[] = { | |||
117 | .extra2 = &xprt_max_resvport_limit | 120 | .extra2 = &xprt_max_resvport_limit |
118 | }, | 121 | }, |
119 | { | 122 | { |
123 | .procname = "tcp_fin_timeout", | ||
124 | .data = &xs_tcp_fin_timeout, | ||
125 | .maxlen = sizeof(xs_tcp_fin_timeout), | ||
126 | .mode = 0644, | ||
127 | .proc_handler = &proc_dointvec_jiffies, | ||
128 | .strategy = sysctl_jiffies | ||
129 | }, | ||
130 | { | ||
120 | .ctl_name = 0, | 131 | .ctl_name = 0, |
121 | }, | 132 | }, |
122 | }; | 133 | }; |
@@ -521,11 +532,12 @@ static void xs_nospace_callback(struct rpc_task *task) | |||
521 | * @task: task to put to sleep | 532 | * @task: task to put to sleep |
522 | * | 533 | * |
523 | */ | 534 | */ |
524 | static void xs_nospace(struct rpc_task *task) | 535 | static int xs_nospace(struct rpc_task *task) |
525 | { | 536 | { |
526 | struct rpc_rqst *req = task->tk_rqstp; | 537 | struct rpc_rqst *req = task->tk_rqstp; |
527 | struct rpc_xprt *xprt = req->rq_xprt; | 538 | struct rpc_xprt *xprt = req->rq_xprt; |
528 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 539 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
540 | int ret = 0; | ||
529 | 541 | ||
530 | dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", | 542 | dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", |
531 | task->tk_pid, req->rq_slen - req->rq_bytes_sent, | 543 | task->tk_pid, req->rq_slen - req->rq_bytes_sent, |
@@ -537,6 +549,7 @@ static void xs_nospace(struct rpc_task *task) | |||
537 | /* Don't race with disconnect */ | 549 | /* Don't race with disconnect */ |
538 | if (xprt_connected(xprt)) { | 550 | if (xprt_connected(xprt)) { |
539 | if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) { | 551 | if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) { |
552 | ret = -EAGAIN; | ||
540 | /* | 553 | /* |
541 | * Notify TCP that we're limited by the application | 554 | * Notify TCP that we're limited by the application |
542 | * window size | 555 | * window size |
@@ -548,10 +561,11 @@ static void xs_nospace(struct rpc_task *task) | |||
548 | } | 561 | } |
549 | } else { | 562 | } else { |
550 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 563 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
551 | task->tk_status = -ENOTCONN; | 564 | ret = -ENOTCONN; |
552 | } | 565 | } |
553 | 566 | ||
554 | spin_unlock_bh(&xprt->transport_lock); | 567 | spin_unlock_bh(&xprt->transport_lock); |
568 | return ret; | ||
555 | } | 569 | } |
556 | 570 | ||
557 | /** | 571 | /** |
@@ -594,6 +608,8 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
594 | /* Still some bytes left; set up for a retry later. */ | 608 | /* Still some bytes left; set up for a retry later. */ |
595 | status = -EAGAIN; | 609 | status = -EAGAIN; |
596 | } | 610 | } |
611 | if (!transport->sock) | ||
612 | goto out; | ||
597 | 613 | ||
598 | switch (status) { | 614 | switch (status) { |
599 | case -ENOTSOCK: | 615 | case -ENOTSOCK: |
@@ -601,21 +617,19 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
601 | /* Should we call xs_close() here? */ | 617 | /* Should we call xs_close() here? */ |
602 | break; | 618 | break; |
603 | case -EAGAIN: | 619 | case -EAGAIN: |
604 | xs_nospace(task); | 620 | status = xs_nospace(task); |
605 | break; | 621 | break; |
622 | default: | ||
623 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | ||
624 | -status); | ||
606 | case -ENETUNREACH: | 625 | case -ENETUNREACH: |
607 | case -EPIPE: | 626 | case -EPIPE: |
608 | case -ECONNREFUSED: | 627 | case -ECONNREFUSED: |
609 | /* When the server has died, an ICMP port unreachable message | 628 | /* When the server has died, an ICMP port unreachable message |
610 | * prompts ECONNREFUSED. */ | 629 | * prompts ECONNREFUSED. */ |
611 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 630 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
612 | break; | ||
613 | default: | ||
614 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | ||
615 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | ||
616 | -status); | ||
617 | } | 631 | } |
618 | 632 | out: | |
619 | return status; | 633 | return status; |
620 | } | 634 | } |
621 | 635 | ||
@@ -697,6 +711,8 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
697 | status = -EAGAIN; | 711 | status = -EAGAIN; |
698 | break; | 712 | break; |
699 | } | 713 | } |
714 | if (!transport->sock) | ||
715 | goto out; | ||
700 | 716 | ||
701 | switch (status) { | 717 | switch (status) { |
702 | case -ENOTSOCK: | 718 | case -ENOTSOCK: |
@@ -704,23 +720,19 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
704 | /* Should we call xs_close() here? */ | 720 | /* Should we call xs_close() here? */ |
705 | break; | 721 | break; |
706 | case -EAGAIN: | 722 | case -EAGAIN: |
707 | xs_nospace(task); | 723 | status = xs_nospace(task); |
708 | break; | 724 | break; |
725 | default: | ||
726 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | ||
727 | -status); | ||
709 | case -ECONNRESET: | 728 | case -ECONNRESET: |
729 | case -EPIPE: | ||
710 | xs_tcp_shutdown(xprt); | 730 | xs_tcp_shutdown(xprt); |
711 | case -ECONNREFUSED: | 731 | case -ECONNREFUSED: |
712 | case -ENOTCONN: | 732 | case -ENOTCONN: |
713 | case -EPIPE: | ||
714 | status = -ENOTCONN; | ||
715 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | ||
716 | break; | ||
717 | default: | ||
718 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | ||
719 | -status); | ||
720 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 733 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
721 | xs_tcp_shutdown(xprt); | ||
722 | } | 734 | } |
723 | 735 | out: | |
724 | return status; | 736 | return status; |
725 | } | 737 | } |
726 | 738 | ||
@@ -767,23 +779,13 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s | |||
767 | sk->sk_error_report = transport->old_error_report; | 779 | sk->sk_error_report = transport->old_error_report; |
768 | } | 780 | } |
769 | 781 | ||
770 | /** | 782 | static void xs_reset_transport(struct sock_xprt *transport) |
771 | * xs_close - close a socket | ||
772 | * @xprt: transport | ||
773 | * | ||
774 | * This is used when all requests are complete; ie, no DRC state remains | ||
775 | * on the server we want to save. | ||
776 | */ | ||
777 | static void xs_close(struct rpc_xprt *xprt) | ||
778 | { | 783 | { |
779 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
780 | struct socket *sock = transport->sock; | 784 | struct socket *sock = transport->sock; |
781 | struct sock *sk = transport->inet; | 785 | struct sock *sk = transport->inet; |
782 | 786 | ||
783 | if (!sk) | 787 | if (sk == NULL) |
784 | goto clear_close_wait; | 788 | return; |
785 | |||
786 | dprintk("RPC: xs_close xprt %p\n", xprt); | ||
787 | 789 | ||
788 | write_lock_bh(&sk->sk_callback_lock); | 790 | write_lock_bh(&sk->sk_callback_lock); |
789 | transport->inet = NULL; | 791 | transport->inet = NULL; |
@@ -797,8 +799,25 @@ static void xs_close(struct rpc_xprt *xprt) | |||
797 | sk->sk_no_check = 0; | 799 | sk->sk_no_check = 0; |
798 | 800 | ||
799 | sock_release(sock); | 801 | sock_release(sock); |
800 | clear_close_wait: | 802 | } |
803 | |||
804 | /** | ||
805 | * xs_close - close a socket | ||
806 | * @xprt: transport | ||
807 | * | ||
808 | * This is used when all requests are complete; ie, no DRC state remains | ||
809 | * on the server we want to save. | ||
810 | */ | ||
811 | static void xs_close(struct rpc_xprt *xprt) | ||
812 | { | ||
813 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
814 | |||
815 | dprintk("RPC: xs_close xprt %p\n", xprt); | ||
816 | |||
817 | xs_reset_transport(transport); | ||
818 | |||
801 | smp_mb__before_clear_bit(); | 819 | smp_mb__before_clear_bit(); |
820 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
802 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | 821 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); |
803 | clear_bit(XPRT_CLOSING, &xprt->state); | 822 | clear_bit(XPRT_CLOSING, &xprt->state); |
804 | smp_mb__after_clear_bit(); | 823 | smp_mb__after_clear_bit(); |
@@ -1126,6 +1145,47 @@ out: | |||
1126 | read_unlock(&sk->sk_callback_lock); | 1145 | read_unlock(&sk->sk_callback_lock); |
1127 | } | 1146 | } |
1128 | 1147 | ||
1148 | /* | ||
1149 | * Do the equivalent of linger/linger2 handling for dealing with | ||
1150 | * broken servers that don't close the socket in a timely | ||
1151 | * fashion | ||
1152 | */ | ||
1153 | static void xs_tcp_schedule_linger_timeout(struct rpc_xprt *xprt, | ||
1154 | unsigned long timeout) | ||
1155 | { | ||
1156 | struct sock_xprt *transport; | ||
1157 | |||
1158 | if (xprt_test_and_set_connecting(xprt)) | ||
1159 | return; | ||
1160 | set_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
1161 | transport = container_of(xprt, struct sock_xprt, xprt); | ||
1162 | queue_delayed_work(rpciod_workqueue, &transport->connect_worker, | ||
1163 | timeout); | ||
1164 | } | ||
1165 | |||
1166 | static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) | ||
1167 | { | ||
1168 | struct sock_xprt *transport; | ||
1169 | |||
1170 | transport = container_of(xprt, struct sock_xprt, xprt); | ||
1171 | |||
1172 | if (!test_bit(XPRT_CONNECTION_ABORT, &xprt->state) || | ||
1173 | !cancel_delayed_work(&transport->connect_worker)) | ||
1174 | return; | ||
1175 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
1176 | xprt_clear_connecting(xprt); | ||
1177 | } | ||
1178 | |||
1179 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) | ||
1180 | { | ||
1181 | smp_mb__before_clear_bit(); | ||
1182 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
1183 | clear_bit(XPRT_CLOSING, &xprt->state); | ||
1184 | smp_mb__after_clear_bit(); | ||
1185 | /* Mark transport as closed and wake up all pending tasks */ | ||
1186 | xprt_disconnect_done(xprt); | ||
1187 | } | ||
1188 | |||
1129 | /** | 1189 | /** |
1130 | * xs_tcp_state_change - callback to handle TCP socket state changes | 1190 | * xs_tcp_state_change - callback to handle TCP socket state changes |
1131 | * @sk: socket whose state has changed | 1191 | * @sk: socket whose state has changed |
@@ -1158,7 +1218,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1158 | transport->tcp_flags = | 1218 | transport->tcp_flags = |
1159 | TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; | 1219 | TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; |
1160 | 1220 | ||
1161 | xprt_wake_pending_tasks(xprt, 0); | 1221 | xprt_wake_pending_tasks(xprt, -EAGAIN); |
1162 | } | 1222 | } |
1163 | spin_unlock_bh(&xprt->transport_lock); | 1223 | spin_unlock_bh(&xprt->transport_lock); |
1164 | break; | 1224 | break; |
@@ -1171,10 +1231,10 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1171 | clear_bit(XPRT_CONNECTED, &xprt->state); | 1231 | clear_bit(XPRT_CONNECTED, &xprt->state); |
1172 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1232 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); |
1173 | smp_mb__after_clear_bit(); | 1233 | smp_mb__after_clear_bit(); |
1234 | xs_tcp_schedule_linger_timeout(xprt, xs_tcp_fin_timeout); | ||
1174 | break; | 1235 | break; |
1175 | case TCP_CLOSE_WAIT: | 1236 | case TCP_CLOSE_WAIT: |
1176 | /* The server initiated a shutdown of the socket */ | 1237 | /* The server initiated a shutdown of the socket */ |
1177 | set_bit(XPRT_CLOSING, &xprt->state); | ||
1178 | xprt_force_disconnect(xprt); | 1238 | xprt_force_disconnect(xprt); |
1179 | case TCP_SYN_SENT: | 1239 | case TCP_SYN_SENT: |
1180 | xprt->connect_cookie++; | 1240 | xprt->connect_cookie++; |
@@ -1187,40 +1247,35 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1187 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | 1247 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; |
1188 | break; | 1248 | break; |
1189 | case TCP_LAST_ACK: | 1249 | case TCP_LAST_ACK: |
1250 | set_bit(XPRT_CLOSING, &xprt->state); | ||
1251 | xs_tcp_schedule_linger_timeout(xprt, xs_tcp_fin_timeout); | ||
1190 | smp_mb__before_clear_bit(); | 1252 | smp_mb__before_clear_bit(); |
1191 | clear_bit(XPRT_CONNECTED, &xprt->state); | 1253 | clear_bit(XPRT_CONNECTED, &xprt->state); |
1192 | smp_mb__after_clear_bit(); | 1254 | smp_mb__after_clear_bit(); |
1193 | break; | 1255 | break; |
1194 | case TCP_CLOSE: | 1256 | case TCP_CLOSE: |
1195 | smp_mb__before_clear_bit(); | 1257 | xs_tcp_cancel_linger_timeout(xprt); |
1196 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1258 | xs_sock_mark_closed(xprt); |
1197 | clear_bit(XPRT_CLOSING, &xprt->state); | ||
1198 | smp_mb__after_clear_bit(); | ||
1199 | /* Mark transport as closed and wake up all pending tasks */ | ||
1200 | xprt_disconnect_done(xprt); | ||
1201 | } | 1259 | } |
1202 | out: | 1260 | out: |
1203 | read_unlock(&sk->sk_callback_lock); | 1261 | read_unlock(&sk->sk_callback_lock); |
1204 | } | 1262 | } |
1205 | 1263 | ||
1206 | /** | 1264 | /** |
1207 | * xs_tcp_error_report - callback mainly for catching RST events | 1265 | * xs_error_report - callback mainly for catching socket errors |
1208 | * @sk: socket | 1266 | * @sk: socket |
1209 | */ | 1267 | */ |
1210 | static void xs_tcp_error_report(struct sock *sk) | 1268 | static void xs_error_report(struct sock *sk) |
1211 | { | 1269 | { |
1212 | struct rpc_xprt *xprt; | 1270 | struct rpc_xprt *xprt; |
1213 | 1271 | ||
1214 | read_lock(&sk->sk_callback_lock); | 1272 | read_lock(&sk->sk_callback_lock); |
1215 | if (sk->sk_err != ECONNRESET || sk->sk_state != TCP_ESTABLISHED) | ||
1216 | goto out; | ||
1217 | if (!(xprt = xprt_from_sock(sk))) | 1273 | if (!(xprt = xprt_from_sock(sk))) |
1218 | goto out; | 1274 | goto out; |
1219 | dprintk("RPC: %s client %p...\n" | 1275 | dprintk("RPC: %s client %p...\n" |
1220 | "RPC: error %d\n", | 1276 | "RPC: error %d\n", |
1221 | __func__, xprt, sk->sk_err); | 1277 | __func__, xprt, sk->sk_err); |
1222 | 1278 | xprt_wake_pending_tasks(xprt, -EAGAIN); | |
1223 | xprt_force_disconnect(xprt); | ||
1224 | out: | 1279 | out: |
1225 | read_unlock(&sk->sk_callback_lock); | 1280 | read_unlock(&sk->sk_callback_lock); |
1226 | } | 1281 | } |
@@ -1494,6 +1549,7 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1494 | sk->sk_user_data = xprt; | 1549 | sk->sk_user_data = xprt; |
1495 | sk->sk_data_ready = xs_udp_data_ready; | 1550 | sk->sk_data_ready = xs_udp_data_ready; |
1496 | sk->sk_write_space = xs_udp_write_space; | 1551 | sk->sk_write_space = xs_udp_write_space; |
1552 | sk->sk_error_report = xs_error_report; | ||
1497 | sk->sk_no_check = UDP_CSUM_NORCV; | 1553 | sk->sk_no_check = UDP_CSUM_NORCV; |
1498 | sk->sk_allocation = GFP_ATOMIC; | 1554 | sk->sk_allocation = GFP_ATOMIC; |
1499 | 1555 | ||
@@ -1526,9 +1582,10 @@ static void xs_udp_connect_worker4(struct work_struct *work) | |||
1526 | goto out; | 1582 | goto out; |
1527 | 1583 | ||
1528 | /* Start by resetting any existing state */ | 1584 | /* Start by resetting any existing state */ |
1529 | xs_close(xprt); | 1585 | xs_reset_transport(transport); |
1530 | 1586 | ||
1531 | if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { | 1587 | err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); |
1588 | if (err < 0) { | ||
1532 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | 1589 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
1533 | goto out; | 1590 | goto out; |
1534 | } | 1591 | } |
@@ -1545,8 +1602,8 @@ static void xs_udp_connect_worker4(struct work_struct *work) | |||
1545 | xs_udp_finish_connecting(xprt, sock); | 1602 | xs_udp_finish_connecting(xprt, sock); |
1546 | status = 0; | 1603 | status = 0; |
1547 | out: | 1604 | out: |
1548 | xprt_wake_pending_tasks(xprt, status); | ||
1549 | xprt_clear_connecting(xprt); | 1605 | xprt_clear_connecting(xprt); |
1606 | xprt_wake_pending_tasks(xprt, status); | ||
1550 | } | 1607 | } |
1551 | 1608 | ||
1552 | /** | 1609 | /** |
@@ -1567,9 +1624,10 @@ static void xs_udp_connect_worker6(struct work_struct *work) | |||
1567 | goto out; | 1624 | goto out; |
1568 | 1625 | ||
1569 | /* Start by resetting any existing state */ | 1626 | /* Start by resetting any existing state */ |
1570 | xs_close(xprt); | 1627 | xs_reset_transport(transport); |
1571 | 1628 | ||
1572 | if ((err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { | 1629 | err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock); |
1630 | if (err < 0) { | ||
1573 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | 1631 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
1574 | goto out; | 1632 | goto out; |
1575 | } | 1633 | } |
@@ -1586,18 +1644,17 @@ static void xs_udp_connect_worker6(struct work_struct *work) | |||
1586 | xs_udp_finish_connecting(xprt, sock); | 1644 | xs_udp_finish_connecting(xprt, sock); |
1587 | status = 0; | 1645 | status = 0; |
1588 | out: | 1646 | out: |
1589 | xprt_wake_pending_tasks(xprt, status); | ||
1590 | xprt_clear_connecting(xprt); | 1647 | xprt_clear_connecting(xprt); |
1648 | xprt_wake_pending_tasks(xprt, status); | ||
1591 | } | 1649 | } |
1592 | 1650 | ||
1593 | /* | 1651 | /* |
1594 | * We need to preserve the port number so the reply cache on the server can | 1652 | * We need to preserve the port number so the reply cache on the server can |
1595 | * find our cached RPC replies when we get around to reconnecting. | 1653 | * find our cached RPC replies when we get around to reconnecting. |
1596 | */ | 1654 | */ |
1597 | static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) | 1655 | static void xs_abort_connection(struct rpc_xprt *xprt, struct sock_xprt *transport) |
1598 | { | 1656 | { |
1599 | int result; | 1657 | int result; |
1600 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
1601 | struct sockaddr any; | 1658 | struct sockaddr any; |
1602 | 1659 | ||
1603 | dprintk("RPC: disconnecting xprt %p to reuse port\n", xprt); | 1660 | dprintk("RPC: disconnecting xprt %p to reuse port\n", xprt); |
@@ -1609,11 +1666,24 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) | |||
1609 | memset(&any, 0, sizeof(any)); | 1666 | memset(&any, 0, sizeof(any)); |
1610 | any.sa_family = AF_UNSPEC; | 1667 | any.sa_family = AF_UNSPEC; |
1611 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); | 1668 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); |
1612 | if (result) | 1669 | if (!result) |
1670 | xs_sock_mark_closed(xprt); | ||
1671 | else | ||
1613 | dprintk("RPC: AF_UNSPEC connect return code %d\n", | 1672 | dprintk("RPC: AF_UNSPEC connect return code %d\n", |
1614 | result); | 1673 | result); |
1615 | } | 1674 | } |
1616 | 1675 | ||
1676 | static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *transport) | ||
1677 | { | ||
1678 | unsigned int state = transport->inet->sk_state; | ||
1679 | |||
1680 | if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) | ||
1681 | return; | ||
1682 | if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) | ||
1683 | return; | ||
1684 | xs_abort_connection(xprt, transport); | ||
1685 | } | ||
1686 | |||
1617 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | 1687 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
1618 | { | 1688 | { |
1619 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1689 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
@@ -1629,7 +1699,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1629 | sk->sk_data_ready = xs_tcp_data_ready; | 1699 | sk->sk_data_ready = xs_tcp_data_ready; |
1630 | sk->sk_state_change = xs_tcp_state_change; | 1700 | sk->sk_state_change = xs_tcp_state_change; |
1631 | sk->sk_write_space = xs_tcp_write_space; | 1701 | sk->sk_write_space = xs_tcp_write_space; |
1632 | sk->sk_error_report = xs_tcp_error_report; | 1702 | sk->sk_error_report = xs_error_report; |
1633 | sk->sk_allocation = GFP_ATOMIC; | 1703 | sk->sk_allocation = GFP_ATOMIC; |
1634 | 1704 | ||
1635 | /* socket options */ | 1705 | /* socket options */ |
@@ -1657,37 +1727,42 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1657 | } | 1727 | } |
1658 | 1728 | ||
1659 | /** | 1729 | /** |
1660 | * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint | 1730 | * xs_tcp_setup_socket - create a TCP socket and connect to a remote endpoint |
1661 | * @work: RPC transport to connect | 1731 | * @xprt: RPC transport to connect |
1732 | * @transport: socket transport to connect | ||
1733 | * @create_sock: function to create a socket of the correct type | ||
1662 | * | 1734 | * |
1663 | * Invoked by a work queue tasklet. | 1735 | * Invoked by a work queue tasklet. |
1664 | */ | 1736 | */ |
1665 | static void xs_tcp_connect_worker4(struct work_struct *work) | 1737 | static void xs_tcp_setup_socket(struct rpc_xprt *xprt, |
1738 | struct sock_xprt *transport, | ||
1739 | struct socket *(*create_sock)(struct rpc_xprt *, | ||
1740 | struct sock_xprt *)) | ||
1666 | { | 1741 | { |
1667 | struct sock_xprt *transport = | ||
1668 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1669 | struct rpc_xprt *xprt = &transport->xprt; | ||
1670 | struct socket *sock = transport->sock; | 1742 | struct socket *sock = transport->sock; |
1671 | int err, status = -EIO; | 1743 | int status = -EIO; |
1672 | 1744 | ||
1673 | if (xprt->shutdown) | 1745 | if (xprt->shutdown) |
1674 | goto out; | 1746 | goto out; |
1675 | 1747 | ||
1676 | if (!sock) { | 1748 | if (!sock) { |
1677 | /* start from scratch */ | 1749 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
1678 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | 1750 | sock = create_sock(xprt, transport); |
1679 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | 1751 | if (IS_ERR(sock)) { |
1752 | status = PTR_ERR(sock); | ||
1680 | goto out; | 1753 | goto out; |
1681 | } | 1754 | } |
1682 | xs_reclassify_socket4(sock); | 1755 | } else { |
1756 | int abort_and_exit; | ||
1683 | 1757 | ||
1684 | if (xs_bind4(transport, sock) < 0) { | 1758 | abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, |
1685 | sock_release(sock); | 1759 | &xprt->state); |
1686 | goto out; | ||
1687 | } | ||
1688 | } else | ||
1689 | /* "close" the socket, preserving the local port */ | 1760 | /* "close" the socket, preserving the local port */ |
1690 | xs_tcp_reuse_connection(xprt); | 1761 | xs_tcp_reuse_connection(xprt, transport); |
1762 | |||
1763 | if (abort_and_exit) | ||
1764 | goto out_eagain; | ||
1765 | } | ||
1691 | 1766 | ||
1692 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1767 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1693 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1768 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
@@ -1696,83 +1771,104 @@ static void xs_tcp_connect_worker4(struct work_struct *work) | |||
1696 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 1771 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
1697 | xprt, -status, xprt_connected(xprt), | 1772 | xprt, -status, xprt_connected(xprt), |
1698 | sock->sk->sk_state); | 1773 | sock->sk->sk_state); |
1699 | if (status < 0) { | 1774 | switch (status) { |
1700 | switch (status) { | 1775 | case -ECONNREFUSED: |
1701 | case -EINPROGRESS: | 1776 | case -ECONNRESET: |
1702 | case -EALREADY: | 1777 | case -ENETUNREACH: |
1703 | goto out_clear; | 1778 | /* retry with existing socket, after a delay */ |
1704 | case -ECONNREFUSED: | 1779 | case 0: |
1705 | case -ECONNRESET: | 1780 | case -EINPROGRESS: |
1706 | /* retry with existing socket, after a delay */ | 1781 | case -EALREADY: |
1707 | break; | 1782 | xprt_clear_connecting(xprt); |
1708 | default: | 1783 | return; |
1709 | /* get rid of existing socket, and retry */ | ||
1710 | xs_tcp_shutdown(xprt); | ||
1711 | } | ||
1712 | } | 1784 | } |
1785 | /* get rid of existing socket, and retry */ | ||
1786 | xs_tcp_shutdown(xprt); | ||
1787 | printk("%s: connect returned unhandled error %d\n", | ||
1788 | __func__, status); | ||
1789 | out_eagain: | ||
1790 | status = -EAGAIN; | ||
1713 | out: | 1791 | out: |
1714 | xprt_wake_pending_tasks(xprt, status); | ||
1715 | out_clear: | ||
1716 | xprt_clear_connecting(xprt); | 1792 | xprt_clear_connecting(xprt); |
1793 | xprt_wake_pending_tasks(xprt, status); | ||
1794 | } | ||
1795 | |||
1796 | static struct socket *xs_create_tcp_sock4(struct rpc_xprt *xprt, | ||
1797 | struct sock_xprt *transport) | ||
1798 | { | ||
1799 | struct socket *sock; | ||
1800 | int err; | ||
1801 | |||
1802 | /* start from scratch */ | ||
1803 | err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); | ||
1804 | if (err < 0) { | ||
1805 | dprintk("RPC: can't create TCP transport socket (%d).\n", | ||
1806 | -err); | ||
1807 | goto out_err; | ||
1808 | } | ||
1809 | xs_reclassify_socket4(sock); | ||
1810 | |||
1811 | if (xs_bind4(transport, sock) < 0) { | ||
1812 | sock_release(sock); | ||
1813 | goto out_err; | ||
1814 | } | ||
1815 | return sock; | ||
1816 | out_err: | ||
1817 | return ERR_PTR(-EIO); | ||
1717 | } | 1818 | } |
1718 | 1819 | ||
1719 | /** | 1820 | /** |
1720 | * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint | 1821 | * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint |
1721 | * @work: RPC transport to connect | 1822 | * @work: RPC transport to connect |
1722 | * | 1823 | * |
1723 | * Invoked by a work queue tasklet. | 1824 | * Invoked by a work queue tasklet. |
1724 | */ | 1825 | */ |
1725 | static void xs_tcp_connect_worker6(struct work_struct *work) | 1826 | static void xs_tcp_connect_worker4(struct work_struct *work) |
1726 | { | 1827 | { |
1727 | struct sock_xprt *transport = | 1828 | struct sock_xprt *transport = |
1728 | container_of(work, struct sock_xprt, connect_worker.work); | 1829 | container_of(work, struct sock_xprt, connect_worker.work); |
1729 | struct rpc_xprt *xprt = &transport->xprt; | 1830 | struct rpc_xprt *xprt = &transport->xprt; |
1730 | struct socket *sock = transport->sock; | ||
1731 | int err, status = -EIO; | ||
1732 | 1831 | ||
1733 | if (xprt->shutdown) | 1832 | xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock4); |
1734 | goto out; | 1833 | } |
1735 | 1834 | ||
1736 | if (!sock) { | 1835 | static struct socket *xs_create_tcp_sock6(struct rpc_xprt *xprt, |
1737 | /* start from scratch */ | 1836 | struct sock_xprt *transport) |
1738 | if ((err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | 1837 | { |
1739 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | 1838 | struct socket *sock; |
1740 | goto out; | 1839 | int err; |
1741 | } | 1840 | |
1742 | xs_reclassify_socket6(sock); | 1841 | /* start from scratch */ |
1842 | err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock); | ||
1843 | if (err < 0) { | ||
1844 | dprintk("RPC: can't create TCP transport socket (%d).\n", | ||
1845 | -err); | ||
1846 | goto out_err; | ||
1847 | } | ||
1848 | xs_reclassify_socket6(sock); | ||
1743 | 1849 | ||
1744 | if (xs_bind6(transport, sock) < 0) { | 1850 | if (xs_bind6(transport, sock) < 0) { |
1745 | sock_release(sock); | 1851 | sock_release(sock); |
1746 | goto out; | 1852 | goto out_err; |
1747 | } | 1853 | } |
1748 | } else | 1854 | return sock; |
1749 | /* "close" the socket, preserving the local port */ | 1855 | out_err: |
1750 | xs_tcp_reuse_connection(xprt); | 1856 | return ERR_PTR(-EIO); |
1857 | } | ||
1751 | 1858 | ||
1752 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1859 | /** |
1753 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1860 | * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint |
1861 | * @work: RPC transport to connect | ||
1862 | * | ||
1863 | * Invoked by a work queue tasklet. | ||
1864 | */ | ||
1865 | static void xs_tcp_connect_worker6(struct work_struct *work) | ||
1866 | { | ||
1867 | struct sock_xprt *transport = | ||
1868 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1869 | struct rpc_xprt *xprt = &transport->xprt; | ||
1754 | 1870 | ||
1755 | status = xs_tcp_finish_connecting(xprt, sock); | 1871 | xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock6); |
1756 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | ||
1757 | xprt, -status, xprt_connected(xprt), sock->sk->sk_state); | ||
1758 | if (status < 0) { | ||
1759 | switch (status) { | ||
1760 | case -EINPROGRESS: | ||
1761 | case -EALREADY: | ||
1762 | goto out_clear; | ||
1763 | case -ECONNREFUSED: | ||
1764 | case -ECONNRESET: | ||
1765 | /* retry with existing socket, after a delay */ | ||
1766 | break; | ||
1767 | default: | ||
1768 | /* get rid of existing socket, and retry */ | ||
1769 | xs_tcp_shutdown(xprt); | ||
1770 | } | ||
1771 | } | ||
1772 | out: | ||
1773 | xprt_wake_pending_tasks(xprt, status); | ||
1774 | out_clear: | ||
1775 | xprt_clear_connecting(xprt); | ||
1776 | } | 1872 | } |
1777 | 1873 | ||
1778 | /** | 1874 | /** |
@@ -1817,9 +1913,6 @@ static void xs_tcp_connect(struct rpc_task *task) | |||
1817 | { | 1913 | { |
1818 | struct rpc_xprt *xprt = task->tk_xprt; | 1914 | struct rpc_xprt *xprt = task->tk_xprt; |
1819 | 1915 | ||
1820 | /* Initiate graceful shutdown of the socket if not already done */ | ||
1821 | if (test_bit(XPRT_CONNECTED, &xprt->state)) | ||
1822 | xs_tcp_shutdown(xprt); | ||
1823 | /* Exit if we need to wait for socket shutdown to complete */ | 1916 | /* Exit if we need to wait for socket shutdown to complete */ |
1824 | if (test_bit(XPRT_CLOSING, &xprt->state)) | 1917 | if (test_bit(XPRT_CLOSING, &xprt->state)) |
1825 | return; | 1918 | return; |