* amq/pawd.c (find_mt, find_mlp): remove obsolete, inefficient
authorErez Zadok <ezk@cs.sunysb.edu>
Fri, 7 Oct 2005 16:39:12 +0000 (16:39 +0000)
committerErez Zadok <ezk@cs.sunysb.edu>
Fri, 7 Oct 2005 16:39:12 +0000 (16:39 +0000)
code.
(transform_dir): call the new, efficient amqproc_pawd_1() routine.

* amq/amq_clnt.c (amqproc_pawd_1): AMQPROC_PAWD wrapper routine.

* amq/amq.h (amqproc_pawd_1): extern for amq's AMQPROC_PAWD
wrapper routine.

* amd/amq_svc.c (amq_program_1): dispatch point for
amqproc_pawd_1_svc.

* amd/amq_subr.c (amqproc_pawd_1_svc): moved pawd's path-matching
functionality into Amd, where it can be done a lot more
efficiently.  We don't have to construct and ship a whole export
tree from Amd to pawd.  We just get a variable-length
xdr_wrapstring for the user's path, iterate over the entire export
list inside Amd, and return only a matched string if found
(otherwise we return "" to indicate that there was no match, and
let pawd printf the same string it sent over).

* amd/amd.h: extern for amqproc_pawd_1_svc, amd's service routine
the AMQPROC_PAWD RPC.

* amq/pawd.c (transform_dir): was using UDP only.  Now will also
try TCP if UDP failed.  Destroy client after use to avoid leftover
TCP sockets in the kernel.

ChangeLog
NEWS
amd/amd.h
amd/amq_subr.c
amd/amq_svc.c
amd/nfs_start.c
amq/amq.h
amq/amq_clnt.c
amq/pawd.c
include/amq_defs.h

index 67ab92be1e86a45ac5cd20de9a5b1b47f72adb33..f6ed1815682d43e3f4d10784d4c8482cf033ea44 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2005-10-07  Erez Zadok  <ezk@cs.sunysb.edu>
+
+       * amq/pawd.c (find_mt, find_mlp): remove obsolete, inefficient
+       code.
+       (transform_dir): call the new, efficient amqproc_pawd_1() routine.
+
+       * amq/amq_clnt.c (amqproc_pawd_1): AMQPROC_PAWD wrapper routine.
+
+       * amq/amq.h (amqproc_pawd_1): extern for amq's AMQPROC_PAWD
+       wrapper routine.
+
+       * amd/amq_svc.c (amq_program_1): dispatch point for
+       amqproc_pawd_1_svc.
+
+       * amd/amq_subr.c (amqproc_pawd_1_svc): moved pawd's path-matching
+       functionality into Amd, where it can be done a lot more
+       efficiently.  We don't have to construct and ship a whole export
+       tree from Amd to pawd.  We just get a variable-length
+       xdr_wrapstring for the user's path, iterate over the entire export
+       list inside Amd, and return only a matched string if found
+       (otherwise we return "" to indicate that there was no match, and
+       let pawd printf the same string it sent over).
+
+       * amd/amd.h: extern for amqproc_pawd_1_svc, amd's service routine
+       the AMQPROC_PAWD RPC.
+
 2005-10-06  Erez Zadok  <ezk@cs.sunysb.edu>
 
        * ltmain.sh, m4/macros/libtool.m4: update to libtool-1.5.20.
@@ -63,8 +89,9 @@
 
 2005-10-05  Erez Zadok  <ezk@cs.sunysb.edu>
 
-       * amq/pawd.c (transform_dir): use TCP first, else UDP.  Destroy
-       client after use to avoid leftover TCP sockets in the kernel.
+       * amq/pawd.c (transform_dir): was using UDP only.  Now will also
+       try TCP if UDP failed.  Destroy client after use to avoid leftover
+       TCP sockets in the kernel.
 
        * libamu/hasmntopt.c (amu_hasmntopt): increase size of MNTMAXSTR
        from 128 to to 256, because some users have really long option
diff --git a/NEWS b/NEWS
index 2f06d919025f1c63db474d1504b7e7f3d7bed0fe..8c6b7711ea34407e8e7f30b0089ac04a605da164 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -52,7 +52,8 @@ XXX: Dan, document sun_map_syntax flag in more detail in am-utils.texi and
        * convert all sprintf to safer xsnprintf
        * convert all strcat to safer xstrlcat
        * convert all strcpy to safer xstrlcpy
-       * pawd uses TCP first, then UDP
+       * fix three buffer overruns in expand_op (amd/opts.c)
+       * pawd was trying UDP only, now try TCP if UDP failed
 
 Amd now understands a new log_option called "defaults" which is synonymous
 with "fatal,error,user,warning,info" (and is also what logging happens by
@@ -61,6 +62,12 @@ default).
 Amd now understands a new debug_option called "defaults" which is synonymous
 with "all,nohrtime,nomtab,noxdrtrace".
 
+Moved pawd's path-matching functionality into Amd, where it can be done a
+lot more efficiently (we no longer need to construct and send the whole
+mounted tree, only to match small parts of it).  This will lessen the CPU
+and network load on systems that use pawd heavily, and also minimize the
+chance that we exceed default or hard-coded UDP/TCP RPC packet sizes.
+
 Changed slightly how Amd behaves when you try to change log_options after
 Amd started (options can be turned on/off via "amq -x ARG").  It used to be
 that Amd won't let you turn off options which were on when Amd started.
index e0eaef50ffd7a88bd9bc30ba02f4a4473eb82df2..1224a087c566451d21235ad3278e3c851e654ab3 100644 (file)
--- a/amd/amd.h
+++ b/amd/amd.h
@@ -515,6 +515,7 @@ extern amq_mount_stats *amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp);
 extern amq_mount_tree_list *amqproc_export_1_svc(voidp argp, struct svc_req *rqstp);
 extern amq_mount_tree_p *amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp);
 extern amq_string *amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp);
+extern amq_string *amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp);
 extern int *amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp);
 extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp);
 extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp);
index a6d245db6bafc8e9a8a51d6684edaf7829ed158f..861550876fef0ff48e0a322ebd20a5b3338db759 100644 (file)
@@ -192,6 +192,43 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
 }
 
 
+/* process PAWD string of remote pawd tool */
+amq_string *
+amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
+{
+  static amq_string res;
+  int index, len;
+  am_node *mp;
+  char *mountpoint;
+  char *dir = *(char **) argp;
+  static char tmp_buf[MAXPATHLEN];
+
+  tmp_buf[0] = '\0';           /* default is empty string: no match */
+  for (mp = get_first_exported_ap(&index);
+       mp;
+       mp = get_next_exported_ap(&index)) {
+    if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
+      continue;
+    if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
+      continue;
+    mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
+    len = strlen(mountpoint);
+    if (len == 0)
+      continue;
+    if (!NSTREQ(mountpoint, dir, len))
+      continue;
+    if (dir[len] != '\0' && dir[len] != '/')
+      continue;
+    xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf));
+    xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
+    break;
+  }
+
+  res = tmp_buf;
+  return &res;
+}
+
+
 /*
  * XDR routines.
  */
index cc8cc7f08108538576996528e1fc80c14fdfd689..b127be6c1876bf4b7f5b9da975caf33e803ceaf1 100644 (file)
@@ -193,6 +193,12 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
     local = (amqsvcproc_t) amqproc_getpid_1_svc;
     break;
 
+  case AMQPROC_PAWD:
+    xdr_argument = (xdrproc_t) xdr_amq_string;
+    xdr_result = (xdrproc_t) xdr_amq_string;
+    local = (amqsvcproc_t) amqproc_pawd_1_svc;
+    break;
+
   default:
     svcerr_noproc(transp);
     return;
index 17303bccbb4f59a79f9618b85926f8dc24d4ca57..76e794f7f4b7913730d1344e9103a4212f8682c7 100644 (file)
@@ -234,7 +234,7 @@ run_rpc(void)
     }
     tvv.tv_usec = 0;
 
-    if (amd_state == Finishing && get_exported_ap(0) == 0) {
+    if (amd_state == Finishing && get_exported_ap(0) == NULL) {
       flush_mntfs();
       amd_state = Quit;
       break;
index e2d693531938a0041e267ca444fa57d1ffe749a1..9d40e7e75f839543338870c4f07c4d4edcc67146 100644 (file)
--- a/amq/amq.h
+++ b/amq/amq.h
@@ -58,5 +58,6 @@ extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
 extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
 extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
 extern int *amqproc_getpid_1(voidp argp, CLIENT *rqstp);
+extern amq_string *amqproc_pawd_1(amq_string *argp, CLIENT *rqstp);
 
 #endif /* not _AMQ_H */
index fa4c503736a7bc140ae671d5595bd5150a6a666f..2c377b717b7be59fd3b40d83b91ef4f82bd2bebf 100644 (file)
@@ -75,7 +75,7 @@ amqproc_mnttree_1(amq_string *argp, CLIENT *clnt)
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_MNTTREE,
                (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
-               (XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (SVC_IN_ARG_TYPE) & res,
+               (XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (SVC_IN_ARG_TYPE) &res,
                TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -108,7 +108,7 @@ amqproc_stats_1(voidp argp, CLIENT *clnt)
   if (clnt_call(clnt, AMQPROC_STATS,
                (XDRPROC_T_TYPE) xdr_void, argp,
                (XDRPROC_T_TYPE) xdr_amq_mount_stats,
-               (SVC_IN_ARG_TYPE) & res,
+               (SVC_IN_ARG_TYPE) &res,
                TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -125,7 +125,7 @@ amqproc_export_1(voidp argp, CLIENT *clnt)
   if (clnt_call(clnt, AMQPROC_EXPORT,
                (XDRPROC_T_TYPE) xdr_void, argp,
                (XDRPROC_T_TYPE) xdr_amq_mount_tree_list,
-               (SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+               (SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
   return (&res);
@@ -140,7 +140,7 @@ amqproc_setopt_1(amq_setopt *argp, CLIENT *clnt)
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_SETOPT, (XDRPROC_T_TYPE) xdr_amq_setopt,
                (SVC_IN_ARG_TYPE) argp, (XDRPROC_T_TYPE) xdr_int,
-               (SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+               (SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
   return (&res);
@@ -155,7 +155,7 @@ amqproc_getmntfs_1(voidp argp, CLIENT *clnt)
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_GETMNTFS, (XDRPROC_T_TYPE) xdr_void, argp,
                (XDRPROC_T_TYPE) xdr_amq_mount_info_list,
-               (SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+               (SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
   return (&res);
@@ -169,7 +169,7 @@ amqproc_mount_1(voidp argp, CLIENT *clnt)
 
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_MOUNT, (XDRPROC_T_TYPE) xdr_amq_string, argp,
-               (XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
+               (XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) &res,
                TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -184,7 +184,7 @@ amqproc_getvers_1(voidp argp, CLIENT *clnt)
 
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_GETVERS, (XDRPROC_T_TYPE) xdr_void, argp,
-               (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) & res,
+               (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) &res,
                TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -199,7 +199,23 @@ amqproc_getpid_1(voidp argp, CLIENT *clnt)
 
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_GETPID, (XDRPROC_T_TYPE) xdr_void, argp,
-               (XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
+               (XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) &res,
+               TIMEOUT) != RPC_SUCCESS) {
+    return (NULL);
+  }
+  return (&res);
+}
+
+
+amq_string *
+amqproc_pawd_1(amq_string *argp, CLIENT *clnt)
+{
+  static amq_string res;
+
+  memset((char *) &res, 0, sizeof(res));
+  if (clnt_call(clnt, AMQPROC_PAWD,
+               (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
+               (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) &res,
                TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
index 44aca1c39f50b3d7c7c5420c471d66639d616fbf..bf06cf684c470746240ef8ec54c0dc52746d0b56 100644 (file)
 #include <amq.h>
 
 /* statics */
-static char *localhost="localhost";
-static char newdir[MAXPATHLEN];
+static char *localhost = "localhost";
 static char transform[MAXPATHLEN];
 
-static int
-find_mt(amq_mount_tree *mt, char *dir)
-{
-  while (mt) {
-    if (!STREQ(mt->mt_type, "toplvl") && !STREQ(mt->mt_type, "auto")) {
-      int len = strlen(mt->mt_mountpoint);
-      if (len != 0 && NSTREQ(mt->mt_mountpoint, dir, len) &&
-         ((dir[len] == '\0') || (dir[len] == '/'))) {
-       char tmp_buf[MAXPATHLEN];
-       xstrlcpy(tmp_buf, mt->mt_directory, sizeof(tmp_buf));
-       xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
-       xstrlcpy(newdir, tmp_buf, sizeof(newdir));
-       return 1;
-      }
-    }
-    if (find_mt(mt->mt_next,dir))
-      return 1;
-    mt = mt->mt_child;
-  }
-  return 0;
-}
-
-
-static int
-find_mlp(amq_mount_tree_list *mlp, char *dir)
-{
-  u_int i;
-
-  for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
-    if (find_mt(mlp->amq_mount_tree_list_val[i], dir))
-      return 1;
-  }
-  return 0;
-}
-
 
 #ifdef HAVE_CNODEID
 static char *
@@ -215,8 +179,9 @@ transform_dir(char *dir)
   int s = RPC_ANYSOCK;
   CLIENT *clnt;
   struct hostent *hp;
-  amq_mount_tree_list *mlp;
   struct timeval tmo = {10, 0};
+  char *dummystr;
+  amq_string *spp;
 
 #ifdef DISK_HOME_HACK
   if (ch = hack_name(dir))
@@ -235,16 +200,18 @@ transform_dir(char *dir)
   server_addr.sin_family = AF_INET;
   server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
 
-  clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
+  clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
   if (clnt == NULL)
-    clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
+    clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
   if (clnt == NULL)
     return dir;
 
   xstrlcpy(transform, dir, sizeof(transform));
-  while ( (mlp = amqproc_export_1((voidp)0, clnt)) &&
-         find_mlp(mlp,transform) ) {
-    xstrlcpy(transform, newdir, sizeof(transform));
+  dummystr = transform;
+  spp = amqproc_pawd_1((amq_string *) &dummystr, clnt);
+  if (spp && *spp && **spp) {
+    xstrlcpy(transform, *spp, sizeof(transform));
+    XFREE(*spp);
   }
   clnt_destroy(clnt);
   return transform;
index 90c4d9b2d077a660ae4fd26962e8a0adbdb6476f..3c3e163a8e864f6a3b8fec38e084d5a4964a7ecd 100644 (file)
@@ -63,6 +63,7 @@
 #define AMQPROC_MOUNT ((u_long)7)
 #define AMQPROC_GETVERS ((u_long)8)
 #define AMQPROC_GETPID ((u_long)9)
+#define AMQPROC_PAWD ((u_long)10)
 
 /*
  * TYPEDEFS