]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Split buffer overflow checking out of struct nfs4_compound
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Fri, 22 Nov 2002 03:08:38 +0000 (19:08 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Fri, 22 Nov 2002 03:08:38 +0000 (19:08 -0800)
Here is the a pre-patch in the attempt to get rid of 'struct
nfs4_compound', and the associated horrible union in 'struct
nfs4_op'.

It splits out the fields that are meant to do buffer overflow checking
and iovec adjusting on the XDR received/sent data. It moves support
for that nto the dedicated structure 'xdr_stream', and the associated
functions 'xdr_reserve_space()', 'xdr_inline_decode()'.

The patch also expands out the all macros ENCODE_HEAD, ENCODE_TAIL,
ADJUST_ARGS and DECODE_HEAD, as well as most of the DECODE_TAILs.

fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_xdr.h
include/linux/sunrpc/xdr.h

index b17c138681eb005b7a7bf46918def51a3d58b500..e563bdc7e3155d8623c2bda376834ce13c446b31 100644 (file)
@@ -65,11 +65,6 @@ nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops,
        memset(cp, 0, sizeof(*cp));
        cp->ops = ops;
        cp->server = server;
-
-#if NFS4_DEBUG
-       cp->taglen = strlen(tag);
-       cp->tag = tag;
-#endif
 }
 
 static void
@@ -373,6 +368,7 @@ nfs4_setup_open(struct nfs4_compound *cp, int flags, struct qstr *name,
 
        BUG_ON(cp->flags);
        
+       open->op_client_state = cp->server->nfs4_state;
        open->op_share_access = flags & 3;
        open->op_opentype = (flags & O_CREAT) ? NFS4_OPEN_CREATE : NFS4_OPEN_NOCREATE;
        open->op_createmode = NFS4_CREATE_UNCHECKED;
@@ -527,6 +523,10 @@ nfs4_setup_rename(struct nfs4_compound *cp, struct qstr *old, struct qstr *new,
 static void
 nfs4_setup_renew(struct nfs4_compound *cp)
 {
+       struct nfs4_client **client_state = GET_OP(cp, renew);
+
+       *client_state = cp->server->nfs4_state;
+
        OPNUM(cp) = OP_RENEW;
        cp->req_nops++;
        cp->renew_index = cp->req_nops;
@@ -575,6 +575,7 @@ nfs4_setup_setclientid(struct nfs4_compound *cp, u32 program, unsigned short por
        sprintf(setclientid->sc_uaddr, "%s.%d.%d", server->ip_addr, port >> 8, port & 255);
        setclientid->sc_prog = program;
        setclientid->sc_cb_ident = 0;
+       setclientid->sc_state = server->nfs4_state;
        
        OPNUM(cp) = OP_SETCLIENTID;
        cp->req_nops++;
@@ -583,6 +584,10 @@ nfs4_setup_setclientid(struct nfs4_compound *cp, u32 program, unsigned short por
 static void
 nfs4_setup_setclientid_confirm(struct nfs4_compound *cp)
 {
+       struct nfs4_client **client_state = GET_OP(cp, setclientid_confirm);
+
+       *client_state = cp->server->nfs4_state;
+
        OPNUM(cp) = OP_SETCLIENTID_CONFIRM;
        cp->req_nops++;
        cp->renew_index = cp->req_nops;
index 7b6c503e4cc7f111d7702724d15227caae93b00e..3847a6bf08749949c5ea1443f96d3daa2fbee414 100644 (file)
@@ -57,8 +57,6 @@
  */
 #define COOKIE_MAX             0x7fffffff
 
-#define NFS4_CLIENTID(server)  ((server)->nfs4_state->cl_clientid)
-
 #define NFSDBG_FACILITY                NFSDBG_XDR
 
 /* Mapping from NFS error code to "errno" error code. */
@@ -95,25 +93,22 @@ static struct {
  * task to translate them into Linux-specific versions which are more
  * consistent with the style used in NFSv2/v3...
  */
-#define ENCODE_HEAD                                            \
-       u32 *p;
-#define ENCODE_TAIL                                            \
-       return 0
-
 #define WRITE32(n)               *p++ = htonl(n)
 #define WRITE64(n)               do {                          \
-       *p++ = htonl((u32)((n) >> 32));                         \
-       *p++ = htonl((u32)(n));                                 \
+       *p++ = htonl((uint32_t)((n) >> 32));                            \
+       *p++ = htonl((uint32_t)(n));                                    \
 } while (0)
 #define WRITEMEM(ptr,nbytes)     do {                          \
        p = xdr_writemem(p, ptr, nbytes);                       \
 } while (0)
 
-#define RESERVE_SPACE(nbytes)  do { BUG_ON(cp->p + XDR_QUADLEN(nbytes) > cp->end); p = cp->p; } while (0)
-#define ADJUST_ARGS()           cp->p = p
+#define RESERVE_SPACE(nbytes)  do {                            \
+       p = xdr_reserve_space(xdr, nbytes);                     \
+       BUG_ON(!p);                                             \
+} while (0)
 
 static inline
-u32 *xdr_writemem(u32 *p, const void *ptr, int nbytes)
+uint32_t *xdr_writemem(uint32_t *p, const void *ptr, int nbytes)
 {
        int tmp = XDR_QUADLEN(nbytes);
        if (!tmp)
@@ -146,18 +141,18 @@ encode_gid(char *p, gid_t gid)
 }
 
 static int
-encode_attrs(struct nfs4_compound *cp, struct iattr *iap)
+encode_attrs(struct xdr_stream *xdr, struct iattr *iap)
 {
        char owner_name[256];
        char owner_group[256];
        int owner_namelen = 0;
        int owner_grouplen = 0;
-       u32 *q;
+       uint32_t *p;
+       uint32_t *q;
        int len;
-       u32 bmval0 = 0;
-       u32 bmval1 = 0;
+       uint32_t bmval0 = 0;
+       uint32_t bmval1 = 0;
        int status;
-       ENCODE_HEAD;
 
        /*
         * We reserve enough space to write the entire attribute buffer at once.
@@ -240,8 +235,6 @@ encode_attrs(struct nfs4_compound *cp, struct iattr *iap)
                WRITE32(NFS4_SET_TO_SERVER_TIME);
        }
        
-       ADJUST_ARGS();
-       
        /*
         * Now we backfill the bitmap and the attribute buffer length.
         */
@@ -256,69 +249,63 @@ out:
 }
 
 static int
-encode_access(struct nfs4_compound *cp, struct nfs4_access *access)
+encode_access(struct xdr_stream *xdr, struct nfs4_access *access)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(8);
        WRITE32(OP_ACCESS);
        WRITE32(access->ac_req_access);
-       ADJUST_ARGS();
        
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_close(struct nfs4_compound *cp, struct nfs4_close *close)
+encode_close(struct xdr_stream *xdr, struct nfs4_close *close)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(20);
        WRITE32(OP_CLOSE);
        WRITE32(close->cl_seqid);
        WRITEMEM(close->cl_stateid, sizeof(nfs4_stateid));
-       ADJUST_ARGS();
        
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_commit(struct nfs4_compound *cp, struct nfs4_commit *commit)
+encode_commit(struct xdr_stream *xdr, struct nfs4_commit *commit)
 {
-        ENCODE_HEAD;
+       uint32_t *p;
         
         RESERVE_SPACE(16);
         WRITE32(OP_COMMIT);
         WRITE64(commit->co_start);
         WRITE32(commit->co_len);
-        ADJUST_ARGS();
 
-        ENCODE_TAIL;
+        return 0;
 }
 
 static int
-encode_create(struct nfs4_compound *cp, struct nfs4_create *create)
+encode_create(struct xdr_stream *xdr, struct nfs4_create *create)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
        
        RESERVE_SPACE(8);
        WRITE32(OP_CREATE);
        WRITE32(create->cr_ftype);
-       ADJUST_ARGS();
 
        switch (create->cr_ftype) {
        case NF4LNK:
                RESERVE_SPACE(4 + create->cr_textlen);
                WRITE32(create->cr_textlen);
                WRITEMEM(create->cr_text, create->cr_textlen);
-               ADJUST_ARGS();
                break;
 
        case NF4BLK: case NF4CHR:
                RESERVE_SPACE(8);
                WRITE32(create->cr_specdata1);
                WRITE32(create->cr_specdata2);
-               ADJUST_ARGS();
                break;
 
        default:
@@ -328,74 +315,69 @@ encode_create(struct nfs4_compound *cp, struct nfs4_create *create)
        RESERVE_SPACE(4 + create->cr_namelen);
        WRITE32(create->cr_namelen);
        WRITEMEM(create->cr_name, create->cr_namelen);
-       ADJUST_ARGS();
 
-       return encode_attrs(cp, create->cr_attrs);
+       return encode_attrs(xdr, create->cr_attrs);
 }
 
 static int
-encode_getattr(struct nfs4_compound *cp, struct nfs4_getattr *getattr)
+encode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr)
 {
-        ENCODE_HEAD;
+        uint32_t *p;
 
         RESERVE_SPACE(16);
         WRITE32(OP_GETATTR);
         WRITE32(2);
         WRITE32(getattr->gt_bmval[0]);
         WRITE32(getattr->gt_bmval[1]);
-        ADJUST_ARGS();
 
-        ENCODE_TAIL;
+        return 0;
 }
 
 static int
-encode_getfh(struct nfs4_compound *cp)
+encode_getfh(struct xdr_stream *xdr)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(4);
        WRITE32(OP_GETFH);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_link(struct nfs4_compound *cp, struct nfs4_link *link)
+encode_link(struct xdr_stream *xdr, struct nfs4_link *link)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(8 + link->ln_namelen);
        WRITE32(OP_LINK);
        WRITE32(link->ln_namelen);
        WRITEMEM(link->ln_name, link->ln_namelen);
-       ADJUST_ARGS();
        
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_lookup(struct nfs4_compound *cp, struct nfs4_lookup *lookup)
+encode_lookup(struct xdr_stream *xdr, struct nfs4_lookup *lookup)
 {
        int len = lookup->lo_name->len;
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(8 + len);
        WRITE32(OP_LOOKUP);
        WRITE32(len);
        WRITEMEM(lookup->lo_name->name, len);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_open(struct nfs4_compound *cp, struct nfs4_open *open)
+encode_open(struct xdr_stream *xdr, struct nfs4_open *open)
 {
        static int global_id = 0;
        int id = global_id++;
        int status;
-       ENCODE_HEAD;
+       uint32_t *p;
        
        /* seqid, share_access, share_deny, clientid, ownerlen, owner, opentype */
        RESERVE_SPACE(52);
@@ -403,24 +385,21 @@ encode_open(struct nfs4_compound *cp, struct nfs4_open *open)
        WRITE32(0);                       /* seqid */
        WRITE32(open->op_share_access);
        WRITE32(0);                       /* for us, share_deny== 0 always */
-       WRITE64(NFS4_CLIENTID(cp->server));
+       WRITE64(open->op_client_state->cl_clientid);
        WRITE32(4);
        WRITE32(id);
        WRITE32(open->op_opentype);
-       ADJUST_ARGS();
        
        if (open->op_opentype == NFS4_OPEN_CREATE) {
                if (open->op_createmode == NFS4_CREATE_EXCLUSIVE) {
                        RESERVE_SPACE(12);
                        WRITE32(open->op_createmode);
                        WRITEMEM(open->op_verifier, sizeof(nfs4_verifier));
-                       ADJUST_ARGS();
                }
                else if (open->op_attrs) {
                        RESERVE_SPACE(4);
                        WRITE32(open->op_createmode);
-                       ADJUST_ARGS();
-                       if ((status = encode_attrs(cp, open->op_attrs)))
+                       if ((status = encode_attrs(xdr, open->op_attrs)))
                                return status;
                }
                else {
@@ -428,7 +407,6 @@ encode_open(struct nfs4_compound *cp, struct nfs4_open *open)
                        WRITE32(open->op_createmode);
                        WRITE32(0);
                        WRITE32(0);
-                       ADJUST_ARGS();
                }
        }
 
@@ -436,15 +414,14 @@ encode_open(struct nfs4_compound *cp, struct nfs4_open *open)
        WRITE32(NFS4_OPEN_CLAIM_NULL);
        WRITE32(open->op_name->len);
        WRITEMEM(open->op_name->name, open->op_name->len);
-       ADJUST_ARGS();
        
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_open_confirm(struct nfs4_compound *cp, struct nfs4_open_confirm *open_confirm)
+encode_open_confirm(struct xdr_stream *xdr, struct nfs4_open_confirm *open_confirm)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        /*
         * Note: In this "stateless" implementation, the OPEN_CONFIRM
@@ -454,44 +431,41 @@ encode_open_confirm(struct nfs4_compound *cp, struct nfs4_open_confirm *open_con
        WRITE32(OP_OPEN_CONFIRM);
        WRITEMEM(open_confirm->oc_stateid, sizeof(nfs4_stateid));
        WRITE32(1);
-       ADJUST_ARGS();
        
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_putfh(struct nfs4_compound *cp, struct nfs4_putfh *putfh)
+encode_putfh(struct xdr_stream *xdr, struct nfs4_putfh *putfh)
 {
        int len = putfh->pf_fhandle->size;
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(8 + len);
        WRITE32(OP_PUTFH);
        WRITE32(len);
        WRITEMEM(putfh->pf_fhandle->data, len);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_putrootfh(struct nfs4_compound *cp)
+encode_putrootfh(struct xdr_stream *xdr)
 {
-        ENCODE_HEAD;
+        uint32_t *p;
         
         RESERVE_SPACE(4);
         WRITE32(OP_PUTROOTFH);
-        ADJUST_ARGS();
 
-        ENCODE_TAIL;
+        return 0;
 }
 
 static int
-encode_read(struct nfs4_compound *cp, struct nfs4_read *read, struct rpc_rqst *req)
+encode_read(struct xdr_stream *xdr, struct nfs4_read *read, struct rpc_rqst *req)
 {
        struct rpc_auth *auth = req->rq_task->tk_auth;
        int             replen;
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(32);
        WRITE32(OP_READ);
@@ -501,26 +475,24 @@ encode_read(struct nfs4_compound *cp, struct nfs4_read *read, struct rpc_rqst *r
        WRITE32(0);
        WRITE64(read->rd_offset);
        WRITE32(read->rd_length);
-       ADJUST_ARGS();
 
        /* set up reply iovec
         *    toplevel status + taglen + rescount + OP_PUTFH + status
         *       + OP_READ + status + eof + datalen = 9
         */
-       replen = (RPC_REPHDRSIZE + auth->au_rslack + 9 + XDR_QUADLEN(cp->taglen)) << 2;
-       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+       replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
        xdr_inline_pages(&req->rq_rcv_buf, replen,
                         read->rd_pages, read->rd_pgbase, read->rd_length);
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_readdir(struct nfs4_compound *cp, struct nfs4_readdir *readdir, struct rpc_rqst *req)
+encode_readdir(struct xdr_stream *xdr, struct nfs4_readdir *readdir, struct rpc_rqst *req)
 {
        struct rpc_auth *auth = req->rq_task->tk_auth;
        int replen;
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(40);
        WRITE32(OP_READDIR);
@@ -531,135 +503,124 @@ encode_readdir(struct nfs4_compound *cp, struct nfs4_readdir *readdir, struct rp
        WRITE32(2);
        WRITE32(readdir->rd_bmval[0]);
        WRITE32(readdir->rd_bmval[1]);
-       ADJUST_ARGS();
 
        /* set up reply iovec
         *    toplevel_status + taglen + rescount + OP_PUTFH + status
         *      + OP_READDIR + status + verifer(2)  = 9
         */
-       replen = (RPC_REPHDRSIZE + auth->au_rslack + 9 + XDR_QUADLEN(cp->taglen)) << 2;
-       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+       replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
        xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->rd_pages,
                         readdir->rd_pgbase, readdir->rd_count);
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_readlink(struct nfs4_compound *cp, struct nfs4_readlink *readlink, struct rpc_rqst *req)
+encode_readlink(struct xdr_stream *xdr, struct nfs4_readlink *readlink, struct rpc_rqst *req)
 {
        struct rpc_auth *auth = req->rq_task->tk_auth;
        int replen;
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(4);
        WRITE32(OP_READLINK);
-       ADJUST_ARGS();
 
        /* set up reply iovec
         *    toplevel_status + taglen + rescount + OP_PUTFH + status
         *      + OP_READLINK + status  = 7
         */
-       replen = (RPC_REPHDRSIZE + auth->au_rslack + 7 + XDR_QUADLEN(cp->taglen)) << 2;
-       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+       replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
        xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->rl_pages, 0, readlink->rl_count);
        
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_remove(struct nfs4_compound *cp, struct nfs4_remove *remove)
+encode_remove(struct xdr_stream *xdr, struct nfs4_remove *remove)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(8 + remove->rm_namelen);
        WRITE32(OP_REMOVE);
        WRITE32(remove->rm_namelen);
        WRITEMEM(remove->rm_name, remove->rm_namelen);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_rename(struct nfs4_compound *cp, struct nfs4_rename *rename)
+encode_rename(struct xdr_stream *xdr, struct nfs4_rename *rename)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(8 + rename->rn_oldnamelen);
        WRITE32(OP_RENAME);
        WRITE32(rename->rn_oldnamelen);
        WRITEMEM(rename->rn_oldname, rename->rn_oldnamelen);
-       ADJUST_ARGS();
        
        RESERVE_SPACE(8 + rename->rn_newnamelen);
        WRITE32(rename->rn_newnamelen);
        WRITEMEM(rename->rn_newname, rename->rn_newnamelen);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_renew(struct nfs4_compound *cp)
+encode_renew(struct xdr_stream *xdr, struct nfs4_client *client_stateid)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(12);
        WRITE32(OP_RENEW);
-       WRITE64(NFS4_CLIENTID(cp->server));
-       ADJUST_ARGS();
+       WRITE64(client_stateid->cl_clientid);
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_restorefh(struct nfs4_compound *cp)
+encode_restorefh(struct xdr_stream *xdr)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(4);
        WRITE32(OP_RESTOREFH);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_savefh(struct nfs4_compound *cp)
+encode_savefh(struct xdr_stream *xdr)
 {
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(4);
        WRITE32(OP_SAVEFH);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_setattr(struct nfs4_compound *cp, struct nfs4_setattr *setattr)
+encode_setattr(struct xdr_stream *xdr, struct nfs4_setattr *setattr)
 {
        int status;
-       ENCODE_HEAD;
+       uint32_t *p;
        
         RESERVE_SPACE(20);
         WRITE32(OP_SETATTR);
        WRITEMEM(setattr->st_stateid, sizeof(nfs4_stateid));
-        ADJUST_ARGS();
 
-        if ((status = encode_attrs(cp, setattr->st_iap)))
+        if ((status = encode_attrs(xdr, setattr->st_iap)))
                return status;
 
-        ENCODE_TAIL;
+        return 0;
 }
 
 static int
-encode_setclientid(struct nfs4_compound *cp, struct nfs4_setclientid *setclientid)
+encode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid *setclientid)
 {
-       u32 total_len;
-       u32 len1, len2, len3;
-       ENCODE_HEAD;
+       uint32_t total_len;
+       uint32_t len1, len2, len3;
+       uint32_t *p;
 
        len1 = strlen(setclientid->sc_name);
        len2 = strlen(setclientid->sc_netid);
@@ -678,30 +639,28 @@ encode_setclientid(struct nfs4_compound *cp, struct nfs4_setclientid *setclienti
        WRITE32(len3);
        WRITEMEM(setclientid->sc_uaddr, len3);
        WRITE32(setclientid->sc_cb_ident);
-       ADJUST_ARGS();
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 static int
-encode_setclientid_confirm(struct nfs4_compound *cp)
+encode_setclientid_confirm(struct xdr_stream *xdr, struct nfs4_client *client_state)
 {
-        ENCODE_HEAD;
+        uint32_t *p;
 
         RESERVE_SPACE(12 + sizeof(nfs4_verifier));
         WRITE32(OP_SETCLIENTID_CONFIRM);
-        WRITE64(cp->server->nfs4_state->cl_clientid);
-        WRITEMEM(cp->server->nfs4_state->cl_confirm,sizeof(nfs4_verifier));
-        ADJUST_ARGS();
+        WRITE64(client_state->cl_clientid);
+        WRITEMEM(client_state->cl_confirm,sizeof(nfs4_verifier));
 
-        ENCODE_TAIL;
+        return 0;
 }
 
 static int
-encode_write(struct nfs4_compound *cp, struct nfs4_write *write, struct rpc_rqst *req)
+encode_write(struct xdr_stream *xdr, struct nfs4_write *write, struct rpc_rqst *req)
 {
        struct xdr_buf *sndbuf = &req->rq_snd_buf;
-       ENCODE_HEAD;
+       uint32_t *p;
 
        RESERVE_SPACE(36);
        WRITE32(OP_WRITE);
@@ -712,20 +671,18 @@ encode_write(struct nfs4_compound *cp, struct nfs4_write *write, struct rpc_rqst
        WRITE64(write->wr_offset);
        WRITE32(write->wr_stable_how);
        WRITE32(write->wr_len);
-       ADJUST_ARGS();
 
-       sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
        xdr_encode_pages(sndbuf, write->wr_pages, write->wr_pgbase, write->wr_len);
 
-       ENCODE_TAIL;
+       return 0;
 }
 
 /* FIXME: this sucks */
 static int
-encode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
+encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqst *req)
 {
        int i, status = 0;
-       ENCODE_HEAD;
+       uint32_t *p;
 
        dprintk("encode_compound: tag=%.*s\n", (int)cp->taglen, cp->tag);
        
@@ -734,81 +691,80 @@ encode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
        WRITEMEM(cp->tag, cp->taglen);
        WRITE32(NFS4_MINOR_VERSION);
        WRITE32(cp->req_nops);
-       ADJUST_ARGS();
 
        for (i = 0; i < cp->req_nops; i++) {
                switch (cp->ops[i].opnum) {
                case OP_ACCESS:
-                       status = encode_access(cp, &cp->ops[i].u.access);
+                       status = encode_access(xdr, &cp->ops[i].u.access);
                        break;
                case OP_CLOSE:
-                       status = encode_close(cp, &cp->ops[i].u.close);
+                       status = encode_close(xdr, &cp->ops[i].u.close);
                        break;
                case OP_COMMIT:
-                       status = encode_commit(cp, &cp->ops[i].u.commit);
+                       status = encode_commit(xdr, &cp->ops[i].u.commit);
                        break;
                case OP_CREATE:
-                       status = encode_create(cp, &cp->ops[i].u.create);
+                       status = encode_create(xdr, &cp->ops[i].u.create);
                        break;
                case OP_GETATTR:
-                       status = encode_getattr(cp, &cp->ops[i].u.getattr);
+                       status = encode_getattr(xdr, &cp->ops[i].u.getattr);
                        break;
                case OP_GETFH:
-                       status = encode_getfh(cp);
+                       status = encode_getfh(xdr);
                        break;
                case OP_LINK:
-                       status = encode_link(cp, &cp->ops[i].u.link);
+                       status = encode_link(xdr, &cp->ops[i].u.link);
                        break;
                case OP_LOOKUP:
-                       status = encode_lookup(cp, &cp->ops[i].u.lookup);
+                       status = encode_lookup(xdr, &cp->ops[i].u.lookup);
                        break;
                case OP_OPEN:
-                       status = encode_open(cp, &cp->ops[i].u.open);
+                       status = encode_open(xdr, &cp->ops[i].u.open);
                        break;
                case OP_OPEN_CONFIRM:
-                       status = encode_open_confirm(cp, &cp->ops[i].u.open_confirm);
+                       status = encode_open_confirm(xdr, &cp->ops[i].u.open_confirm);
                        break;
                case OP_PUTFH:
-                       status = encode_putfh(cp, &cp->ops[i].u.putfh);
+                       status = encode_putfh(xdr, &cp->ops[i].u.putfh);
                        break;
                case OP_PUTROOTFH:
-                       status = encode_putrootfh(cp);
+                       status = encode_putrootfh(xdr);
                        break;
                case OP_READ:
-                       status = encode_read(cp, &cp->ops[i].u.read, req);
+                       status = encode_read(xdr, &cp->ops[i].u.read, req);
                        break;
                case OP_READDIR:
-                       status = encode_readdir(cp, &cp->ops[i].u.readdir, req);
+                       status = encode_readdir(xdr, &cp->ops[i].u.readdir, req);
                        break;
                case OP_READLINK:
-                       status = encode_readlink(cp, &cp->ops[i].u.readlink, req);
+                       status = encode_readlink(xdr, &cp->ops[i].u.readlink, req);
                        break;
                case OP_REMOVE:
-                       status = encode_remove(cp, &cp->ops[i].u.remove);
+                       status = encode_remove(xdr, &cp->ops[i].u.remove);
                        break;
                case OP_RENAME:
-                       status = encode_rename(cp, &cp->ops[i].u.rename);
+                       status = encode_rename(xdr, &cp->ops[i].u.rename);
                        break;
                case OP_RENEW:
-                       status = encode_renew(cp);
+                       status = encode_renew(xdr, cp->ops[i].u.renew);
                        break;
                case OP_RESTOREFH:
-                       status = encode_restorefh(cp);
+                       status = encode_restorefh(xdr);
                        break;
                case OP_SAVEFH:
-                       status = encode_savefh(cp);
+                       status = encode_savefh(xdr);
                        break;
                case OP_SETATTR:
-                       status = encode_setattr(cp, &cp->ops[i].u.setattr);
+                       status = encode_setattr(xdr, &cp->ops[i].u.setattr);
                        break;
                case OP_SETCLIENTID:
-                       status = encode_setclientid(cp, &cp->ops[i].u.setclientid);
+                       status = encode_setclientid(xdr, &cp->ops[i].u.setclientid);
                        break;
                case OP_SETCLIENTID_CONFIRM:
-                       status = encode_setclientid_confirm(cp);
+                       status = encode_setclientid_confirm(xdr, cp->ops[i].u.setclientid_confirm);
                        break;
                case OP_WRITE:
-                       status = encode_write(cp, &cp->ops[i].u.write, req);
+                       status = encode_write(xdr, &cp->ops[i].u.write, req);
                        break;
                default:
                        BUG();
@@ -817,7 +773,7 @@ encode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
                        return status;
        }
        
-       ENCODE_TAIL;
+       return 0;
 }
 /*
  * END OF "GENERIC" ENCODE ROUTINES.
@@ -828,18 +784,14 @@ encode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
  * Encode COMPOUND argument
  */
 static int
-nfs4_xdr_enc_compound(struct rpc_rqst *req, u32 *p, struct nfs4_compound *cp)
+nfs4_xdr_enc_compound(struct rpc_rqst *req, uint32_t *p, struct nfs4_compound *cp)
 {
+       struct xdr_stream xdr;
        int status;
-       struct xdr_buf *sndbuf = &req->rq_snd_buf;
        
-       cp->p = p;
-       cp->end = (u32 *) ((char *)req->rq_svec[0].iov_base + req->rq_svec[0].iov_len);
-       status = encode_compound(cp, req);
+       xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+       status = encode_compound(&xdr, cp, req);
        cp->timestamp = jiffies;
-
-       if (!status && !sndbuf->page_len)
-               req->rq_slen = xdr_adjust_iovec(sndbuf->head, cp->p);
        return status;
 }
 
@@ -854,9 +806,6 @@ nfs4_xdr_enc_compound(struct rpc_rqst *req, u32 *p, struct nfs4_compound *cp)
  * task to translate them into Linux-specific versions which are more
  * consistent with the style used in NFSv2/v3...
  */
-#define DECODE_HEAD                            \
-       u32 *p;                                 \
-       int status
 #define DECODE_TAIL                            \
        status = 0;                             \
 out:                                           \
@@ -881,11 +830,13 @@ xdr_error:                                        \
        p += XDR_QUADLEN(nbytes);               \
 } while (0)
 
-#define READ_BUF(nbytes)  do {                 \
-       if (nbytes > (u32)((char *)cp->end - (char *)cp->p))  \
-               goto xdr_error;                 \
-       p = cp->p;                              \
-       cp->p += XDR_QUADLEN(nbytes);           \
+#define READ_BUF(nbytes)  do { \
+       p = xdr_inline_decode(xdr, nbytes); \
+       if (!p) { \
+               printk(KERN_WARNING "%s: reply buffer overflowed in line %d.", \
+                               __FUNCTION__, __LINE__); \
+                       return -EIO; \
+       } \
 } while (0)
 
 /*
@@ -893,7 +844,7 @@ xdr_error:                                  \
  * upcall gets in...
  */
 static int
-decode_uid(char *p, u32 len, uid_t *uid)
+decode_uid(char *p, uint32_t len, uid_t *uid)
 {
        *uid = -2;
        return 0;
@@ -904,82 +855,78 @@ decode_uid(char *p, u32 len, uid_t *uid)
  * upcall gets in...
  */
 static int
-decode_gid(char *p, u32 len, gid_t *gid)
+decode_gid(char *p, uint32_t len, gid_t *gid)
 {
        *gid = -2;
        return 0;
 }
 
 static int
-decode_change_info(struct nfs4_compound *cp, struct nfs4_change_info *cinfo)
+decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
 {
-       DECODE_HEAD;
+       uint32_t *p;
 
        READ_BUF(20);
        READ32(cinfo->atomic);
        READ64(cinfo->before);
        READ64(cinfo->after);
-       
-       DECODE_TAIL;
+       return 0;
 }
 
 static int
-decode_access(struct nfs4_compound *cp, int nfserr, struct nfs4_access *access)
+decode_access(struct xdr_stream *xdr, int nfserr, struct nfs4_access *access)
 {
-       u32 supp, acc;
-       DECODE_HEAD;
+       uint32_t *p;
+       uint32_t supp, acc;
 
        if (!nfserr) {
                READ_BUF(8);
                READ32(supp);
                READ32(acc);
 
-               status = -EIO;
                if ((supp & ~access->ac_req_access) || (acc & ~supp)) {
                        printk(KERN_NOTICE "NFS: server returned bad bits in access call!\n");
-                       goto out;
+                       return -EIO;
                }
                *access->ac_resp_supported = supp;
                *access->ac_resp_access = acc;
        }
-       
-       DECODE_TAIL;
+       return 0;
 }
 
 static int
-decode_close(struct nfs4_compound *cp, int nfserr, struct nfs4_close *close)
+decode_close(struct xdr_stream *xdr, int nfserr, struct nfs4_close *close)
 {
-       DECODE_HEAD;
+       uint32_t *p;
 
        if (!nfserr) {
                READ_BUF(sizeof(nfs4_stateid));
                COPYMEM(close->cl_stateid, sizeof(nfs4_stateid));
        }
-       
-       DECODE_TAIL;
+       return 0;
 }
 
 static int
-decode_commit(struct nfs4_compound *cp, int nfserr, struct nfs4_commit *commit)
+decode_commit(struct xdr_stream *xdr, int nfserr, struct nfs4_commit *commit)
 {
-        DECODE_HEAD;
+       uint32_t *p;
 
         if (!nfserr) {
                 READ_BUF(8);
                 COPYMEM(commit->co_verifier->verifier, 8);
         }
-
-        DECODE_TAIL;
+       return 0;
 }
 
 static int
-decode_create(struct nfs4_compound *cp, int nfserr, struct nfs4_create *create)
+decode_create(struct xdr_stream *xdr, int nfserr, struct nfs4_create *create)
 {
-       u32 bmlen;
-       DECODE_HEAD;
+       uint32_t *p;
+       uint32_t bmlen;
+       int status;
 
        if (!nfserr) {
-               if ((status = decode_change_info(cp, create->cr_cinfo)))
+               if ((status = decode_change_info(xdr, create->cr_cinfo)))
                        goto out;
                READ_BUF(4);
                READ32(bmlen);
@@ -991,27 +938,28 @@ decode_create(struct nfs4_compound *cp, int nfserr, struct nfs4_create *create)
        DECODE_TAIL;
 }
 
-extern u32 nfs4_fattr_bitmap[2];
-extern u32 nfs4_fsinfo_bitmap[2];
-extern u32 nfs4_fsstat_bitmap[2];
-extern u32 nfs4_pathconf_bitmap[2];
+extern uint32_t nfs4_fattr_bitmap[2];
+extern uint32_t nfs4_fsinfo_bitmap[2];
+extern uint32_t nfs4_fsstat_bitmap[2];
+extern uint32_t nfs4_pathconf_bitmap[2];
 
 static int
-decode_getattr(struct nfs4_compound *cp, int nfserr, struct nfs4_getattr *getattr)
+decode_getattr(struct xdr_stream *xdr, int nfserr, struct nfs4_getattr *getattr)
 {
         struct nfs_fattr *nfp = getattr->gt_attrs;
        struct nfs_fsstat *fsstat = getattr->gt_fsstat;
        struct nfs_fsinfo *fsinfo = getattr->gt_fsinfo;
        struct nfs_pathconf *pathconf = getattr->gt_pathconf;
-        u32 bmlen;
-        u32 bmval0 = 0;
-        u32 bmval1 = 0;
-        u32 attrlen;
-        u32 dummy32;
-        u32 len = 0;
+       uint32_t *p;
+        uint32_t bmlen;
+        uint32_t bmval0 = 0;
+        uint32_t bmval1 = 0;
+        uint32_t attrlen;
+        uint32_t dummy32;
+        uint32_t len = 0;
        unsigned int type;
        int fmode = 0;
-        DECODE_HEAD;
+       int status;
        
         if (nfserr)
                 goto success;
@@ -1060,7 +1008,7 @@ decode_getattr(struct nfs4_compound *cp, int nfserr, struct nfs4_getattr *getatt
                 }
                nfp->type = nfs_type2fmt[type].nfs2type;
                fmode = nfs_type2fmt[type].mode;
-                dprintk("read_attrs: type=%d\n", (u32)nfp->type);
+                dprintk("read_attrs: type=%d\n", (uint32_t)nfp->type);
         }
         if (bmval0 & FATTR4_WORD0_CHANGE) {
                 READ_BUF(8);
@@ -1250,11 +1198,12 @@ success:
 }
 
 static int
-decode_getfh(struct nfs4_compound *cp, int nfserr, struct nfs4_getfh *getfh)
+decode_getfh(struct xdr_stream *xdr, int nfserr, struct nfs4_getfh *getfh)
 {
        struct nfs_fh *fh = getfh->gf_fhandle;
-       int len;
-        DECODE_HEAD;
+       uint32_t *p;
+       uint32_t len;
+       int status;
 
        /* Zero handle first to allow comparisons */
        memset(fh, 0, sizeof(*fh));
@@ -1273,26 +1222,27 @@ decode_getfh(struct nfs4_compound *cp, int nfserr, struct nfs4_getfh *getfh)
 }
 
 static int
-decode_link(struct nfs4_compound *cp, int nfserr, struct nfs4_link *link)
+decode_link(struct xdr_stream *xdr, int nfserr, struct nfs4_link *link)
 {
        int status = 0;
        
        if (!nfserr)
-               status = decode_change_info(cp, link->ln_cinfo);
+               status = decode_change_info(xdr, link->ln_cinfo);
        return status;
 }
 
 static int
-decode_open(struct nfs4_compound *cp, int nfserr, struct nfs4_open *open)
+decode_open(struct xdr_stream *xdr, int nfserr, struct nfs4_open *open)
 {
-       u32 bmlen, delegation_type;
-       DECODE_HEAD;
+       uint32_t *p;
+       uint32_t bmlen, delegation_type;
+       int status;
        
        if (!nfserr) {
                READ_BUF(sizeof(nfs4_stateid));
                COPYMEM(open->op_stateid, sizeof(nfs4_stateid));
 
-               decode_change_info(cp, open->op_cinfo);
+               decode_change_info(xdr, open->op_cinfo);
 
                READ_BUF(8);
                READ32(*open->op_rflags);
@@ -1311,23 +1261,23 @@ decode_open(struct nfs4_compound *cp, int nfserr, struct nfs4_open *open)
 }
 
 static int
-decode_open_confirm(struct nfs4_compound *cp, int nfserr, struct nfs4_open_confirm *open_confirm)
+decode_open_confirm(struct xdr_stream *xdr, int nfserr, struct nfs4_open_confirm *open_confirm)
 {
-       DECODE_HEAD;
+       uint32_t *p;
 
        if (!nfserr) {
                READ_BUF(sizeof(nfs4_stateid));
                COPYMEM(open_confirm->oc_stateid, sizeof(nfs4_stateid));
        }
-
-       DECODE_TAIL;
+       return 0;
 }
 
 static int
-decode_read(struct nfs4_compound *cp, int nfserr, struct nfs4_read *read)
+decode_read(struct xdr_stream *xdr, int nfserr, struct nfs4_read *read)
 {
-       u32 throwaway;
-       DECODE_HEAD;
+       uint32_t throwaway;
+       uint32_t *p;
+       int status;
 
        if (!nfserr) {
                READ_BUF(8);
@@ -1344,23 +1294,22 @@ decode_read(struct nfs4_compound *cp, int nfserr, struct nfs4_read *read)
 }
 
 static int
-decode_readdir(struct nfs4_compound *cp, int nfserr, struct rpc_rqst *req, struct nfs4_readdir *readdir)
+decode_readdir(struct xdr_stream *xdr, int nfserr, struct rpc_rqst *req, struct nfs4_readdir *readdir)
 {
        struct xdr_buf  *rcvbuf = &req->rq_rcv_buf;
        struct page     *page = *rcvbuf->pages;
        unsigned int    pglen = rcvbuf->page_len;
-       u32             *end, *entry;
-       u32             len, attrlen, word;
-       int             i;
-       DECODE_HEAD;
+       uint32_t *end, *entry, *p;
+       uint32_t len, attrlen, word;
+       int i;
 
        if (!nfserr) {
                READ_BUF(8);
                COPYMEM(readdir->rd_resp_verifier, 8);
 
                BUG_ON(pglen > PAGE_CACHE_SIZE);
-               p   = (u32 *) kmap(page);
-               end = (u32 *) ((char *)p + pglen + readdir->rd_pgbase);
+               p   = (uint32_t *) kmap(page);
+               end = (uint32_t *) ((char *)p + pglen + readdir->rd_pgbase);
 
                while (*p++) {
                        entry = p - 1;
@@ -1406,7 +1355,7 @@ decode_readdir(struct nfs4_compound *cp, int nfserr, struct rpc_rqst *req, struc
                kunmap(page);
        }
        
-       DECODE_TAIL;
+       return 0;
 short_pkt:
        printk(KERN_NOTICE "NFS: short packet in readdir reply!\n");
        /* truncate listing */
@@ -1419,11 +1368,11 @@ err_unmap:
 }
 
 static int
-decode_readlink(struct nfs4_compound *cp, int nfserr, struct rpc_rqst *req, struct nfs4_readlink *readlink)
+decode_readlink(struct xdr_stream *xdr, int nfserr, struct rpc_rqst *req, struct nfs4_readlink *readlink)
 {
        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
-       u32 *strlen;
-       u32 len;
+       uint32_t *strlen;
+       uint32_t len;
        char *string;
 
        if (!nfserr) {
@@ -1434,7 +1383,7 @@ decode_readlink(struct nfs4_compound *cp, int nfserr, struct rpc_rqst *req, stru
                 * and and null-terminate the text (the VFS expects
                 * null-termination).
                 */
-               strlen = (u32 *) kmap(rcvbuf->pages[0]);
+               strlen = (uint32_t *) kmap(rcvbuf->pages[0]);
                len = ntohl(*strlen);
                if (len > PAGE_CACHE_SIZE - 5) {
                        printk(KERN_WARNING "nfs: server returned giant symlink!\n");
@@ -1451,25 +1400,25 @@ decode_readlink(struct nfs4_compound *cp, int nfserr, struct rpc_rqst *req, stru
 }
 
 static int
-decode_remove(struct nfs4_compound *cp, int nfserr, struct nfs4_remove *remove)
+decode_remove(struct xdr_stream *xdr, int nfserr, struct nfs4_remove *remove)
 {
        int status;
 
        status = 0;
        if (!nfserr) 
-               status = decode_change_info(cp, remove->rm_cinfo);
+               status = decode_change_info(xdr, remove->rm_cinfo);
        return status;
 }
 
 static int
-decode_rename(struct nfs4_compound *cp, int nfserr, struct nfs4_rename *rename)
+decode_rename(struct xdr_stream *xdr, int nfserr, struct nfs4_rename *rename)
 {
        int status = 0;
 
        if (!nfserr) {
-               if ((status = decode_change_info(cp, rename->rn_src_cinfo)))
+               if ((status = decode_change_info(xdr, rename->rn_src_cinfo)))
                        goto out;
-               if ((status = decode_change_info(cp, rename->rn_dst_cinfo)))
+               if ((status = decode_change_info(xdr, rename->rn_dst_cinfo)))
                        goto out;
        }
 out:
@@ -1477,10 +1426,11 @@ out:
 }
 
 static int
-decode_setattr(struct nfs4_compound *cp)
+decode_setattr(struct xdr_stream *xdr)
 {
-        u32 bmlen;
-        DECODE_HEAD;
+       uint32_t *p;
+        uint32_t bmlen;
+       int status;
         
         READ_BUF(4);
         READ32(bmlen);
@@ -1492,17 +1442,17 @@ decode_setattr(struct nfs4_compound *cp)
 }
 
 static int
-decode_setclientid(struct nfs4_compound *cp, int nfserr)
+decode_setclientid(struct xdr_stream *xdr, int nfserr, struct nfs4_setclientid *setclientid)
 {
-       DECODE_HEAD;
+       uint32_t *p;
 
        if (!nfserr) {
                READ_BUF(8 + sizeof(nfs4_verifier));
-               READ64(cp->server->nfs4_state->cl_clientid);
-               COPYMEM(cp->server->nfs4_state->cl_confirm, sizeof(nfs4_verifier));
+               READ64(setclientid->sc_state->cl_clientid);
+               COPYMEM(setclientid->sc_state->cl_confirm, sizeof(nfs4_verifier));
        }
        else if (nfserr == NFSERR_CLID_INUSE) {
-               u32 len;
+               uint32_t len;
 
                /* skip netid string */
                READ_BUF(4);
@@ -1515,13 +1465,14 @@ decode_setclientid(struct nfs4_compound *cp, int nfserr)
                READ_BUF(len);
        }
 
-       DECODE_TAIL;
+       return 0;
 }
 
 static int
-decode_write(struct nfs4_compound *cp, int nfserr, struct nfs4_write *write)
+decode_write(struct xdr_stream *xdr, int nfserr, struct nfs4_write *write)
 {
-       DECODE_HEAD;
+       uint32_t *p;
+       int status;
 
        if (!nfserr) {
                READ_BUF(16);
@@ -1537,11 +1488,12 @@ decode_write(struct nfs4_compound *cp, int nfserr, struct nfs4_write *write)
 
 /* FIXME: this sucks */
 static int
-decode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
+decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqst *req)
 {
-       u32 taglen;
-       u32 opnum, nfserr;
-       DECODE_HEAD;
+       uint32_t *p;
+       uint32_t taglen;
+       uint32_t opnum, nfserr;
+       int status;
 
        READ_BUF(8);
        READ32(cp->toplevel_status);
@@ -1584,34 +1536,34 @@ decode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
 
                switch (opnum) {
                case OP_ACCESS:
-                       status = decode_access(cp, nfserr, &cp->ops[cp->nops].u.access);
+                       status = decode_access(xdr, nfserr, &cp->ops[cp->nops].u.access);
                        break;
                case OP_CLOSE:
-                       status = decode_close(cp, nfserr, &cp->ops[cp->nops].u.close);
+                       status = decode_close(xdr, nfserr, &cp->ops[cp->nops].u.close);
                        break;
                case OP_COMMIT:
-                       status = decode_commit(cp, nfserr, &cp->ops[cp->nops].u.commit);
+                       status = decode_commit(xdr, nfserr, &cp->ops[cp->nops].u.commit);
                        break;
                case OP_CREATE:
-                       status = decode_create(cp, nfserr, &cp->ops[cp->nops].u.create);
+                       status = decode_create(xdr, nfserr, &cp->ops[cp->nops].u.create);
                        break;
                case OP_GETATTR:
-                       status = decode_getattr(cp, nfserr, &cp->ops[cp->nops].u.getattr);
+                       status = decode_getattr(xdr, nfserr, &cp->ops[cp->nops].u.getattr);
                        break;
                case OP_GETFH:
-                       status = decode_getfh(cp, nfserr, &cp->ops[cp->nops].u.getfh);
+                       status = decode_getfh(xdr, nfserr, &cp->ops[cp->nops].u.getfh);
                        break;
                case OP_LINK:
-                       status = decode_link(cp, nfserr, &cp->ops[cp->nops].u.link);
+                       status = decode_link(xdr, nfserr, &cp->ops[cp->nops].u.link);
                        break;
                case OP_LOOKUP:
                        status = 0;
                        break;
                case OP_OPEN:
-                       status = decode_open(cp, nfserr, &cp->ops[cp->nops].u.open);
+                       status = decode_open(xdr, nfserr, &cp->ops[cp->nops].u.open);
                        break;
                case OP_OPEN_CONFIRM:
-                       status = decode_open_confirm(cp, nfserr, &cp->ops[cp->nops].u.open_confirm);
+                       status = decode_open_confirm(xdr, nfserr, &cp->ops[cp->nops].u.open_confirm);
                        break;
                case OP_PUTFH:
                        status = 0;
@@ -1620,22 +1572,22 @@ decode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
                        status = 0;
                        break;
                case OP_READ:
-                       status = decode_read(cp, nfserr, &cp->ops[cp->nops].u.read);
+                       status = decode_read(xdr, nfserr, &cp->ops[cp->nops].u.read);
                        break;
                case OP_READDIR:
-                       status = decode_readdir(cp, nfserr, req, &cp->ops[cp->nops].u.readdir);
+                       status = decode_readdir(xdr, nfserr, req, &cp->ops[cp->nops].u.readdir);
                        break;
                case OP_READLINK:
-                       status = decode_readlink(cp, nfserr, req, &cp->ops[cp->nops].u.readlink);
+                       status = decode_readlink(xdr, nfserr, req, &cp->ops[cp->nops].u.readlink);
                        break;
                case OP_RESTOREFH:
                        status = 0;
                        break;
                case OP_REMOVE:
-                       status = decode_remove(cp, nfserr, &cp->ops[cp->nops].u.remove);
+                       status = decode_remove(xdr, nfserr, &cp->ops[cp->nops].u.remove);
                        break;
                case OP_RENAME:
-                       status = decode_rename(cp, nfserr, &cp->ops[cp->nops].u.rename);
+                       status = decode_rename(xdr, nfserr, &cp->ops[cp->nops].u.rename);
                        break;
                case OP_RENEW:
                        status = 0;
@@ -1644,16 +1596,16 @@ decode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
                        status = 0;
                        break;
                case OP_SETATTR:
-                       status = decode_setattr(cp);
+                       status = decode_setattr(xdr);
                        break;
                case OP_SETCLIENTID:
-                       status = decode_setclientid(cp, nfserr);
+                       status = decode_setclientid(xdr, nfserr, &cp->ops[cp->nops].u.setclientid);
                        break;
                case OP_SETCLIENTID_CONFIRM:
                        status = 0;
                        break;
                case OP_WRITE:
-                       status = decode_write(cp, nfserr, &cp->ops[cp->nops].u.write);
+                       status = decode_write(xdr, nfserr, &cp->ops[cp->nops].u.write);
                        break;
                default:
                        BUG();
@@ -1673,14 +1625,13 @@ decode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
  * Decode COMPOUND response
  */
 static int
-nfs4_xdr_dec_compound(struct rpc_rqst *rqstp, u32 *p, struct nfs4_compound *cp)
+nfs4_xdr_dec_compound(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_compound *cp)
 {
+       struct xdr_stream xdr;
        int status;
        
-       cp->p = p;
-       cp->end = (u32 *) ((u8 *) rqstp->rq_rvec->iov_base + rqstp->rq_rvec->iov_len);
-
-       if ((status = decode_compound(cp, rqstp)))
+       xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+       if ((status = decode_compound(&xdr, cp, rqstp)))
                goto out;
        
        status = 0;
@@ -1691,10 +1642,10 @@ out:
        return status;
 }
 
-u32 *
-nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
+uint32_t *
+nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 {
-       u32 len;
+       uint32_t len;
 
        if (!*p++) {
                if (!*p)
index 6c82048e2acf8c79e981b0f973d31cf3aa4afc73..970ffa785f78955c532f87a3eb509bc772a4857e 100644 (file)
@@ -398,6 +398,7 @@ struct nfs4_lookup {
 };
 
 struct nfs4_open {
+       struct nfs4_client *            op_client_state;  /* request */
        u32                             op_share_access;  /* request */
        u32                             op_opentype;      /* request */
        u32                             op_createmode;    /* request */
@@ -472,6 +473,7 @@ struct nfs4_setclientid {
        char                            sc_netid[4];      /* request */
        char                            sc_uaddr[24];     /* request */
        u32                             sc_cb_ident;      /* request */
+       struct nfs4_client *            sc_state;         /* response */
 };
 
 struct nfs4_write {
@@ -504,8 +506,10 @@ struct nfs4_op {
                struct nfs4_readlink    readlink;
                struct nfs4_remove      remove;
                struct nfs4_rename      rename;
+               struct nfs4_client *    renew;
                struct nfs4_setattr     setattr;
                struct nfs4_setclientid setclientid;
+               struct nfs4_client *    setclientid_confirm;
                struct nfs4_write       write;
        } u;
 };
index 0233988f40b459e1efa9310392dde96606b7f630..74c5260b23432fec705dc0b6cd4f1c1ec918e91d 100644 (file)
@@ -155,6 +155,93 @@ typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
 extern void xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
                skb_reader_t *, skb_read_actor_t);
 
+/*
+ * Provide some simple tools for XDR buffer overflow-checking etc.
+ */
+struct xdr_stream {
+       uint32_t *p;            /* start of available buffer */
+       struct xdr_buf *buf;    /* XDR buffer to read/write */
+
+       uint32_t *end;          /* end of available buffer space */
+       struct iovec *iov;      /* pointer to the current iovec */
+};
+
+/*
+ * Initialize an xdr_stream for encoding data.
+ *
+ * Note: at the moment the RPC client only passes the length of our
+ *      scratch buffer in the xdr_buf's header iovec. Previously this
+ *      meant we needed to call xdr_adjust_iovec() after encoding the
+ *      data. With the new scheme, the xdr_stream manages the details
+ *      of the buffer length, and takes care of adjusting the iovec
+ *      length for us.
+ */
+static inline void
+xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
+{
+       struct iovec *iov = buf->head;
+
+       xdr->buf = buf;
+       xdr->iov = iov;
+       xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
+       buf->len = iov->iov_len = (char *)p - (char *)iov->iov_base;
+       xdr->p = p;
+}
+
+/*
+ * Check that we have enough buffer space to encode 'nbytes' more
+ * bytes of data. If so, update the total xdr_buf length, and
+ * adjust the length of the current iovec.
+ */
+static inline uint32_t *
+xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)
+{
+       uint32_t *p = xdr->p;
+       uint32_t *q;
+
+       /* align nbytes on the next 32-bit boundary */
+       nbytes += 3;
+       nbytes &= ~3;
+       q = p + (nbytes >> 2);
+       if (unlikely(q > xdr->end || q < p))
+               return NULL;
+       xdr->p = q;
+       xdr->iov->iov_len += nbytes;
+       xdr->buf->len += nbytes;
+       return p;
+}
+
+/*
+ * Initialize an xdr_stream for decoding data.
+ */
+static inline void
+xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
+{
+       struct iovec *iov = buf->head;
+       xdr->buf = buf;
+       xdr->iov = iov;
+       xdr->p = p;
+       xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
+}
+
+/*
+ * Check if the input buffer is long enough to enable us to decode
+ * 'nbytes' more bytes of data starting at the current position.
+ * If so return the current pointer, then update the current
+ * position.
+ */
+static inline uint32_t *
+xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
+{
+       uint32_t *p = xdr->p;
+       uint32_t *q = p + XDR_QUADLEN(nbytes);
+
+       if (unlikely(q > xdr->end || q < p))
+               return NULL;
+       xdr->p = q;
+       return p;
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _SUNRPC_XDR_H_ */