Author: baggins                      Date: Mon Oct  4 12:02:30 2010 GMT
Module: packages                      Tag: HEAD
---- Log message:
- rel 3
- fix for https://bugzilla.linux-nfs.org/show_bug.cgi?id=190
  (-p <port> option broken in mountd)

---- Files affected:
packages/nfs-utils:
   nfs-utils.spec (1.196 -> 1.197) , svc-create-fixed-port.patch (NONE -> 1.1)  
(NEW)

---- Diffs:

================================================================
Index: packages/nfs-utils/nfs-utils.spec
diff -u packages/nfs-utils/nfs-utils.spec:1.196 
packages/nfs-utils/nfs-utils.spec:1.197
--- packages/nfs-utils/nfs-utils.spec:1.196     Sun Oct  3 20:33:52 2010
+++ packages/nfs-utils/nfs-utils.spec   Mon Oct  4 14:02:22 2010
@@ -14,7 +14,7 @@
 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
@@ -36,6 +36,7 @@
 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
@@ -171,6 +172,7 @@
 %patch2 -p1
 %patch3 -p1
 %patch4 -p1
+%patch5 -p1
 
 %build
 %{__libtoolize}
@@ -414,6 +416,11 @@
 All persons listed below can be reached at <cvs_login>@pld-linux.org
 
 $Log$
+Revision 1.197  2010/10/04 12:02:22  baggins
+- rel 3
+- fix for https://bugzilla.linux-nfs.org/show_bug.cgi?id=190
+  (-p <port> option broken in mountd)
+
 Revision 1.196  2010/10/03 18:33:52  baggins
 - cosmetics
 

================================================================
Index: packages/nfs-utils/svc-create-fixed-port.patch
diff -u /dev/null packages/nfs-utils/svc-create-fixed-port.patch:1.1
--- /dev/null   Mon Oct  4 14:02:30 2010
+++ packages/nfs-utils/svc-create-fixed-port.patch      Mon Oct  4 14:02:22 2010
@@ -0,0 +1,323 @@
+commit 0e94118815e8ff9c1142117764ee3e6cddba0395
+Author: Chuck Lever <[email protected]>
+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 <[email protected]>
+
+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
================================================================

---- CVS-web:
    
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/packages/nfs-utils/nfs-utils.spec?r1=1.196&r2=1.197&f=u

_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to