aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-01-10 14:48:02 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-01-10 14:48:02 -0500
commit68c404b18f6fba404b2753622d0459c68ee128ae (patch)
treec1ec0bb12f19d91071b461cc2831d9d3dd4c74f3 /fs/nfs/dir.c
parentd035c36c58dd9183ad6aa7875dea89893faedb55 (diff)
parent6650239a4b01077e80d5a4468562756d77afaa59 (diff)
Merge branch 'bugfixes' into nfs-for-2.6.38
Conflicts: fs/nfs/nfs2xdr.c fs/nfs/nfs3xdr.c fs/nfs/nfs4xdr.c
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c44
1 files changed, 21 insertions, 23 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 65d5cb4f70b1..16ec096f6b24 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -33,7 +33,6 @@
33#include <linux/namei.h> 33#include <linux/namei.h>
34#include <linux/mount.h> 34#include <linux/mount.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/vmalloc.h>
37#include <linux/kmemleak.h> 36#include <linux/kmemleak.h>
38#include <linux/xattr.h> 37#include <linux/xattr.h>
39 38
@@ -461,25 +460,26 @@ out:
461/* Perform conversion from xdr to cache array */ 460/* Perform conversion from xdr to cache array */
462static 461static
463int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, 462int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
464 void *xdr_page, struct page *page, unsigned int buflen) 463 struct page **xdr_pages, struct page *page, unsigned int buflen)
465{ 464{
466 struct xdr_stream stream; 465 struct xdr_stream stream;
467 struct xdr_buf buf; 466 struct xdr_buf buf = {
468 __be32 *ptr = xdr_page; 467 .pages = xdr_pages,
468 .page_len = buflen,
469 .buflen = buflen,
470 .len = buflen,
471 };
472 struct page *scratch;
469 struct nfs_cache_array *array; 473 struct nfs_cache_array *array;
470 unsigned int count = 0; 474 unsigned int count = 0;
471 int status; 475 int status;
472 476
473 buf.head->iov_base = xdr_page; 477 scratch = alloc_page(GFP_KERNEL);
474 buf.head->iov_len = buflen; 478 if (scratch == NULL)
475 buf.tail->iov_len = 0; 479 return -ENOMEM;
476 buf.page_base = 0;
477 buf.page_len = 0;
478 buf.buflen = buf.head->iov_len;
479 buf.len = buf.head->iov_len;
480
481 xdr_init_decode(&stream, &buf, ptr);
482 480
481 xdr_init_decode(&stream, &buf, NULL);
482 xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
483 483
484 do { 484 do {
485 status = xdr_decode(desc, entry, &stream); 485 status = xdr_decode(desc, entry, &stream);
@@ -508,6 +508,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
508 } else 508 } else
509 status = PTR_ERR(array); 509 status = PTR_ERR(array);
510 } 510 }
511
512 put_page(scratch);
511 return status; 513 return status;
512} 514}
513 515
@@ -523,7 +525,6 @@ static
523void nfs_readdir_free_large_page(void *ptr, struct page **pages, 525void nfs_readdir_free_large_page(void *ptr, struct page **pages,
524 unsigned int npages) 526 unsigned int npages)
525{ 527{
526 vm_unmap_ram(ptr, npages);
527 nfs_readdir_free_pagearray(pages, npages); 528 nfs_readdir_free_pagearray(pages, npages);
528} 529}
529 530
@@ -532,9 +533,8 @@ void nfs_readdir_free_large_page(void *ptr, struct page **pages,
532 * to nfs_readdir_free_large_page 533 * to nfs_readdir_free_large_page
533 */ 534 */
534static 535static
535void *nfs_readdir_large_page(struct page **pages, unsigned int npages) 536int nfs_readdir_large_page(struct page **pages, unsigned int npages)
536{ 537{
537 void *ptr;
538 unsigned int i; 538 unsigned int i;
539 539
540 for (i = 0; i < npages; i++) { 540 for (i = 0; i < npages; i++) {
@@ -543,13 +543,11 @@ void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
543 goto out_freepages; 543 goto out_freepages;
544 pages[i] = page; 544 pages[i] = page;
545 } 545 }
546 return 0;
546 547
547 ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL);
548 if (!IS_ERR_OR_NULL(ptr))
549 return ptr;
550out_freepages: 548out_freepages:
551 nfs_readdir_free_pagearray(pages, i); 549 nfs_readdir_free_pagearray(pages, i);
552 return NULL; 550 return -ENOMEM;
553} 551}
554 552
555static 553static
@@ -580,8 +578,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
580 memset(array, 0, sizeof(struct nfs_cache_array)); 578 memset(array, 0, sizeof(struct nfs_cache_array));
581 array->eof_index = -1; 579 array->eof_index = -1;
582 580
583 pages_ptr = nfs_readdir_large_page(pages, array_size); 581 status = nfs_readdir_large_page(pages, array_size);
584 if (!pages_ptr) 582 if (status < 0)
585 goto out_release_array; 583 goto out_release_array;
586 do { 584 do {
587 unsigned int pglen; 585 unsigned int pglen;
@@ -590,7 +588,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
590 if (status < 0) 588 if (status < 0)
591 break; 589 break;
592 pglen = status; 590 pglen = status;
593 status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, pglen); 591 status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen);
594 if (status < 0) { 592 if (status < 0) {
595 if (status == -ENOSPC) 593 if (status == -ENOSPC)
596 status = 0; 594 status = 0;