aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/dir.c44
-rw-r--r--fs/nfs/nfs2xdr.c6
-rw-r--r--fs/nfs/nfs3xdr.c6
-rw-r--r--fs/nfs/nfs4xdr.c6
4 files changed, 21 insertions, 41 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 996dd8989a91..0108cf4f3403 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 37
39#include "delegation.h" 38#include "delegation.h"
@@ -459,25 +458,26 @@ out:
459/* Perform conversion from xdr to cache array */ 458/* Perform conversion from xdr to cache array */
460static 459static
461int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, 460int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
462 void *xdr_page, struct page *page, unsigned int buflen) 461 struct page **xdr_pages, struct page *page, unsigned int buflen)
463{ 462{
464 struct xdr_stream stream; 463 struct xdr_stream stream;
465 struct xdr_buf buf; 464 struct xdr_buf buf = {
466 __be32 *ptr = xdr_page; 465 .pages = xdr_pages,
466 .page_len = buflen,
467 .buflen = buflen,
468 .len = buflen,
469 };
470 struct page *scratch;
467 struct nfs_cache_array *array; 471 struct nfs_cache_array *array;
468 unsigned int count = 0; 472 unsigned int count = 0;
469 int status; 473 int status;
470 474
471 buf.head->iov_base = xdr_page; 475 scratch = alloc_page(GFP_KERNEL);
472 buf.head->iov_len = buflen; 476 if (scratch == NULL)
473 buf.tail->iov_len = 0; 477 return -ENOMEM;
474 buf.page_base = 0;
475 buf.page_len = 0;
476 buf.buflen = buf.head->iov_len;
477 buf.len = buf.head->iov_len;
478
479 xdr_init_decode(&stream, &buf, ptr);
480 478
479 xdr_init_decode(&stream, &buf, NULL);
480 xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
481 481
482 do { 482 do {
483 status = xdr_decode(desc, entry, &stream); 483 status = xdr_decode(desc, entry, &stream);
@@ -506,6 +506,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
506 } else 506 } else
507 status = PTR_ERR(array); 507 status = PTR_ERR(array);
508 } 508 }
509
510 put_page(scratch);
509 return status; 511 return status;
510} 512}
511 513
@@ -521,7 +523,6 @@ static
521void nfs_readdir_free_large_page(void *ptr, struct page **pages, 523void nfs_readdir_free_large_page(void *ptr, struct page **pages,
522 unsigned int npages) 524 unsigned int npages)
523{ 525{
524 vm_unmap_ram(ptr, npages);
525 nfs_readdir_free_pagearray(pages, npages); 526 nfs_readdir_free_pagearray(pages, npages);
526} 527}
527 528
@@ -530,9 +531,8 @@ void nfs_readdir_free_large_page(void *ptr, struct page **pages,
530 * to nfs_readdir_free_large_page 531 * to nfs_readdir_free_large_page
531 */ 532 */
532static 533static
533void *nfs_readdir_large_page(struct page **pages, unsigned int npages) 534int nfs_readdir_large_page(struct page **pages, unsigned int npages)
534{ 535{
535 void *ptr;
536 unsigned int i; 536 unsigned int i;
537 537
538 for (i = 0; i < npages; i++) { 538 for (i = 0; i < npages; i++) {
@@ -541,13 +541,11 @@ void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
541 goto out_freepages; 541 goto out_freepages;
542 pages[i] = page; 542 pages[i] = page;
543 } 543 }
544 return 0;
544 545
545 ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL);
546 if (!IS_ERR_OR_NULL(ptr))
547 return ptr;
548out_freepages: 546out_freepages:
549 nfs_readdir_free_pagearray(pages, i); 547 nfs_readdir_free_pagearray(pages, i);
550 return NULL; 548 return -ENOMEM;
551} 549}
552 550
553static 551static
@@ -577,8 +575,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
577 memset(array, 0, sizeof(struct nfs_cache_array)); 575 memset(array, 0, sizeof(struct nfs_cache_array));
578 array->eof_index = -1; 576 array->eof_index = -1;
579 577
580 pages_ptr = nfs_readdir_large_page(pages, array_size); 578 status = nfs_readdir_large_page(pages, array_size);
581 if (!pages_ptr) 579 if (status < 0)
582 goto out_release_array; 580 goto out_release_array;
583 do { 581 do {
584 unsigned int pglen; 582 unsigned int pglen;
@@ -587,7 +585,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
587 if (status < 0) 585 if (status < 0)
588 break; 586 break;
589 pglen = status; 587 pglen = status;
590 status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, pglen); 588 status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen);
591 if (status < 0) { 589 if (status < 0) {
592 if (status == -ENOSPC) 590 if (status == -ENOSPC)
593 status = 0; 591 status = 0;
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 5914a1911c95..b382a1b5e7e4 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -487,12 +487,6 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
487 487
488 entry->d_type = DT_UNKNOWN; 488 entry->d_type = DT_UNKNOWN;
489 489
490 p = xdr_inline_peek(xdr, 8);
491 if (p != NULL)
492 entry->eof = !p[0] && p[1];
493 else
494 entry->eof = 0;
495
496 return p; 490 return p;
497 491
498out_overflow: 492out_overflow:
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index f6cc60f06dac..ba91236c6ee7 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -647,12 +647,6 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
647 memset((u8*)(entry->fh), 0, sizeof(*entry->fh)); 647 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
648 } 648 }
649 649
650 p = xdr_inline_peek(xdr, 8);
651 if (p != NULL)
652 entry->eof = !p[0] && p[1];
653 else
654 entry->eof = 0;
655
656 return p; 650 return p;
657 651
658out_overflow: 652out_overflow:
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 9f1826b012e6..0662a9821df5 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -6215,12 +6215,6 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6215 if (verify_attr_len(xdr, p, len) < 0) 6215 if (verify_attr_len(xdr, p, len) < 0)
6216 goto out_overflow; 6216 goto out_overflow;
6217 6217
6218 p = xdr_inline_peek(xdr, 8);
6219 if (p != NULL)
6220 entry->eof = !p[0] && p[1];
6221 else
6222 entry->eof = 0;
6223
6224 return p; 6218 return p;
6225 6219
6226out_overflow: 6220out_overflow: