From fc70014e410134efdcda92ae12824bf92de964bf Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Sun, 5 Jan 2003 03:43:44 -0800 Subject: [PATCH] knfsd: NFSv4 server fixes Assorted fixes particularly related to handling the new style xdr_buf buffers for NFSv4 server --- fs/nfsd/nfs4proc.c | 2 ++ fs/nfsd/nfs4xdr.c | 53 +++++++++++++++++++++++++++++++++-------------- include/linux/nfsd/xdr4.h | 1 + 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 99d89405387d..24a0a912e7c0 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -568,6 +568,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, resp->xbuf = &rqstp->rq_res; resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; + resp->tagp = resp->p + 1; /* skip over status */ + /* reserve space for: status, taglen, tag, and opcnt */ resp->p += 3 + XDR_QUADLEN(args->taglen); resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE; resp->taglen = args->taglen; diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 906b727f8873..fba884d7d8d6 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1728,8 +1728,17 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read WRITE32(maxcount); ADJUST_ARGS(); resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; - resp->p = resp->xbuf->tail[0].iov_base; + resp->xbuf->page_len = maxcount; + + /* set up page for remaining responses */ + svc_take_page(resp->rqstp); + resp->xbuf->tail[0].iov_base = + page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); + resp->xbuf->tail[0].iov_len = 0; + resp->p = resp->xbuf->tail[0].iov_base; + resp->end = resp->p + PAGE_SIZE/4; + if (maxcount&3) { *(resp->p)++ = 0; resp->xbuf->tail[0].iov_base += maxcount&3; @@ -1753,11 +1762,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r svc_take_page(resp->rqstp); page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); - svc_take_page(resp->rqstp); - resp->xbuf->tail[0].iov_base = - page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); - resp->xbuf->tail[0].iov_len = 0; - maxcount = PAGE_SIZE; RESERVE_SPACE(4); @@ -1774,7 +1778,14 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r WRITE32(maxcount); ADJUST_ARGS(); resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; + + svc_take_page(resp->rqstp); + resp->xbuf->tail[0].iov_base = + page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); + resp->xbuf->tail[0].iov_len = 0; resp->p = resp->xbuf->tail[0].iov_base; + resp->end = resp->p + PAGE_SIZE/4; + resp->xbuf->page_len = maxcount; if (maxcount&3) { *(resp->p)++ = 0; @@ -1803,6 +1814,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re WRITE32(0); WRITE32(0); ADJUST_ARGS(); + resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; maxcount = PAGE_SIZE; if (maxcount > readdir->rd_maxcount) @@ -1832,16 +1844,26 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re readdir->common.err == nfserr_readdir_nospc && readdir->buffer == page) nfserr = nfserr_readdir_nospc; - if (!nfserr) { - if (readdir->offset) - xdr_encode_hyper(readdir->offset, offset); + if (nfserr) + return nfserr; - p = readdir->buffer; - *p++ = 0; /* no more entries */ - *p++ = htonl(readdir->common.err == nfserr_eof); - resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); - } - return nfserr; + if (readdir->offset) + xdr_encode_hyper(readdir->offset, offset); + + p = readdir->buffer; + *p++ = 0; /* no more entries */ + *p++ = htonl(readdir->common.err == nfserr_eof); + resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); + + /* allocate a page for the tail */ + svc_take_page(resp->rqstp); + resp->xbuf->tail[0].iov_base = + page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); + resp->xbuf->tail[0].iov_len = 0; + resp->p = resp->xbuf->tail[0].iov_base; + resp->end = resp->p + PAGE_SIZE/4; + + return 0; } static void @@ -2066,6 +2088,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compound * All that remains is to write the tag and operation count... */ struct iovec *iov; + p = resp->tagp; *p++ = htonl(resp->taglen); memcpy(p, resp->tag, resp->taglen); p += XDR_QUADLEN(resp->taglen); diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index 8359679908ab..c29972812936 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h @@ -320,6 +320,7 @@ struct nfsd4_compoundres { u32 taglen; char * tag; u32 opcnt; + u32 * tagp; /* where to encode tag and opcount */ }; #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) -- cgit v1.2.3