Commit 6edc72f4 authored by Neil Brown's avatar Neil Brown Committed by James Bottomley

[PATCH] Fix handling of error code in NFSv4 replies

As nfsv4 does some reply encoding while processing
requests, the code which tries to put the overall status
at the head of the reply fails.

With this patch, we take the address for the overall
status very early so NFSv4's encoding wont confuse us.
parent 467cb27b
...@@ -568,9 +568,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, ...@@ -568,9 +568,9 @@ 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 */ resp->tagp = resp->p;
/* reserve space for: status, taglen, tag, and opcnt */ /* reserve space for: taglen, tag, and opcnt */
resp->p += 3 + XDR_QUADLEN(args->taglen); resp->p += 2 + 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;
resp->tag = args->tag; resp->tag = args->tag;
......
...@@ -264,6 +264,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) ...@@ -264,6 +264,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
struct svc_procedure *proc; struct svc_procedure *proc;
kxdrproc_t xdr; kxdrproc_t xdr;
u32 nfserr; u32 nfserr;
u32 *nfserrp;
dprintk("nfsd_dispatch: vers %d proc %d\n", dprintk("nfsd_dispatch: vers %d proc %d\n",
rqstp->rq_vers, rqstp->rq_proc); rqstp->rq_vers, rqstp->rq_proc);
...@@ -290,6 +291,13 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) ...@@ -290,6 +291,13 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
return 1; return 1;
} }
/* need to grab the location to store the status, as
* nfsv4 does some encoding while processing
*/
nfserrp = rqstp->rq_res.head[0].iov_base
+ rqstp->rq_res.head[0].iov_len;
rqstp->rq_res.head[0].iov_len += sizeof(u32);
/* Now call the procedure handler, and encode NFS status. */ /* Now call the procedure handler, and encode NFS status. */
nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
if (nfserr == nfserr_dropit) { if (nfserr == nfserr_dropit) {
...@@ -297,16 +305,16 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) ...@@ -297,16 +305,16 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
nfsd_cache_update(rqstp, RC_NOCACHE, NULL); nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
return 0; return 0;
} }
if (rqstp->rq_proc != 0) if (rqstp->rq_proc != 0)
svc_putu32(&rqstp->rq_res.head[0], nfserr); *nfserrp++ = nfserr;
/* Encode result. /* Encode result.
* For NFSv2, additional info is never returned in case of an error. * For NFSv2, additional info is never returned in case of an error.
*/ */
if (!(nfserr && rqstp->rq_vers == 2)) { if (!(nfserr && rqstp->rq_vers == 2)) {
xdr = proc->pc_encode; xdr = proc->pc_encode;
if (xdr && !xdr(rqstp, (u32*)(rqstp->rq_res.head[0].iov_base+rqstp->rq_res.head[0].iov_len), if (xdr && !xdr(rqstp, nfserrp,
rqstp->rq_resp)) { rqstp->rq_resp)) {
/* Failed to encode result. Release cache entry */ /* Failed to encode result. Release cache entry */
dprintk("nfsd: failed to encode result!\n"); dprintk("nfsd: failed to encode result!\n");
......
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