On 2/2/2016 02:38, J. Bruce Fields wrote: > On Sun, Jan 31, 2016 at 08:50:10PM +0800, Kinglong Mee wrote: >> ltp fsync02 will cause nfs sending LAYOUTCOMMIT with length >> larger than two pages. nfsd returns NFSERR_BAD_XDR right now. > > This is with the xfs block layout? Yes, xfs block layout. Tested by ltp's fsync02. thanks, Kinglong Mee > > Christoph, do we know anything about average or worst-case sizes for > that layout update field? > >> This patch lets nfsd supports read buffer from multiples pages. > > Hm. We'll end up kmalloc()ing the passed-in field length: > > p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); > > We still do still have that (avail + argp->pagelen) limit, so we're not > going to pass arbitrarily large nbytes straight from the network to > kmalloc. But we do try to avoid depending on higher-order allocations. > > --b. > >> >> Signed-off-by: Kinglong Mee <kinglongmee@xxxxxxxxx> >> --- >> fs/nfsd/nfs4xdr.c | 18 ++++++++++++++---- >> 1 file changed, 14 insertions(+), 4 deletions(-) >> >> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c >> index d6ef095..fcf399f 100644 >> --- a/fs/nfsd/nfs4xdr.c >> +++ b/fs/nfsd/nfs4xdr.c >> @@ -143,11 +143,11 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) >> * Maybe we need a new page, maybe we have just run out >> */ >> unsigned int avail = (char *)argp->end - (char *)argp->p; >> + unsigned int copied = 0; >> __be32 *p; >> + >> if (avail + argp->pagelen < nbytes) >> return NULL; >> - if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */ >> - return NULL; >> /* ok, we can do it with the current plus the next page */ >> if (nbytes <= sizeof(argp->tmp)) >> p = argp->tmp; >> @@ -164,9 +164,19 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) >> * guarantee p points to at least nbytes bytes. >> */ >> memcpy(p, argp->p, avail); >> + copied += avail; >> + nbytes -= avail; >> + >> + while (nbytes > PAGE_SIZE) { >> + next_decode_page(argp); >> + memcpy(((char*)p) + copied, argp->p, PAGE_SIZE); >> + copied += PAGE_SIZE; >> + nbytes -= PAGE_SIZE; >> + } >> + >> next_decode_page(argp); >> - memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); >> - argp->p += XDR_QUADLEN(nbytes - avail); >> + memcpy(((char*)p) + copied, argp->p, nbytes); >> + argp->p += XDR_QUADLEN(nbytes); >> return p; >> } >> >> -- >> 2.5.0 > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html