From: Steve Dickson <SteveD@redhat.com>
To: Chris Perl <chris.perl@gmail.com>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [PATCH] nfs-utils: nfs_get_tcpclient/nfs_get_udpclient - make bind(2) implicit
Date: Tue, 16 Sep 2014 09:30:55 -0400 [thread overview]
Message-ID: <54183B8F.3080301@RedHat.com> (raw)
In-Reply-To: <1410547762-27285-1-git-send-email-chris.perl@gmail.com>
On 09/12/2014 02:49 PM, Chris Perl wrote:
> When attempting to establish a local ephemeral endpoint for a TCP or UDP
> socket, do not explicitly call bind(2), instead let it happen implicilty when
> the socket is first used.
>
> The main motivating factor for this change is when TCP runs out of unique
> ephemeral ports (i.e. cannot find any ephemeral ports which are not a part of
> *any* TCP connection). In this situation if you explicitly call bind(2), then
> the call will fail with EADDRINUSE. However, if you allow the allocation of an
> ephemeral port to happen implicitly as part of connect(2) (or other functions),
> then ephemeral ports can be reused, so long as the combination of (local_ip,
> local_port, remote_ip, remote_port) is unique for TCP sockets on the system.
>
> This doesn't matter for UDP sockets, but it seemed easiest to treat TCP and UDP
> sockets the same.
>
> This can allow mount.nfs(8) to continue to function successfully, even in the
> face of misbehaving applications which are creating a large number of TCP
> connections.
>
> Signed-off-by: Chris Perl <chris.perl@gmail.com>
Committed...
steved.
> ---
> support/nfs/rpc_socket.c | 68 ++++++++++++++----------------------------------
> 1 file changed, 20 insertions(+), 48 deletions(-)
>
> diff --git a/support/nfs/rpc_socket.c b/support/nfs/rpc_socket.c
> index 7896cd2..2900d18 100644
> --- a/support/nfs/rpc_socket.c
> +++ b/support/nfs/rpc_socket.c
> @@ -106,36 +106,6 @@ static CLIENT *nfs_get_localclient(const struct sockaddr *sap,
> return client;
> }
>
> -/*
> - * Bind a socket using an unused ephemeral source port.
> - *
> - * Returns zero on success, or returns -1 on error. errno is
> - * set to reflect the nature of the error.
> - */
> -static int nfs_bind(const int sock, const sa_family_t family)
> -{
> - struct sockaddr_in sin = {
> - .sin_family = AF_INET,
> - .sin_addr.s_addr = htonl(INADDR_ANY),
> - };
> - struct sockaddr_in6 sin6 = {
> - .sin6_family = AF_INET6,
> - .sin6_addr = IN6ADDR_ANY_INIT,
> - };
> -
> - switch (family) {
> - case AF_INET:
> - return bind(sock, (struct sockaddr *)(char *)&sin,
> - (socklen_t)sizeof(sin));
> - case AF_INET6:
> - return bind(sock, (struct sockaddr *)(char *)&sin6,
> - (socklen_t)sizeof(sin6));
> - }
> -
> - errno = EAFNOSUPPORT;
> - return -1;
> -}
> -
> #ifdef HAVE_LIBTIRPC
>
> /*
> @@ -276,7 +246,8 @@ static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
> const int resvport)
> {
> CLIENT *client;
> - int ret, sock;
> + int ret = 0;
> + int sock = 0;
> #ifdef HAVE_LIBTIRPC
> struct sockaddr_storage address;
> const struct netbuf nbuf = {
> @@ -300,15 +271,15 @@ static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
> return NULL;
> }
>
> - if (resvport)
> + if (resvport) {
> ret = nfs_bindresvport(sock, sap->sa_family);
> - else
> - ret = nfs_bind(sock, sap->sa_family);
> - if (ret < 0) {
> - rpc_createerr.cf_stat = RPC_SYSTEMERROR;
> - rpc_createerr.cf_error.re_errno = errno;
> - (void)close(sock);
> - return NULL;
> +
> + if (ret < 0) {
> + rpc_createerr.cf_stat = RPC_SYSTEMERROR;
> + rpc_createerr.cf_error.re_errno = errno;
> + (void)close(sock);
> + return NULL;
> + }
> }
>
> if (timeout->tv_sec == -1)
> @@ -358,7 +329,8 @@ static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
> const int resvport)
> {
> CLIENT *client;
> - int ret, sock;
> + int ret = 0;
> + int sock = 0;
> #ifdef HAVE_LIBTIRPC
> struct sockaddr_storage address;
> const struct netbuf nbuf = {
> @@ -382,15 +354,15 @@ static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
> return NULL;
> }
>
> - if (resvport)
> + if (resvport) {
> ret = nfs_bindresvport(sock, sap->sa_family);
> - else
> - ret = nfs_bind(sock, sap->sa_family);
> - if (ret < 0) {
> - rpc_createerr.cf_stat = RPC_SYSTEMERROR;
> - rpc_createerr.cf_error.re_errno = errno;
> - (void)close(sock);
> - return NULL;
> +
> + if (ret < 0) {
> + rpc_createerr.cf_stat = RPC_SYSTEMERROR;
> + rpc_createerr.cf_error.re_errno = errno;
> + (void)close(sock);
> + return NULL;
> + }
> }
>
> if (timeout->tv_sec == -1)
>
next prev parent reply other threads:[~2014-09-16 13:30 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-12 18:49 [PATCH] nfs-utils: nfs_get_tcpclient/nfs_get_udpclient - make bind(2) implicit Chris Perl
2014-09-16 13:30 ` Steve Dickson [this message]
-- strict thread matches above, loose matches on Subject: below --
2014-09-05 20:17 Chris Perl
2014-09-05 19:40 Chris Perl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54183B8F.3080301@RedHat.com \
--to=steved@redhat.com \
--cc=chris.perl@gmail.com \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).