Commit fc70014e authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] knfsd: NFSv4 server fixes

Assorted fixes particularly related to handling the new style
xdr_buf buffers for NFSv4 server
parent ec6867b3
...@@ -568,6 +568,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, ...@@ -568,6 +568,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
resp->xbuf = &rqstp->rq_res; resp->xbuf = &rqstp->rq_res;
resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; 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->p += 3 + XDR_QUADLEN(args->taglen);
resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE; resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
resp->taglen = args->taglen; resp->taglen = args->taglen;
......
...@@ -1728,8 +1728,17 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read ...@@ -1728,8 +1728,17 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
WRITE32(maxcount); WRITE32(maxcount);
ADJUST_ARGS(); ADJUST_ARGS();
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 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; 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) { if (maxcount&3) {
*(resp->p)++ = 0; *(resp->p)++ = 0;
resp->xbuf->tail[0].iov_base += maxcount&3; resp->xbuf->tail[0].iov_base += maxcount&3;
...@@ -1753,11 +1762,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r ...@@ -1753,11 +1762,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
svc_take_page(resp->rqstp); svc_take_page(resp->rqstp);
page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); 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; maxcount = PAGE_SIZE;
RESERVE_SPACE(4); RESERVE_SPACE(4);
...@@ -1774,7 +1778,14 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r ...@@ -1774,7 +1778,14 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
WRITE32(maxcount); WRITE32(maxcount);
ADJUST_ARGS(); ADJUST_ARGS();
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 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->p = resp->xbuf->tail[0].iov_base;
resp->end = resp->p + PAGE_SIZE/4;
resp->xbuf->page_len = maxcount; resp->xbuf->page_len = maxcount;
if (maxcount&3) { if (maxcount&3) {
*(resp->p)++ = 0; *(resp->p)++ = 0;
...@@ -1803,6 +1814,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re ...@@ -1803,6 +1814,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
WRITE32(0); WRITE32(0);
WRITE32(0); WRITE32(0);
ADJUST_ARGS(); ADJUST_ARGS();
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
maxcount = PAGE_SIZE; maxcount = PAGE_SIZE;
if (maxcount > readdir->rd_maxcount) if (maxcount > readdir->rd_maxcount)
...@@ -1832,7 +1844,9 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re ...@@ -1832,7 +1844,9 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
readdir->common.err == nfserr_readdir_nospc && readdir->common.err == nfserr_readdir_nospc &&
readdir->buffer == page) readdir->buffer == page)
nfserr = nfserr_readdir_nospc; nfserr = nfserr_readdir_nospc;
if (!nfserr) { if (nfserr)
return nfserr;
if (readdir->offset) if (readdir->offset)
xdr_encode_hyper(readdir->offset, offset); xdr_encode_hyper(readdir->offset, offset);
...@@ -1840,8 +1854,16 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re ...@@ -1840,8 +1854,16 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
*p++ = 0; /* no more entries */ *p++ = 0; /* no more entries */
*p++ = htonl(readdir->common.err == nfserr_eof); *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]); resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
}
return nfserr; /* 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 static void
...@@ -2066,6 +2088,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compound ...@@ -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... * All that remains is to write the tag and operation count...
*/ */
struct iovec *iov; struct iovec *iov;
p = resp->tagp;
*p++ = htonl(resp->taglen); *p++ = htonl(resp->taglen);
memcpy(p, resp->tag, resp->taglen); memcpy(p, resp->tag, resp->taglen);
p += XDR_QUADLEN(resp->taglen); p += XDR_QUADLEN(resp->taglen);
......
...@@ -320,6 +320,7 @@ struct nfsd4_compoundres { ...@@ -320,6 +320,7 @@ struct nfsd4_compoundres {
u32 taglen; u32 taglen;
char * tag; char * tag;
u32 opcnt; u32 opcnt;
u32 * tagp; /* where to encode tag and opcount */
}; };
#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment