]> git.pld-linux.org Git - packages/nfs-utils.git/commitdiff
- rel 3 auto/th/nfs-utils-1_2_3-3
authorJan Rękorajski <baggins@pld-linux.org>
Mon, 4 Oct 2010 12:02:22 +0000 (12:02 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
- fix for https://bugzilla.linux-nfs.org/show_bug.cgi?id=190
  (-p <port> option broken in mountd)

Changed files:
    nfs-utils.spec -> 1.197
    svc-create-fixed-port.patch -> 1.1

nfs-utils.spec
svc-create-fixed-port.patch [new file with mode: 0644]

index 5e99b0992a4a44d8ffb38abb4afa7fabedbd3222..f6e6539a2c6f98d69f7e65e6f560d480ef65bc4c 100644 (file)
@@ -13,7 +13,7 @@ Summary(ru.UTF-8):    Утилиты для NFS и демоны поддержки
 Summary(uk.UTF-8):     Утиліти для NFS та демони підтримки для NFS-сервера ядра
 Name:          nfs-utils
 Version:       1.2.3
-Release:       2
+Release:       3
 License:       GPL v2
 Group:         Networking/Daemons
 Source0:       http://www.kernel.org/pub/linux/utils/nfs/%{name}-%{version}.tar.bz2
@@ -35,6 +35,7 @@ Patch1:               %{name}-statdpath.patch
 Patch2:                %{name}-subsys.patch
 Patch3:                %{name}-union-mount.patch
 Patch4:                %{name}-heimdal.patch
+Patch5:                svc-create-fixed-port.patch
 URL:           http://nfs.sourceforge.net/
 BuildRequires: autoconf >= 2.59
 BuildRequires: automake
@@ -170,6 +171,7 @@ Wspólne programy do obsługi NFS.
 %patch2 -p1
 %patch3 -p1
 %patch4 -p1
+%patch5 -p1
 
 %build
 %{__libtoolize}
diff --git a/svc-create-fixed-port.patch b/svc-create-fixed-port.patch
new file mode 100644 (file)
index 0000000..2c197e5
--- /dev/null
@@ -0,0 +1,323 @@
+commit 0e94118815e8ff9c1142117764ee3e6cddba0395
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Fri Oct 1 15:04:20 2010 -0400
+
+    libnfs.a: Allow multiple RPC listeners to share listener port number
+    
+    Normally, when "-p" is not specified on the mountd command line, the
+    TI-RPC library chooses random port numbers for each listener.  If a
+    port number _is_ specified on the command line, all the listeners
+    will get the same port number, so SO_REUSEADDR needs to be set on
+    each socket.
+    
+    Thus we can't let TI-RPC create the listener sockets for us in this
+    case; we must create them ourselves and then set SO_REUSEADDR (and
+    other socket options) by hand.
+    
+    Different versions of the same RPC program have to share the same
+    listener and SVCXPRT, so we have to cache xprts we create, and re-use
+    them when additional requests for registration come from the
+    application.
+    
+    Though it doesn't look like it, this fix was "copied" from the legacy
+    rpc_init() function.  It's more complicated for TI-RPC, of course,
+    since you can have an arbitrary number of listeners, not just two
+    (one for AF_INET UDP and one for AF_INET TCP).
+    
+    Fix for:
+    
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=190
+    
+    There have been no reports of problems with specifying statd's
+    listener port, but I expect this is a problem for statd too.
+    
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+
+diff --git a/support/nfs/svc_create.c b/support/nfs/svc_create.c
+index 59ba505..fdc4846 100644
+--- a/support/nfs/svc_create.c
++++ b/support/nfs/svc_create.c
+@@ -27,6 +27,7 @@
+ #include <memory.h>
+ #include <signal.h>
+ #include <unistd.h>
++#include <errno.h>
+ #include <netdb.h>
+ #include <netinet/in.h>
+@@ -41,11 +42,68 @@
+ #include "tcpwrapper.h"
+ #endif
++#include "sockaddr.h"
+ #include "rpcmisc.h"
+ #include "xlog.h"
+ #ifdef HAVE_LIBTIRPC
++#define SVC_CREATE_XPRT_CACHE_SIZE    (8)
++static SVCXPRT *svc_create_xprt_cache[SVC_CREATE_XPRT_CACHE_SIZE] = { NULL, };
++
++/*
++ * Cache an SVC xprt, in case there are more programs or versions to
++ * register against it.
++ */
++static void
++svc_create_cache_xprt(SVCXPRT *xprt)
++{
++      unsigned int i;
++
++      /* Check if we've already got this one... */
++      for (i = 0; i < SVC_CREATE_XPRT_CACHE_SIZE; i++)
++              if (svc_create_xprt_cache[i] == xprt)
++                      return;
++
++      /* No, we don't.  Cache it. */
++      for (i = 0; i < SVC_CREATE_XPRT_CACHE_SIZE; i++)
++              if (svc_create_xprt_cache[i] == NULL) {
++                      svc_create_xprt_cache[i] = xprt;
++                      return;
++              }
++
++      xlog(L_ERROR, "%s: Failed to cache an xprt", __func__);
++}
++
++/*
++ * Find a previously cached SVC xprt structure with the given bind address
++ * and transport semantics.
++ *
++ * Returns pointer to a SVC xprt.
++ *
++ * If no matching SVC XPRT can be found, NULL is returned.
++ */
++static SVCXPRT *
++svc_create_find_xprt(const struct sockaddr *bindaddr, const struct netconfig *nconf)
++{
++      unsigned int i;
++
++      for (i = 0; i < SVC_CREATE_XPRT_CACHE_SIZE; i++) {
++              SVCXPRT *xprt = svc_create_xprt_cache[i];
++              struct sockaddr *sap;
++
++              if (xprt == NULL)
++                      continue;
++              if (strcmp(nconf->nc_netid, xprt->xp_netid) != 0)
++                      continue;
++              sap = (struct sockaddr *)xprt->xp_ltaddr.buf;
++              if (!nfs_compare_sockaddr(bindaddr, sap))
++                      continue;
++              return xprt;
++      }
++      return NULL;
++}
++
+ /*
+  * Set up an appropriate bind address, given @port and @nconf.
+  *
+@@ -98,17 +156,112 @@ svc_create_bindaddr(struct netconfig *nconf, const uint16_t port)
+       return ai;
+ }
++/*
++ * Create a listener socket on a specific bindaddr, and set
++ * special socket options to allow it to share the same port
++ * as other listeners.
++ *
++ * Returns an open, bound, and possibly listening network
++ * socket on success.
++ *
++ * Otherwise returns -1 if some error occurs.
++ */
++static int
++svc_create_sock(const struct sockaddr *sap, socklen_t salen,
++              struct netconfig *nconf)
++{
++      int fd, type, protocol;
++      int one = 1;
++
++      switch(nconf->nc_semantics) {
++      case NC_TPI_CLTS:
++              type = SOCK_DGRAM;
++              break;
++      case NC_TPI_COTS_ORD:
++              type = SOCK_STREAM;
++              break;
++      default:
++              xlog(D_GENERAL, "%s: Unrecognized bind address semantics: %u",
++                      __func__, nconf->nc_semantics);
++              return -1;
++      }
++
++      if (strcmp(nconf->nc_proto, NC_UDP) == 0)
++              protocol = (int)IPPROTO_UDP;
++      else if (strcmp(nconf->nc_proto, NC_TCP) == 0)
++              protocol = (int)IPPROTO_TCP;
++      else {
++              xlog(D_GENERAL, "%s: Unrecognized bind address protocol: %s",
++                      __func__, nconf->nc_proto);
++              return -1;
++      }
++
++      fd = socket((int)sap->sa_family, type, protocol);
++      if (fd == -1) {
++              xlog(L_ERROR, "Could not make a socket: (%d) %m",
++                      errno);
++              return -1;
++      }
++
++#ifdef IPV6_SUPPORTED
++      if (sap->sa_family == AF_INET6) {
++              if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
++                              &one, sizeof(one)) == -1) {
++                      xlog(L_ERROR, "Failed to set IPV6_V6ONLY: (%d) %m",
++                              errno);
++                      (void)close(fd);
++                      return -1;
++              }
++      }
++#endif        /* IPV6_SUPPORTED */
++
++      if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
++                     &one, sizeof(one)) == -1) {
++              xlog(L_ERROR, "Failed to set SO_REUSEADDR: (%d) %m",
++                      errno);
++              (void)close(fd);
++              return -1;
++      }
++
++      if (bind(fd, sap, salen) == -1) {
++              xlog(L_ERROR, "Could not bind socket: (%d) %m",
++                      errno);
++              (void)close(fd);
++              return -1;
++      }
++
++      if (nconf->nc_semantics == NC_TPI_COTS_ORD)
++              if (listen(fd, SOMAXCONN) == -1) {
++                      xlog(L_ERROR, "Could not listen on socket: (%d) %m",
++                              errno);
++                      (void)close(fd);
++                      return -1;
++              }
++
++      return fd;
++}
++
++/*
++ * The simple case is allowing the TI-RPC library to create a
++ * transport itself, given just the bind address and transport
++ * semantics.
++ *
++ * The port is chosen at random by the library; we don't know
++ * what it is.  So the new xprt cannot be cached here.
++ *
++ * Returns the count of started listeners (one or zero).
++ */
+ static unsigned int
+-svc_create_nconf(const char *name, const rpcprog_t program,
++svc_create_nconf_rand_port(const char *name, const rpcprog_t program,
+               const rpcvers_t version,
+               void (*dispatch)(struct svc_req *, SVCXPRT *),
+-              const uint16_t port, struct netconfig *nconf)
++              struct netconfig *nconf)
+ {
+       struct t_bind bindaddr;
+       struct addrinfo *ai;
+       SVCXPRT *xprt;
+-      ai = svc_create_bindaddr(nconf, port);
++      ai = svc_create_bindaddr(nconf, 0);
+       if (ai == NULL)
+               return 0;
+@@ -119,7 +272,7 @@ svc_create_nconf(const char *name, const rpcprog_t program,
+       freeaddrinfo(ai);
+       if (xprt == NULL) {
+               xlog(D_GENERAL, "Failed to create listener xprt "
+-                              "(%s, %u, %s)", name, version, nconf->nc_netid);
++                      "(%s, %u, %s)", name, version, nconf->nc_netid);
+               return 0;
+       }
+@@ -133,6 +286,81 @@ svc_create_nconf(const char *name, const rpcprog_t program,
+       return 1;
+ }
++/*
++ * If a port is specified on the command line, that port value will be
++ * the same for all listeners created here.  Create each listener socket
++ * in advance and set SO_REUSEADDR, rather than allowing the RPC library
++ * to create the listeners for us on a randomly chosen port (RPC_ANYFD).
++ *
++ * Also, to support multiple RPC versions on the same listener, register
++ * any new versions on the same transport that is already handling other
++ * versions on the same bindaddr and transport.  To accomplish this,
++ * cache previously created xprts on a list, and check that list before
++ * creating a new socket for this [program, version].
++ *
++ * Returns the count of started listeners (one or zero).
++ */
++static unsigned int
++svc_create_nconf_fixed_port(const char *name, const rpcprog_t program,
++              const rpcvers_t version,
++              void (*dispatch)(struct svc_req *, SVCXPRT *),
++              const uint16_t port, struct netconfig *nconf)
++{
++      struct addrinfo *ai;
++      SVCXPRT *xprt;
++
++      ai = svc_create_bindaddr(nconf, port);
++      if (ai == NULL)
++              return 0;
++
++      xprt = svc_create_find_xprt(ai->ai_addr, nconf);
++      if (xprt == NULL) {
++              int fd;
++
++              fd = svc_create_sock(ai->ai_addr, ai->ai_addrlen, nconf);
++              if (fd == -1)
++                      goto out_free;
++
++              xprt = svc_tli_create(fd, nconf, NULL, 0, 0);
++              if (xprt == NULL) {
++                      xlog(D_GENERAL, "Failed to create listener xprt "
++                              "(%s, %u, %s)", name, version, nconf->nc_netid);
++                      (void)close(fd);
++                      goto out_free;
++              }
++      }
++
++      if (!svc_reg(xprt, program, version, dispatch, nconf)) {
++              /* svc_reg(3) destroys @xprt in this case */
++              xlog(D_GENERAL, "Failed to register (%s, %u, %s)",
++                              name, version, nconf->nc_netid);
++              goto out_free;
++      }
++
++      svc_create_cache_xprt(xprt);
++
++      freeaddrinfo(ai);
++      return 1;
++
++out_free:
++      freeaddrinfo(ai);
++      return 0;
++}
++
++static unsigned int
++svc_create_nconf(const char *name, const rpcprog_t program,
++              const rpcvers_t version,
++              void (*dispatch)(struct svc_req *, SVCXPRT *),
++              const uint16_t port, struct netconfig *nconf)
++{
++      if (port != 0)
++              return svc_create_nconf_fixed_port(name, program,
++                      version, dispatch, port, nconf);
++
++      return svc_create_nconf_rand_port(name, program,
++                      version, dispatch, nconf);
++}
++
+ /**
+  * nfs_svc_create - start up RPC svc listeners
+  * @name: C string containing name of new service
This page took 0.048217 seconds and 4 git commands to generate.