Udiff nfs3_xdr.c
--- /webrev/webrev/usr/src/uts/common/fs/nfs/nfs3_xdr.c-        Mon Aug 14 13:12:13 2006
+++ nfs3_xdr.c  Sun Jul 23 00:43:22 2006
@@ -25,10 +25,22 @@
  */
 
 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
 /* All Rights Reserved */
 
+ /* Copyright (c) 2006, The Ohio State University. All rights reserved.
+  *
+  * Portions of this source code is developed by the team members of
+  * The Ohio State University's Network-Based Computing Laboratory (NBCL),
+  * headed by Professor Dhabaleswar K. (DK) Panda.
+  *
+  * Acknowledgements to contributions from developors:
+  *   Ranjit Noronha: noronha@cse.ohio-state.edu
+  *   Lei Chai      : chail@cse.ohio-state.edu
+  *   Weikuan Yu    : yuw@cse.ohio-state.edu
+  *
+  */
 #pragma ident  "@(#)nfs3_xdr.c 1.62    05/06/08 SMI"
 
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/systm.h>
@@ -49,10 +61,11 @@
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 
 #include <nfs/nfs.h>
 #include <nfs/rnode.h>
+#include <rpc/rpc_rdma.h>
 
 /* Checks if the fh is 32 bytes and returns TRUE if it is, otherwise FALSE */
 #define        XDR_CHECKFHSIZE(x, len, sz)     \
        (((int32_t)ntohl(len) == NFS3_CURFHSIZE) ? TRUE : \
        (xdr_rewind(x, sz), FALSE))
@@ -1270,28 +1283,46 @@
                                        *mp->b_wptr++ = '\0';
                        if (xdrmblk_putmblk(xdrs, mp, resokp->count) == TRUE) {
                                resokp->data.mp = NULL;
                                return (TRUE);
                        }
+               
+                } else {
+                       if(xdr_u_int(xdrs, &resokp->count) == FALSE){
+                                return (FALSE);
                }
                /*
+                        * If read data sent by wlist (RDMA_WRITE), don't do
+                        * xdr_bytes() below.   RDMA_WRITE transfers the data.
+                        * Note: this is encode-only because the client code
+                        * uses xdr_READ3vres/xdr_READ3uiores to decode results.
+                        */
+                       if (resokp->wlist) {
+                              /*clist_free(resokp->wlist);*/
+                               return (TRUE);
+                       }
+               }
+        
+               /*
                 * Fall thru for the xdr_bytes()
                 *
                 * note: the mblk will be freed in
                 * rfs3_read_free.
                 */
        }
 
+       /* no RDMA_WRITE transfer -- send data inline */
+
        ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val,
            &resokp->data.data_len, nfs3tsize());
-
        return (ret);
 }
 
 bool_t
 xdr_READ3vres(XDR *xdrs, READ3vres *objp)
 {
+count3 ocount;
        /*
         * DECODE or FREE only
         */
        if (xdrs->x_op == XDR_FREE)
                return (TRUE);
@@ -1312,17 +1343,34 @@
                return (FALSE);
 
        if (!xdr_bool(xdrs, &objp->eof))
                return (FALSE);
 
+       /*
+        * If read data received via RDMA_WRITE, don't do xdr_bytes().
+        * RDMA_WRITE already moved the data so decode length of RDMA_WRITE.
+        */
+       if (objp->wlist) {
+       if (!xdr_u_int(xdrs, &ocount))
+               return (FALSE);
+       if(ocount != objp->count){
+       cmn_err(CE_NOTE,"NFS: READ count doesn't match RPC opaque count.\n");
+       return(FALSE);
+       }
+               objp->data.data_len = objp->wlist_len;
+              clist_free(objp->wlist);
+               return (TRUE);
+       }
+
        return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
            &objp->data.data_len, nfs3tsize()));
 }
 
 bool_t
 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp)
 {
+       count3 ocount;
        bool_t attributes;
        mblk_t *mp;
        size_t n;
        int error;
        int size = (int)objp->size;
@@ -1394,10 +1442,30 @@
                        while (mp && (mp->b_rptr >= mp->b_wptr))
                                mp = mp->b_cont;
                } while (mp && size > 0 && uiop->uio_resid > 0);
 
                return (TRUE);
+       }
+
+       if (objp->wlist) {
+               if (!xdr_u_int(xdrs, &ocount))
+                       return (FALSE);
+               if(ocount != objp->count){
+                       cmn_err(CE_NOTE,"NFS: READ count doesn't match RPC opaque count.\n");
+                       return(FALSE);
+               }
+               /*
+               * XXX: Assume 1 iov, needs to be changed.
+               */
+               uiop->uio_resid -= objp->count;
+               uiop->uio_iov->iov_len -= objp->count;
+               uiop->uio_iov->iov_base += objp->count;
+               uiop->uio_loffset += objp->count;
+               objp->size = objp->wlist_len;
+              clist_free(objp->wlist);
+
+               return (TRUE);
        }
 
        /*
         * This isn't an xdrmblk stream.   Handle the likely
         * case that it can be inlined (ex. xdrmem).