The nfs_quick_reply() functionality relies on taking a copy of the
authorzoulasc <christos@zoulas.com>
Thu, 3 Mar 2016 18:21:13 +0000 (13:21 -0500)
committerzoulasc <christos@zoulas.com>
Thu, 3 Mar 2016 18:21:13 +0000 (13:21 -0500)
current transport for later use.

The problem with this is the context of the RPC message is kept in
the transport and if any RPC message arrives before nfs_quick_reply()
is called that context will be corrupted.

So add a function get_nfs_xprt() to replace the current transport
with a new one returning the passed in transort so nfs_quick_reply()
can use it later.

A function put_nfs_xprt() is also added (although not really needed
since it just destroys the now unused transport) for completeness.

From: Ian Kent

conf/transp/transp_sockets.c
conf/transp/transp_tli.c
include/am_utils.h

index 63260071ed9f96707b7b8b3930fb0f984d47c16c..98f79c8d21aa0c2ecad6868a56c331188653b38c 100644 (file)
@@ -45,6 +45,7 @@
 #include <am_defs.h>
 #include <amu.h>
 
+static int soNFS = RPC_ANYSOCK;
 
 /*
  * find the IP address that can be used to connect to the local host
@@ -273,9 +274,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
     return 3;
   }
 
+  soNFS = *soNFSp;
+
   return 0;                    /* all is well */
 }
 
+/*
+ * Get a pointer to the current NFS SVCXPRT and replace it
+ * with a new one.
+ */
+SVCXPRT *
+get_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+  SVCXPRT *newxprt;
+  int newfd;
+
+  if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+    return NULL;
+
+  newfd = dup(soNFS);
+  if (newfd < 0)
+    return NULL;
+
+  xprt_unregister(nfs_xprt);
+  newxprt = svcudp_create(newfd);
+  if (!newxprt) {
+    plog(XLOG_FATAL, "Can't swicth to new transpot");
+    xprt_register(nfs_xprt);
+    close(newfd);
+    return NULL;
+  }
+
+  soNFS = newfd;
+
+  return nfs_xprt;
+}
+
+/*
+ * Destroy a transport previously obtained by get_nfs_xprt().
+ */
+void put_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+  if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+    return;
+
+  svc_destroy(nfs_xprt);
+}
 
 /*
  * Create the amq service for amd (both TCP and UDP)
index d26a511bfe40621735f0b36d722d765582de2c78..ea565cce81437c3dab69e3f903b89dacedb66e63 100644 (file)
@@ -45,7 +45,8 @@
 #include <am_defs.h>
 #include <amu.h>
 
-struct netconfig *nfsncp;
+struct netconfig *nfsncp = NULL;
+static int soNFS = RPC_ANYSOCK;
 
 
 /*
@@ -456,9 +457,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
     return 1;
   }
 
+  soNFS = *soNFSp;
+
   return 0;                    /* all is well */
 }
 
+/*
+ * Get a pointer to the current NFS SVCXPRT and replace it
+ * with a new one.
+ */
+SVCXPRT *
+get_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+  SVCXPRT *newxprt;
+  int newfd;
+
+  if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+    return NULL;
+
+  newfd = dup(soNFS);
+  if (newfd < 0)
+    return NULL;
+
+  xprt_unregister(nfs_xprt);
+  newxprt = svc_tli_create(newfd, nfsncp, NULL, 0, 0);
+  if (!newxprt) {
+    plog(XLOG_FATAL, "Can't swicth to new transpot");
+    xprt_register(nfs_xprt);
+    close(newfd);
+    return NULL;
+  }
+
+  soNFS = newfd;
+
+  return nfs_xprt;
+}
+
+/*
+ * Destroy a transport previously obtained by get_nfs_xprt().
+ */
+void put_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+  if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+    return;
+
+  svc_destroy(nfs_xprt);
+}
 
 /*
  * Bind to preferred AMQ port.
index 0de881ad8c8529c01f5933886ec24ad5d2393d82..ff13c26648c05f309d7291d9fd9bd3b712ac96dd 100644 (file)
@@ -378,6 +378,8 @@ extern void compute_nfs_args(void *nap, mntent_t *mntp, int genflags, struct net
 extern void destroy_nfs_args(void *nap, u_long nfs_version);
 extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port);
 extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version);
+extern SVCXPRT *get_nfs_xprt(SVCXPRT *nfs_xprt);
+extern void put_nfs_xprt(SVCXPRT *nfs_xprt);
 extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *);
 
 #ifdef HAVE_TRANSPORT_TYPE_TLI