Commit 099e99f0 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] nfsv4 page boundary handling fixes.

From: Galen Michael Elias <gme@citi.umich.edu>

  This patch fixes two places where the handling of page boundaries was
incorrect and caused to IO_ERR's when it shouldn't have.

1.  In decode_write it was just a small typo.
2.  In decode_compound we avoid using READ_BUF, but don't provide all of
it's functionality, specifically crosses a page boundary.
parent dd726068
...@@ -880,7 +880,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) ...@@ -880,7 +880,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
v++; v++;
write->wr_vec[v].iov_base = page_address(argp->pagelist[0]); write->wr_vec[v].iov_base = page_address(argp->pagelist[0]);
argp->pagelist++; argp->pagelist++;
if (len >= PAGE_SIZE) { if (argp->pagelen >= PAGE_SIZE) {
write->wr_vec[v].iov_len = PAGE_SIZE; write->wr_vec[v].iov_len = PAGE_SIZE;
argp->pagelen -= PAGE_SIZE; argp->pagelen -= PAGE_SIZE;
} else { } else {
...@@ -934,16 +934,35 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) ...@@ -934,16 +934,35 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
op = &argp->ops[i]; op = &argp->ops[i];
/* /*
* Before reading the opcode, we test for the 4-byte buffer * We can't use READ_BUF() here because we need to handle
* overrun explicitly, instead of using READ_BUF(). This is * a missing opcode as an OP_WRITE + 1. So we need to check
* because we want a missing opcode to be treated as opcode * to see if we're truly at the end of our buffer or if there
* OP_WRITE+1, instead of a failed XDR. * is another page we need to flip to.
*/ */
if (argp->p == argp->end) { if (argp->p == argp->end) {
op->opnum = OP_WRITE + 1; if (argp->pagelen < 4) {
op->status = nfserr_bad_xdr; /* There isn't an opcode still on the wire */
argp->opcnt = i+1; op->opnum = OP_WRITE + 1;
break; op->status = nfserr_bad_xdr;
argp->opcnt = i+1;
break;
}
/*
* False alarm. We just hit a page boundary, but there
* is still data available. Move pointer across page
* boundary. *snip from READ_BUF*
*/
argp->p = page_address(argp->pagelist[0]);
argp->pagelist++;
if (argp->pagelen < PAGE_SIZE) {
argp->end = p + (argp->pagelen>>2);
argp->pagelen = 0;
} else {
argp->end = p + (PAGE_SIZE>>2);
argp->pagelen -= PAGE_SIZE;
}
} }
op->opnum = ntohl(*argp->p++); op->opnum = ntohl(*argp->p++);
......
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