diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-08 12:49:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-08 12:49:23 -0400 |
commit | 25641c0c8d72f3d235c022fd2c19181912c2ae8b (patch) | |
tree | c8970effb0f33eb870777031162de5d1bfd0ec08 /net | |
parent | ef0625b70dac9405ac9d9928cf767108041a9e51 (diff) | |
parent | 72c23f0819977d37924af92a42a9b7fbfd1c95d8 (diff) |
Merge tag 'nfs-for-3.18-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Highlights include:
Stable fixes:
- fix an NFSv4.1 state renewal regression
- fix open/lock state recovery error handling
- fix lock recovery when CREATE_SESSION/SETCLIENTID_CONFIRM fails
- fix statd when reconnection fails
- don't wake tasks during connection abort
- don't start reboot recovery if lease check fails
- fix duplicate proc entries
Features:
- pNFS block driver fixes and clean ups from Christoph
- More code cleanups from Anna
- Improve mmap() writeback performance
- Replace use of PF_TRANS with a more generic mechanism for avoiding
deadlocks in nfs_release_page"
* tag 'nfs-for-3.18-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (66 commits)
NFSv4.1: Fix an NFSv4.1 state renewal regression
NFSv4: fix open/lock state recovery error handling
NFSv4: Fix lock recovery when CREATE_SESSION/SETCLIENTID_CONFIRM fails
NFS: Fabricate fscache server index key correctly
SUNRPC: Add missing support for RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT
NFSv3: Fix missing includes of nfs3_fs.h
NFS/SUNRPC: Remove other deadlock-avoidance mechanisms in nfs_release_page()
NFS: avoid waiting at all in nfs_release_page when congested.
NFS: avoid deadlocks with loop-back mounted NFS filesystems.
MM: export page_wakeup functions
SCHED: add some "wait..on_bit...timeout()" interfaces.
NFS: don't use STABLE writes during writeback.
NFSv4: use exponential retry on NFS4ERR_DELAY for async requests.
rpc: Add -EPERM processing for xs_udp_send_request()
rpc: return sent and err from xs_sendpages()
lockd: Try to reconnect if statd has moved
SUNRPC: Don't wake tasks during connection abort
Fixing lease renewal
nfs: fix duplicate proc entries
pnfs/blocklayout: Fix a 64-bit division/remainder issue in bl_map_stripe
...
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/clnt.c | 5 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/transport.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 121 |
4 files changed, 75 insertions, 55 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 488ddeed9363..9acd6ce88db7 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -461,6 +461,8 @@ struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, | |||
461 | 461 | ||
462 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) | 462 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) |
463 | clnt->cl_autobind = 1; | 463 | clnt->cl_autobind = 1; |
464 | if (args->flags & RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT) | ||
465 | clnt->cl_noretranstimeo = 1; | ||
464 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) | 466 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) |
465 | clnt->cl_discrtry = 1; | 467 | clnt->cl_discrtry = 1; |
466 | if (!(args->flags & RPC_CLNT_CREATE_QUIET)) | 468 | if (!(args->flags & RPC_CLNT_CREATE_QUIET)) |
@@ -579,6 +581,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, | |||
579 | /* Turn off autobind on clones */ | 581 | /* Turn off autobind on clones */ |
580 | new->cl_autobind = 0; | 582 | new->cl_autobind = 0; |
581 | new->cl_softrtry = clnt->cl_softrtry; | 583 | new->cl_softrtry = clnt->cl_softrtry; |
584 | new->cl_noretranstimeo = clnt->cl_noretranstimeo; | ||
582 | new->cl_discrtry = clnt->cl_discrtry; | 585 | new->cl_discrtry = clnt->cl_discrtry; |
583 | new->cl_chatty = clnt->cl_chatty; | 586 | new->cl_chatty = clnt->cl_chatty; |
584 | return new; | 587 | return new; |
@@ -1913,6 +1916,7 @@ call_transmit_status(struct rpc_task *task) | |||
1913 | case -EHOSTDOWN: | 1916 | case -EHOSTDOWN: |
1914 | case -EHOSTUNREACH: | 1917 | case -EHOSTUNREACH: |
1915 | case -ENETUNREACH: | 1918 | case -ENETUNREACH: |
1919 | case -EPERM: | ||
1916 | if (RPC_IS_SOFTCONN(task)) { | 1920 | if (RPC_IS_SOFTCONN(task)) { |
1917 | xprt_end_transmit(task); | 1921 | xprt_end_transmit(task); |
1918 | rpc_exit(task, task->tk_status); | 1922 | rpc_exit(task, task->tk_status); |
@@ -2018,6 +2022,7 @@ call_status(struct rpc_task *task) | |||
2018 | case -EHOSTDOWN: | 2022 | case -EHOSTDOWN: |
2019 | case -EHOSTUNREACH: | 2023 | case -EHOSTUNREACH: |
2020 | case -ENETUNREACH: | 2024 | case -ENETUNREACH: |
2025 | case -EPERM: | ||
2021 | if (RPC_IS_SOFTCONN(task)) { | 2026 | if (RPC_IS_SOFTCONN(task)) { |
2022 | rpc_exit(task, status); | 2027 | rpc_exit(task, status); |
2023 | break; | 2028 | break; |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 9358c79fd589..fe3441abdbe5 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -821,9 +821,7 @@ void rpc_execute(struct rpc_task *task) | |||
821 | 821 | ||
822 | static void rpc_async_schedule(struct work_struct *work) | 822 | static void rpc_async_schedule(struct work_struct *work) |
823 | { | 823 | { |
824 | current->flags |= PF_FSTRANS; | ||
825 | __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); | 824 | __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); |
826 | current->flags &= ~PF_FSTRANS; | ||
827 | } | 825 | } |
828 | 826 | ||
829 | /** | 827 | /** |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 2faac4940563..6a4615dd0261 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -205,7 +205,6 @@ xprt_rdma_connect_worker(struct work_struct *work) | |||
205 | struct rpc_xprt *xprt = &r_xprt->xprt; | 205 | struct rpc_xprt *xprt = &r_xprt->xprt; |
206 | int rc = 0; | 206 | int rc = 0; |
207 | 207 | ||
208 | current->flags |= PF_FSTRANS; | ||
209 | xprt_clear_connected(xprt); | 208 | xprt_clear_connected(xprt); |
210 | 209 | ||
211 | dprintk("RPC: %s: %sconnect\n", __func__, | 210 | dprintk("RPC: %s: %sconnect\n", __func__, |
@@ -216,7 +215,6 @@ xprt_rdma_connect_worker(struct work_struct *work) | |||
216 | 215 | ||
217 | dprintk("RPC: %s: exit\n", __func__); | 216 | dprintk("RPC: %s: exit\n", __func__); |
218 | xprt_clear_connecting(xprt); | 217 | xprt_clear_connecting(xprt); |
219 | current->flags &= ~PF_FSTRANS; | ||
220 | } | 218 | } |
221 | 219 | ||
222 | /* | 220 | /* |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 43cd89eacfab..3b305ab17afe 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -399,13 +399,13 @@ static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen, | |||
399 | return kernel_sendmsg(sock, &msg, NULL, 0, 0); | 399 | return kernel_sendmsg(sock, &msg, NULL, 0, 0); |
400 | } | 400 | } |
401 | 401 | ||
402 | static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy) | 402 | static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy, int *sent_p) |
403 | { | 403 | { |
404 | ssize_t (*do_sendpage)(struct socket *sock, struct page *page, | 404 | ssize_t (*do_sendpage)(struct socket *sock, struct page *page, |
405 | int offset, size_t size, int flags); | 405 | int offset, size_t size, int flags); |
406 | struct page **ppage; | 406 | struct page **ppage; |
407 | unsigned int remainder; | 407 | unsigned int remainder; |
408 | int err, sent = 0; | 408 | int err; |
409 | 409 | ||
410 | remainder = xdr->page_len - base; | 410 | remainder = xdr->page_len - base; |
411 | base += xdr->page_base; | 411 | base += xdr->page_base; |
@@ -424,15 +424,15 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i | |||
424 | err = do_sendpage(sock, *ppage, base, len, flags); | 424 | err = do_sendpage(sock, *ppage, base, len, flags); |
425 | if (remainder == 0 || err != len) | 425 | if (remainder == 0 || err != len) |
426 | break; | 426 | break; |
427 | sent += err; | 427 | *sent_p += err; |
428 | ppage++; | 428 | ppage++; |
429 | base = 0; | 429 | base = 0; |
430 | } | 430 | } |
431 | if (sent == 0) | 431 | if (err > 0) { |
432 | return err; | 432 | *sent_p += err; |
433 | if (err > 0) | 433 | err = 0; |
434 | sent += err; | 434 | } |
435 | return sent; | 435 | return err; |
436 | } | 436 | } |
437 | 437 | ||
438 | /** | 438 | /** |
@@ -443,12 +443,14 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i | |||
443 | * @xdr: buffer containing this request | 443 | * @xdr: buffer containing this request |
444 | * @base: starting position in the buffer | 444 | * @base: starting position in the buffer |
445 | * @zerocopy: true if it is safe to use sendpage() | 445 | * @zerocopy: true if it is safe to use sendpage() |
446 | * @sent_p: return the total number of bytes successfully queued for sending | ||
446 | * | 447 | * |
447 | */ | 448 | */ |
448 | static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy) | 449 | static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy, int *sent_p) |
449 | { | 450 | { |
450 | unsigned int remainder = xdr->len - base; | 451 | unsigned int remainder = xdr->len - base; |
451 | int err, sent = 0; | 452 | int err = 0; |
453 | int sent = 0; | ||
452 | 454 | ||
453 | if (unlikely(!sock)) | 455 | if (unlikely(!sock)) |
454 | return -ENOTSOCK; | 456 | return -ENOTSOCK; |
@@ -465,7 +467,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, | |||
465 | err = xs_send_kvec(sock, addr, addrlen, &xdr->head[0], base, remainder != 0); | 467 | err = xs_send_kvec(sock, addr, addrlen, &xdr->head[0], base, remainder != 0); |
466 | if (remainder == 0 || err != len) | 468 | if (remainder == 0 || err != len) |
467 | goto out; | 469 | goto out; |
468 | sent += err; | 470 | *sent_p += err; |
469 | base = 0; | 471 | base = 0; |
470 | } else | 472 | } else |
471 | base -= xdr->head[0].iov_len; | 473 | base -= xdr->head[0].iov_len; |
@@ -473,23 +475,23 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, | |||
473 | if (base < xdr->page_len) { | 475 | if (base < xdr->page_len) { |
474 | unsigned int len = xdr->page_len - base; | 476 | unsigned int len = xdr->page_len - base; |
475 | remainder -= len; | 477 | remainder -= len; |
476 | err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy); | 478 | err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy, &sent); |
477 | if (remainder == 0 || err != len) | 479 | *sent_p += sent; |
480 | if (remainder == 0 || sent != len) | ||
478 | goto out; | 481 | goto out; |
479 | sent += err; | ||
480 | base = 0; | 482 | base = 0; |
481 | } else | 483 | } else |
482 | base -= xdr->page_len; | 484 | base -= xdr->page_len; |
483 | 485 | ||
484 | if (base >= xdr->tail[0].iov_len) | 486 | if (base >= xdr->tail[0].iov_len) |
485 | return sent; | 487 | return 0; |
486 | err = xs_send_kvec(sock, NULL, 0, &xdr->tail[0], base, 0); | 488 | err = xs_send_kvec(sock, NULL, 0, &xdr->tail[0], base, 0); |
487 | out: | 489 | out: |
488 | if (sent == 0) | 490 | if (err > 0) { |
489 | return err; | 491 | *sent_p += err; |
490 | if (err > 0) | 492 | err = 0; |
491 | sent += err; | 493 | } |
492 | return sent; | 494 | return err; |
493 | } | 495 | } |
494 | 496 | ||
495 | static void xs_nospace_callback(struct rpc_task *task) | 497 | static void xs_nospace_callback(struct rpc_task *task) |
@@ -573,19 +575,20 @@ static int xs_local_send_request(struct rpc_task *task) | |||
573 | container_of(xprt, struct sock_xprt, xprt); | 575 | container_of(xprt, struct sock_xprt, xprt); |
574 | struct xdr_buf *xdr = &req->rq_snd_buf; | 576 | struct xdr_buf *xdr = &req->rq_snd_buf; |
575 | int status; | 577 | int status; |
578 | int sent = 0; | ||
576 | 579 | ||
577 | xs_encode_stream_record_marker(&req->rq_snd_buf); | 580 | xs_encode_stream_record_marker(&req->rq_snd_buf); |
578 | 581 | ||
579 | xs_pktdump("packet data:", | 582 | xs_pktdump("packet data:", |
580 | req->rq_svec->iov_base, req->rq_svec->iov_len); | 583 | req->rq_svec->iov_base, req->rq_svec->iov_len); |
581 | 584 | ||
582 | status = xs_sendpages(transport->sock, NULL, 0, | 585 | status = xs_sendpages(transport->sock, NULL, 0, xdr, req->rq_bytes_sent, |
583 | xdr, req->rq_bytes_sent, true); | 586 | true, &sent); |
584 | dprintk("RPC: %s(%u) = %d\n", | 587 | dprintk("RPC: %s(%u) = %d\n", |
585 | __func__, xdr->len - req->rq_bytes_sent, status); | 588 | __func__, xdr->len - req->rq_bytes_sent, status); |
586 | if (likely(status >= 0)) { | 589 | if (likely(sent > 0) || status == 0) { |
587 | req->rq_bytes_sent += status; | 590 | req->rq_bytes_sent += sent; |
588 | req->rq_xmit_bytes_sent += status; | 591 | req->rq_xmit_bytes_sent += sent; |
589 | if (likely(req->rq_bytes_sent >= req->rq_slen)) { | 592 | if (likely(req->rq_bytes_sent >= req->rq_slen)) { |
590 | req->rq_bytes_sent = 0; | 593 | req->rq_bytes_sent = 0; |
591 | return 0; | 594 | return 0; |
@@ -626,6 +629,7 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
626 | struct rpc_xprt *xprt = req->rq_xprt; | 629 | struct rpc_xprt *xprt = req->rq_xprt; |
627 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 630 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
628 | struct xdr_buf *xdr = &req->rq_snd_buf; | 631 | struct xdr_buf *xdr = &req->rq_snd_buf; |
632 | int sent = 0; | ||
629 | int status; | 633 | int status; |
630 | 634 | ||
631 | xs_pktdump("packet data:", | 635 | xs_pktdump("packet data:", |
@@ -634,22 +638,25 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
634 | 638 | ||
635 | if (!xprt_bound(xprt)) | 639 | if (!xprt_bound(xprt)) |
636 | return -ENOTCONN; | 640 | return -ENOTCONN; |
637 | status = xs_sendpages(transport->sock, | 641 | status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, |
638 | xs_addr(xprt), | 642 | xdr, req->rq_bytes_sent, true, &sent); |
639 | xprt->addrlen, xdr, | ||
640 | req->rq_bytes_sent, true); | ||
641 | 643 | ||
642 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", | 644 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", |
643 | xdr->len - req->rq_bytes_sent, status); | 645 | xdr->len - req->rq_bytes_sent, status); |
644 | 646 | ||
645 | if (status >= 0) { | 647 | /* firewall is blocking us, don't return -EAGAIN or we end up looping */ |
646 | req->rq_xmit_bytes_sent += status; | 648 | if (status == -EPERM) |
647 | if (status >= req->rq_slen) | 649 | goto process_status; |
650 | |||
651 | if (sent > 0 || status == 0) { | ||
652 | req->rq_xmit_bytes_sent += sent; | ||
653 | if (sent >= req->rq_slen) | ||
648 | return 0; | 654 | return 0; |
649 | /* Still some bytes left; set up for a retry later. */ | 655 | /* Still some bytes left; set up for a retry later. */ |
650 | status = -EAGAIN; | 656 | status = -EAGAIN; |
651 | } | 657 | } |
652 | 658 | ||
659 | process_status: | ||
653 | switch (status) { | 660 | switch (status) { |
654 | case -ENOTSOCK: | 661 | case -ENOTSOCK: |
655 | status = -ENOTCONN; | 662 | status = -ENOTCONN; |
@@ -665,6 +672,7 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
665 | case -ENOBUFS: | 672 | case -ENOBUFS: |
666 | case -EPIPE: | 673 | case -EPIPE: |
667 | case -ECONNREFUSED: | 674 | case -ECONNREFUSED: |
675 | case -EPERM: | ||
668 | /* When the server has died, an ICMP port unreachable message | 676 | /* When the server has died, an ICMP port unreachable message |
669 | * prompts ECONNREFUSED. */ | 677 | * prompts ECONNREFUSED. */ |
670 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 678 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
@@ -713,6 +721,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
713 | struct xdr_buf *xdr = &req->rq_snd_buf; | 721 | struct xdr_buf *xdr = &req->rq_snd_buf; |
714 | bool zerocopy = true; | 722 | bool zerocopy = true; |
715 | int status; | 723 | int status; |
724 | int sent; | ||
716 | 725 | ||
717 | xs_encode_stream_record_marker(&req->rq_snd_buf); | 726 | xs_encode_stream_record_marker(&req->rq_snd_buf); |
718 | 727 | ||
@@ -730,26 +739,26 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
730 | * to cope with writespace callbacks arriving _after_ we have | 739 | * to cope with writespace callbacks arriving _after_ we have |
731 | * called sendmsg(). */ | 740 | * called sendmsg(). */ |
732 | while (1) { | 741 | while (1) { |
733 | status = xs_sendpages(transport->sock, | 742 | sent = 0; |
734 | NULL, 0, xdr, req->rq_bytes_sent, | 743 | status = xs_sendpages(transport->sock, NULL, 0, xdr, |
735 | zerocopy); | 744 | req->rq_bytes_sent, zerocopy, &sent); |
736 | 745 | ||
737 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", | 746 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", |
738 | xdr->len - req->rq_bytes_sent, status); | 747 | xdr->len - req->rq_bytes_sent, status); |
739 | 748 | ||
740 | if (unlikely(status < 0)) | 749 | if (unlikely(sent == 0 && status < 0)) |
741 | break; | 750 | break; |
742 | 751 | ||
743 | /* If we've sent the entire packet, immediately | 752 | /* If we've sent the entire packet, immediately |
744 | * reset the count of bytes sent. */ | 753 | * reset the count of bytes sent. */ |
745 | req->rq_bytes_sent += status; | 754 | req->rq_bytes_sent += sent; |
746 | req->rq_xmit_bytes_sent += status; | 755 | req->rq_xmit_bytes_sent += sent; |
747 | if (likely(req->rq_bytes_sent >= req->rq_slen)) { | 756 | if (likely(req->rq_bytes_sent >= req->rq_slen)) { |
748 | req->rq_bytes_sent = 0; | 757 | req->rq_bytes_sent = 0; |
749 | return 0; | 758 | return 0; |
750 | } | 759 | } |
751 | 760 | ||
752 | if (status != 0) | 761 | if (sent != 0) |
753 | continue; | 762 | continue; |
754 | status = -EAGAIN; | 763 | status = -EAGAIN; |
755 | break; | 764 | break; |
@@ -845,6 +854,8 @@ static void xs_error_report(struct sock *sk) | |||
845 | dprintk("RPC: xs_error_report client %p, error=%d...\n", | 854 | dprintk("RPC: xs_error_report client %p, error=%d...\n", |
846 | xprt, -err); | 855 | xprt, -err); |
847 | trace_rpc_socket_error(xprt, sk->sk_socket, err); | 856 | trace_rpc_socket_error(xprt, sk->sk_socket, err); |
857 | if (test_bit(XPRT_CONNECTION_REUSE, &xprt->state)) | ||
858 | goto out; | ||
848 | xprt_wake_pending_tasks(xprt, err); | 859 | xprt_wake_pending_tasks(xprt, err); |
849 | out: | 860 | out: |
850 | read_unlock_bh(&sk->sk_callback_lock); | 861 | read_unlock_bh(&sk->sk_callback_lock); |
@@ -1746,13 +1757,29 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
1746 | unsigned short port = xs_get_srcport(transport); | 1757 | unsigned short port = xs_get_srcport(transport); |
1747 | unsigned short last; | 1758 | unsigned short last; |
1748 | 1759 | ||
1760 | /* | ||
1761 | * If we are asking for any ephemeral port (i.e. port == 0 && | ||
1762 | * transport->xprt.resvport == 0), don't bind. Let the local | ||
1763 | * port selection happen implicitly when the socket is used | ||
1764 | * (for example at connect time). | ||
1765 | * | ||
1766 | * This ensures that we can continue to establish TCP | ||
1767 | * connections even when all local ephemeral ports are already | ||
1768 | * a part of some TCP connection. This makes no difference | ||
1769 | * for UDP sockets, but also doens't harm them. | ||
1770 | * | ||
1771 | * If we're asking for any reserved port (i.e. port == 0 && | ||
1772 | * transport->xprt.resvport == 1) xs_get_srcport above will | ||
1773 | * ensure that port is non-zero and we will bind as needed. | ||
1774 | */ | ||
1775 | if (port == 0) | ||
1776 | return 0; | ||
1777 | |||
1749 | memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen); | 1778 | memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen); |
1750 | do { | 1779 | do { |
1751 | rpc_set_port((struct sockaddr *)&myaddr, port); | 1780 | rpc_set_port((struct sockaddr *)&myaddr, port); |
1752 | err = kernel_bind(sock, (struct sockaddr *)&myaddr, | 1781 | err = kernel_bind(sock, (struct sockaddr *)&myaddr, |
1753 | transport->xprt.addrlen); | 1782 | transport->xprt.addrlen); |
1754 | if (port == 0) | ||
1755 | break; | ||
1756 | if (err == 0) { | 1783 | if (err == 0) { |
1757 | transport->srcport = port; | 1784 | transport->srcport = port; |
1758 | break; | 1785 | break; |
@@ -1927,8 +1954,6 @@ static int xs_local_setup_socket(struct sock_xprt *transport) | |||
1927 | struct socket *sock; | 1954 | struct socket *sock; |
1928 | int status = -EIO; | 1955 | int status = -EIO; |
1929 | 1956 | ||
1930 | current->flags |= PF_FSTRANS; | ||
1931 | |||
1932 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | 1957 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
1933 | status = __sock_create(xprt->xprt_net, AF_LOCAL, | 1958 | status = __sock_create(xprt->xprt_net, AF_LOCAL, |
1934 | SOCK_STREAM, 0, &sock, 1); | 1959 | SOCK_STREAM, 0, &sock, 1); |
@@ -1968,7 +1993,6 @@ static int xs_local_setup_socket(struct sock_xprt *transport) | |||
1968 | out: | 1993 | out: |
1969 | xprt_clear_connecting(xprt); | 1994 | xprt_clear_connecting(xprt); |
1970 | xprt_wake_pending_tasks(xprt, status); | 1995 | xprt_wake_pending_tasks(xprt, status); |
1971 | current->flags &= ~PF_FSTRANS; | ||
1972 | return status; | 1996 | return status; |
1973 | } | 1997 | } |
1974 | 1998 | ||
@@ -2071,8 +2095,6 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
2071 | struct socket *sock = transport->sock; | 2095 | struct socket *sock = transport->sock; |
2072 | int status = -EIO; | 2096 | int status = -EIO; |
2073 | 2097 | ||
2074 | current->flags |= PF_FSTRANS; | ||
2075 | |||
2076 | /* Start by resetting any existing state */ | 2098 | /* Start by resetting any existing state */ |
2077 | xs_reset_transport(transport); | 2099 | xs_reset_transport(transport); |
2078 | sock = xs_create_sock(xprt, transport, | 2100 | sock = xs_create_sock(xprt, transport, |
@@ -2092,7 +2114,6 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
2092 | out: | 2114 | out: |
2093 | xprt_clear_connecting(xprt); | 2115 | xprt_clear_connecting(xprt); |
2094 | xprt_wake_pending_tasks(xprt, status); | 2116 | xprt_wake_pending_tasks(xprt, status); |
2095 | current->flags &= ~PF_FSTRANS; | ||
2096 | } | 2117 | } |
2097 | 2118 | ||
2098 | /* | 2119 | /* |
@@ -2229,8 +2250,6 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2229 | struct rpc_xprt *xprt = &transport->xprt; | 2250 | struct rpc_xprt *xprt = &transport->xprt; |
2230 | int status = -EIO; | 2251 | int status = -EIO; |
2231 | 2252 | ||
2232 | current->flags |= PF_FSTRANS; | ||
2233 | |||
2234 | if (!sock) { | 2253 | if (!sock) { |
2235 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | 2254 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
2236 | sock = xs_create_sock(xprt, transport, | 2255 | sock = xs_create_sock(xprt, transport, |
@@ -2245,7 +2264,9 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2245 | abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, | 2264 | abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, |
2246 | &xprt->state); | 2265 | &xprt->state); |
2247 | /* "close" the socket, preserving the local port */ | 2266 | /* "close" the socket, preserving the local port */ |
2267 | set_bit(XPRT_CONNECTION_REUSE, &xprt->state); | ||
2248 | xs_tcp_reuse_connection(transport); | 2268 | xs_tcp_reuse_connection(transport); |
2269 | clear_bit(XPRT_CONNECTION_REUSE, &xprt->state); | ||
2249 | 2270 | ||
2250 | if (abort_and_exit) | 2271 | if (abort_and_exit) |
2251 | goto out_eagain; | 2272 | goto out_eagain; |
@@ -2276,7 +2297,6 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2276 | case -EINPROGRESS: | 2297 | case -EINPROGRESS: |
2277 | case -EALREADY: | 2298 | case -EALREADY: |
2278 | xprt_clear_connecting(xprt); | 2299 | xprt_clear_connecting(xprt); |
2279 | current->flags &= ~PF_FSTRANS; | ||
2280 | return; | 2300 | return; |
2281 | case -EINVAL: | 2301 | case -EINVAL: |
2282 | /* Happens, for instance, if the user specified a link | 2302 | /* Happens, for instance, if the user specified a link |
@@ -2294,7 +2314,6 @@ out_eagain: | |||
2294 | out: | 2314 | out: |
2295 | xprt_clear_connecting(xprt); | 2315 | xprt_clear_connecting(xprt); |
2296 | xprt_wake_pending_tasks(xprt, status); | 2316 | xprt_wake_pending_tasks(xprt, status); |
2297 | current->flags &= ~PF_FSTRANS; | ||
2298 | } | 2317 | } |
2299 | 2318 | ||
2300 | /** | 2319 | /** |