summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2003-01-05 03:43:44 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-01-05 03:43:44 -0800
commitfc70014e410134efdcda92ae12824bf92de964bf (patch)
tree8797ee38ce3521373e6a3071f4bd7a49bb215700
parentec6867b3093f15e8c4fcc96438245458f596d97f (diff)
[PATCH] knfsd: NFSv4 server fixes
Assorted fixes particularly related to handling the new style xdr_buf buffers for NFSv4 server
-rw-r--r--fs/nfsd/nfs4proc.c2
-rw-r--r--fs/nfsd/nfs4xdr.c53
-rw-r--r--include/linux/nfsd/xdr4.h1
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)