diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 44 |
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 */ |
462 | static | 461 | static |
463 | int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, | 462 | int 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 | |||
523 | void nfs_readdir_free_large_page(void *ptr, struct page **pages, | 525 | void 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 | */ |
534 | static | 535 | static |
535 | void *nfs_readdir_large_page(struct page **pages, unsigned int npages) | 536 | int 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; | ||
550 | out_freepages: | 548 | out_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 | ||
555 | static | 553 | static |
@@ -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; |