Ian Kent eb3e266
am-utils-6.2 - add NFSv3 nfs_quick_reply() functionality
Ian Kent eb3e266
Ian Kent eb3e266
From: Ian Kent <raven@themaw.net>
Ian Kent eb3e266
Ian Kent eb3e266
The implementation of the NFS v3 server does not use the hack needed
Ian Kent eb3e266
by the nfs_quick_reply() function.
Ian Kent eb3e266
Ian Kent eb3e266
Now that saving the current transort for later use by nfs_quick_reply()
Ian Kent eb3e266
avoids concurrency races it should be ok to use it.
Ian Kent eb3e266
Ian Kent eb3e266
Signed-off-by: Ian Kent <raven@themaw.net>
Ian Kent eb3e266
---
Ian Kent eb3e266
 amd/nfs_prot_svc.c |   13 +++++
Ian Kent eb3e266
 amd/nfs_subr.c     |  137 +++++++++++++++++++++++++++++++++++++++++-----------
Ian Kent eb3e266
 2 files changed, 120 insertions(+), 30 deletions(-)
Ian Kent eb3e266
Ian Kent eb3e266
diff --git a/amd/nfs_prot_svc.c b/amd/nfs_prot_svc.c
Ian Kent eb3e266
index cbde172..29b7551 100644
Ian Kent eb3e266
--- a/amd/nfs_prot_svc.c
Ian Kent eb3e266
+++ b/amd/nfs_prot_svc.c
Ian Kent eb3e266
@@ -180,7 +180,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
Ian Kent eb3e266
     xdr_result = (xdrproc_t) xdr_diropres;
Ian Kent eb3e266
     local = (nfssvcproc_t) nfsproc_lookup_2_svc;
Ian Kent eb3e266
     /*
Ian Kent eb3e266
-     * Cheap way to pass transp down to amfs_auto_lookuppn so it can
Ian Kent eb3e266
+     * Cheap way to pass transp down to amfs_auto_lookup so it can
Ian Kent eb3e266
      * be stored in the am_node structure and later used for
Ian Kent eb3e266
      * quick_reply().
Ian Kent eb3e266
      */
Ian Kent eb3e266
@@ -327,6 +327,8 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
Ian Kent eb3e266
   xdrproc_t _xdr_argument, _xdr_result;
Ian Kent eb3e266
   nfssvcproc_t local;
Ian Kent eb3e266
 
Ian Kent eb3e266
+  current_transp = NULL;
Ian Kent eb3e266
+
Ian Kent eb3e266
   switch (rqstp->rq_proc) {
Ian Kent eb3e266
   case AM_NFS3_NULL:
Ian Kent eb3e266
     _xdr_argument = (xdrproc_t) xdr_void;
Ian Kent eb3e266
@@ -350,6 +352,12 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
Ian Kent eb3e266
     _xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args;
Ian Kent eb3e266
     _xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
Ian Kent eb3e266
     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc;
Ian Kent eb3e266
+    /*
Ian Kent eb3e266
+     * Cheap way to pass transp down to amfs_auto_lookup so it can
Ian Kent eb3e266
+     * be stored in the am_node structure and later used for
Ian Kent eb3e266
+     * quick_reply().
Ian Kent eb3e266
+     */
Ian Kent eb3e266
+    current_transp = transp;
Ian Kent eb3e266
     break;
Ian Kent eb3e266
 
Ian Kent eb3e266
   case AM_NFS3_ACCESS:
Ian Kent eb3e266
@@ -476,6 +484,9 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
Ian Kent eb3e266
   }
Ian Kent eb3e266
 
Ian Kent eb3e266
   result = (*local) (&argument, rqstp);
Ian Kent eb3e266
+
Ian Kent eb3e266
+  current_transp = NULL;
Ian Kent eb3e266
+
Ian Kent eb3e266
   if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
Ian Kent eb3e266
     svcerr_systemerr (transp);
Ian Kent eb3e266
   }
Ian Kent eb3e266
diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c
Ian Kent eb3e266
index 07d960d..a383618 100644
Ian Kent eb3e266
--- a/amd/nfs_subr.c
Ian Kent eb3e266
+++ b/amd/nfs_subr.c
Ian Kent eb3e266
@@ -87,6 +87,9 @@ struct am_fh3 {
Ian Kent eb3e266
 };
Ian Kent eb3e266
 
Ian Kent eb3e266
 /* forward declarations */
Ian Kent eb3e266
+static int nfs_quick_reply2(am_node *mp, int error);
Ian Kent eb3e266
+static int nfs_quick_reply3(am_node *mp, int error);
Ian Kent eb3e266
+
Ian Kent eb3e266
 /* converting am-filehandles to mount-points */
Ian Kent eb3e266
 static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop);
Ian Kent eb3e266
 static am_node *fh_to_mp(am_nfs_fh *fhp);
Ian Kent eb3e266
@@ -255,46 +258,65 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
Ian Kent eb3e266
   return &res;
Ian Kent eb3e266
 }
Ian Kent eb3e266
 
Ian Kent eb3e266
-
Ian Kent eb3e266
 void
Ian Kent eb3e266
 nfs_quick_reply(am_node *mp, int error)
Ian Kent eb3e266
 {
Ian Kent eb3e266
-  SVCXPRT *transp = mp->am_transp;
Ian Kent eb3e266
-  nfsdiropres res;
Ian Kent eb3e266
-  xdrproc_t xdr_result = (xdrproc_t) xdr_diropres;
Ian Kent eb3e266
+  int ret;
Ian Kent eb3e266
 
Ian Kent eb3e266
   /*
Ian Kent eb3e266
-   * If there's a transp structure then we can reply to the client's
Ian Kent eb3e266
-   * nfs lookup request.
Ian Kent eb3e266
+   * If there's no transp structure then we can't reply to the
Ian Kent eb3e266
+   * client's nfs lookup request.
Ian Kent eb3e266
    */
Ian Kent eb3e266
-  if (transp) {
Ian Kent eb3e266
-    if (error == 0) {
Ian Kent eb3e266
-      /*
Ian Kent eb3e266
-       * Construct a valid reply to a lookup request.  Same
Ian Kent eb3e266
-       * code as in nfsproc_lookup_2_svc() above.
Ian Kent eb3e266
-       */
Ian Kent eb3e266
-      mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle);
Ian Kent eb3e266
-      res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr;
Ian Kent eb3e266
-      res.dr_status = NFS_OK;
Ian Kent eb3e266
-    } else
Ian Kent eb3e266
-      /*
Ian Kent eb3e266
-       * Return the error that was passed to us.
Ian Kent eb3e266
-       */
Ian Kent eb3e266
-      res.dr_status = nfs_error(error);
Ian Kent eb3e266
+  if (!mp->am_transp)
Ian Kent eb3e266
+    return;
Ian Kent eb3e266
+
Ian Kent eb3e266
+  if (nfs_dispatcher == nfs_program_2)
Ian Kent eb3e266
+    ret = nfs_quick_reply2(mp, error);
Ian Kent eb3e266
+  else
Ian Kent eb3e266
+    ret = nfs_quick_reply3(mp, error);
Ian Kent eb3e266
+
Ian Kent eb3e266
+  if (!ret)
Ian Kent eb3e266
+    svcerr_systemerr(mp->am_transp);
Ian Kent eb3e266
+
Ian Kent eb3e266
+  /*
Ian Kent eb3e266
+   * Free up transp.  It's only used for one reply.
Ian Kent eb3e266
+   */
Ian Kent eb3e266
+  put_nfs_xprt(mp->am_transp);
Ian Kent eb3e266
+  mp->am_transp = NULL;
Ian Kent eb3e266
+  dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
Ian Kent eb3e266
+}
Ian Kent eb3e266
 
Ian Kent eb3e266
+
Ian Kent eb3e266
+static int
Ian Kent eb3e266
+nfs_quick_reply2(am_node *mp, int error)
Ian Kent eb3e266
+{
Ian Kent eb3e266
+  SVCXPRT *transp = mp->am_transp;
Ian Kent eb3e266
+  nfsdiropres res;
Ian Kent eb3e266
+  xdrproc_t xdr_result = (xdrproc_t) xdr_diropres;
Ian Kent eb3e266
+  int ret;
Ian Kent eb3e266
+
Ian Kent eb3e266
+  if (error == 0) {
Ian Kent eb3e266
     /*
Ian Kent eb3e266
-     * Send off our reply
Ian Kent eb3e266
+     * Construct a valid reply to a lookup request.  Same
Ian Kent eb3e266
+     * code as in nfsproc_lookup_2_svc() above.
Ian Kent eb3e266
      */
Ian Kent eb3e266
-    if (!svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, (SVC_IN_ARG_TYPE) & res))
Ian Kent eb3e266
-      svcerr_systemerr(transp);
Ian Kent eb3e266
-
Ian Kent eb3e266
+    mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle);
Ian Kent eb3e266
+    res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr;
Ian Kent eb3e266
+    res.dr_status = NFS_OK;
Ian Kent eb3e266
+  } else
Ian Kent eb3e266
     /*
Ian Kent eb3e266
-     * Free up transp.  It's only used for one reply.
Ian Kent eb3e266
+     * Return the error that was passed to us.
Ian Kent eb3e266
      */
Ian Kent eb3e266
-    put_nfs_xprt(mp->am_transp);
Ian Kent eb3e266
-    mp->am_transp = NULL;
Ian Kent eb3e266
-    dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
Ian Kent eb3e266
-  }
Ian Kent eb3e266
+    res.dr_status = nfs_error(error);
Ian Kent eb3e266
+
Ian Kent eb3e266
+  /*
Ian Kent eb3e266
+   * Send off our reply
Ian Kent eb3e266
+   */
Ian Kent eb3e266
+  ret = svc_sendreply(transp,
Ian Kent eb3e266
+                     (XDRPROC_T_TYPE) xdr_result,
Ian Kent eb3e266
+                     (SVC_IN_ARG_TYPE) & res);
Ian Kent eb3e266
+
Ian Kent eb3e266
+  return ret;
Ian Kent eb3e266
 }
Ian Kent eb3e266
 
Ian Kent eb3e266
 
Ian Kent eb3e266
@@ -890,6 +912,8 @@ mp_to_fh(am_node *mp, am_nfs_fh *fhp)
Ian Kent eb3e266
     /* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */
Ian Kent eb3e266
   }
Ian Kent eb3e266
 }
Ian Kent eb3e266
+
Ian Kent eb3e266
+
Ian Kent eb3e266
 void
Ian Kent eb3e266
 mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp)
Ian Kent eb3e266
 {
Ian Kent eb3e266
@@ -1257,6 +1281,61 @@ am_nfs3_lookup_3_svc(am_LOOKUP3args *argp, struct svc_req *rqstp)
Ian Kent eb3e266
   return &result;
Ian Kent eb3e266
 }
Ian Kent eb3e266
 
Ian Kent eb3e266
+
Ian Kent eb3e266
+static int
Ian Kent eb3e266
+nfs_quick_reply3(am_node *mp, int error)
Ian Kent eb3e266
+{
Ian Kent eb3e266
+  SVCXPRT *transp = mp->am_transp;
Ian Kent eb3e266
+  xdrproc_t xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
Ian Kent eb3e266
+  am_LOOKUP3res  result;
Ian Kent eb3e266
+  am_post_op_attr *post_op_dir;
Ian Kent eb3e266
+  am_post_op_attr *post_op_obj;
Ian Kent eb3e266
+  int ret;
Ian Kent eb3e266
+
Ian Kent eb3e266
+  if (error) {
Ian Kent eb3e266
+    /*
Ian Kent eb3e266
+     * Return the error that was passed to us.
Ian Kent eb3e266
+     */
Ian Kent eb3e266
+    post_op_dir->attributes_follow = 0;
Ian Kent eb3e266
+    result.status = nfs_error(error);
Ian Kent eb3e266
+  } else {
Ian Kent eb3e266
+    post_op_dir = &result.res_u.ok.dir_attributes;
Ian Kent eb3e266
+    post_op_obj = &result.res_u.ok.obj_attributes;
Ian Kent eb3e266
+    am_fattr3 *fattr3;
Ian Kent eb3e266
+    nfsfattr *fattr;
Ian Kent eb3e266
+
Ian Kent eb3e266
+    /*
Ian Kent eb3e266
+     * Construct a valid reply to a lookup request.  Same
Ian Kent eb3e266
+     * code as in am_nfs3_lookup_3_svc() above.
Ian Kent eb3e266
+     */
Ian Kent eb3e266
+
Ian Kent eb3e266
+    /* dir attributes */
Ian Kent eb3e266
+    post_op_dir->attributes_follow = 1;
Ian Kent eb3e266
+    fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
Ian Kent eb3e266
+    parent_fattr_to_fattr3(mp, fattr3);
Ian Kent eb3e266
+
Ian Kent eb3e266
+    mp_to_fh3(mp, &result.res_u.ok.object);
Ian Kent eb3e266
+
Ian Kent eb3e266
+    /* mount attributes */
Ian Kent eb3e266
+    post_op_obj->attributes_follow = 1;
Ian Kent eb3e266
+    fattr = &mp->am_fattr;
Ian Kent eb3e266
+    fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
Ian Kent eb3e266
+    fattr_to_fattr3(fattr, fattr3);
Ian Kent eb3e266
+
Ian Kent eb3e266
+    result.status = AM_NFS3_OK;
Ian Kent eb3e266
+  }
Ian Kent eb3e266
+
Ian Kent eb3e266
+  /*
Ian Kent eb3e266
+   * Send off our reply
Ian Kent eb3e266
+   */
Ian Kent eb3e266
+  ret = svc_sendreply(transp,
Ian Kent eb3e266
+                     (XDRPROC_T_TYPE) xdr_result,
Ian Kent eb3e266
+                     (SVC_IN_ARG_TYPE) &result);
Ian Kent eb3e266
+
Ian Kent eb3e266
+  return ret;
Ian Kent eb3e266
+}
Ian Kent eb3e266
+
Ian Kent eb3e266
+
Ian Kent eb3e266
 am_ACCESS3res *
Ian Kent eb3e266
 am_nfs3_access_3_svc(am_ACCESS3args *argp, struct svc_req *rqstp)
Ian Kent eb3e266
 {