diff options
| -rw-r--r-- | fs/nfsd/nfs3proc.c | 17 | ||||
| -rw-r--r-- | fs/nfsd/nfs3xdr.c | 11 |
2 files changed, 24 insertions, 4 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 8f933e84cec1..9bc32af4e2da 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
| @@ -442,7 +442,9 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) | |||
| 442 | struct nfsd3_readdirargs *argp = rqstp->rq_argp; | 442 | struct nfsd3_readdirargs *argp = rqstp->rq_argp; |
| 443 | struct nfsd3_readdirres *resp = rqstp->rq_resp; | 443 | struct nfsd3_readdirres *resp = rqstp->rq_resp; |
| 444 | __be32 nfserr; | 444 | __be32 nfserr; |
| 445 | int count; | 445 | int count = 0; |
| 446 | struct page **p; | ||
| 447 | caddr_t page_addr = NULL; | ||
| 446 | 448 | ||
| 447 | dprintk("nfsd: READDIR(3) %s %d bytes at %d\n", | 449 | dprintk("nfsd: READDIR(3) %s %d bytes at %d\n", |
| 448 | SVCFH_fmt(&argp->fh), | 450 | SVCFH_fmt(&argp->fh), |
| @@ -462,7 +464,18 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) | |||
| 462 | nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, | 464 | nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, |
| 463 | &resp->common, nfs3svc_encode_entry); | 465 | &resp->common, nfs3svc_encode_entry); |
| 464 | memcpy(resp->verf, argp->verf, 8); | 466 | memcpy(resp->verf, argp->verf, 8); |
| 465 | resp->count = resp->buffer - argp->buffer; | 467 | count = 0; |
| 468 | for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) { | ||
| 469 | page_addr = page_address(*p); | ||
| 470 | |||
| 471 | if (((caddr_t)resp->buffer >= page_addr) && | ||
| 472 | ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) { | ||
| 473 | count += (caddr_t)resp->buffer - page_addr; | ||
| 474 | break; | ||
| 475 | } | ||
| 476 | count += PAGE_SIZE; | ||
| 477 | } | ||
| 478 | resp->count = count >> 2; | ||
| 466 | if (resp->offset) { | 479 | if (resp->offset) { |
| 467 | loff_t offset = argp->cookie; | 480 | loff_t offset = argp->cookie; |
| 468 | 481 | ||
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 93fea246f676..8d789124ed3c 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
| @@ -573,6 +573,7 @@ int | |||
| 573 | nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) | 573 | nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) |
| 574 | { | 574 | { |
| 575 | struct nfsd3_readdirargs *args = rqstp->rq_argp; | 575 | struct nfsd3_readdirargs *args = rqstp->rq_argp; |
| 576 | int len; | ||
| 576 | u32 max_blocksize = svc_max_payload(rqstp); | 577 | u32 max_blocksize = svc_max_payload(rqstp); |
| 577 | 578 | ||
| 578 | p = decode_fh(p, &args->fh); | 579 | p = decode_fh(p, &args->fh); |
| @@ -582,8 +583,14 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) | |||
| 582 | args->verf = p; p += 2; | 583 | args->verf = p; p += 2; |
| 583 | args->dircount = ~0; | 584 | args->dircount = ~0; |
| 584 | args->count = ntohl(*p++); | 585 | args->count = ntohl(*p++); |
| 585 | args->count = min_t(u32, args->count, max_blocksize); | 586 | len = args->count = min_t(u32, args->count, max_blocksize); |
| 586 | args->buffer = page_address(*(rqstp->rq_next_page++)); | 587 | |
| 588 | while (len > 0) { | ||
| 589 | struct page *p = *(rqstp->rq_next_page++); | ||
| 590 | if (!args->buffer) | ||
| 591 | args->buffer = page_address(p); | ||
| 592 | len -= PAGE_SIZE; | ||
| 593 | } | ||
| 587 | 594 | ||
| 588 | return xdr_argsize_check(rqstp, p); | 595 | return xdr_argsize_check(rqstp, p); |
| 589 | } | 596 | } |
