aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c162
1 files changed, 97 insertions, 65 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 07ac3847e562..f0a384e2ae63 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -34,6 +34,7 @@
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> 36#include <linux/vmalloc.h>
37#include <linux/kmemleak.h>
37 38
38#include "delegation.h" 39#include "delegation.h"
39#include "iostat.h" 40#include "iostat.h"
@@ -161,6 +162,7 @@ struct nfs_cache_array_entry {
161 u64 cookie; 162 u64 cookie;
162 u64 ino; 163 u64 ino;
163 struct qstr string; 164 struct qstr string;
165 unsigned char d_type;
164}; 166};
165 167
166struct nfs_cache_array { 168struct nfs_cache_array {
@@ -170,8 +172,6 @@ struct nfs_cache_array {
170 struct nfs_cache_array_entry array[0]; 172 struct nfs_cache_array_entry array[0];
171}; 173};
172 174
173#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
174
175typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); 175typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
176typedef struct { 176typedef struct {
177 struct file *file; 177 struct file *file;
@@ -194,9 +194,13 @@ typedef struct {
194static 194static
195struct nfs_cache_array *nfs_readdir_get_array(struct page *page) 195struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
196{ 196{
197 void *ptr;
197 if (page == NULL) 198 if (page == NULL)
198 return ERR_PTR(-EIO); 199 return ERR_PTR(-EIO);
199 return (struct nfs_cache_array *)kmap(page); 200 ptr = kmap(page);
201 if (ptr == NULL)
202 return ERR_PTR(-ENOMEM);
203 return ptr;
200} 204}
201 205
202static 206static
@@ -213,6 +217,9 @@ int nfs_readdir_clear_array(struct page *page, gfp_t mask)
213{ 217{
214 struct nfs_cache_array *array = nfs_readdir_get_array(page); 218 struct nfs_cache_array *array = nfs_readdir_get_array(page);
215 int i; 219 int i;
220
221 if (IS_ERR(array))
222 return PTR_ERR(array);
216 for (i = 0; i < array->size; i++) 223 for (i = 0; i < array->size; i++)
217 kfree(array->array[i].string.name); 224 kfree(array->array[i].string.name);
218 nfs_readdir_release_array(page); 225 nfs_readdir_release_array(page);
@@ -231,6 +238,11 @@ int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int le
231 string->name = kmemdup(name, len, GFP_KERNEL); 238 string->name = kmemdup(name, len, GFP_KERNEL);
232 if (string->name == NULL) 239 if (string->name == NULL)
233 return -ENOMEM; 240 return -ENOMEM;
241 /*
242 * Avoid a kmemleak false positive. The pointer to the name is stored
243 * in a page cache page which kmemleak does not scan.
244 */
245 kmemleak_not_leak(string->name);
234 string->hash = full_name_hash(name, len); 246 string->hash = full_name_hash(name, len);
235 return 0; 247 return 0;
236} 248}
@@ -244,20 +256,24 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
244 256
245 if (IS_ERR(array)) 257 if (IS_ERR(array))
246 return PTR_ERR(array); 258 return PTR_ERR(array);
247 ret = -EIO;
248 if (array->size >= MAX_READDIR_ARRAY)
249 goto out;
250 259
251 cache_entry = &array->array[array->size]; 260 cache_entry = &array->array[array->size];
261
262 /* Check that this entry lies within the page bounds */
263 ret = -ENOSPC;
264 if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE)
265 goto out;
266
252 cache_entry->cookie = entry->prev_cookie; 267 cache_entry->cookie = entry->prev_cookie;
253 cache_entry->ino = entry->ino; 268 cache_entry->ino = entry->ino;
269 cache_entry->d_type = entry->d_type;
254 ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); 270 ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
255 if (ret) 271 if (ret)
256 goto out; 272 goto out;
257 array->last_cookie = entry->cookie; 273 array->last_cookie = entry->cookie;
274 array->size++;
258 if (entry->eof == 1) 275 if (entry->eof == 1)
259 array->eof_index = array->size; 276 array->eof_index = array->size;
260 array->size++;
261out: 277out:
262 nfs_readdir_release_array(page); 278 nfs_readdir_release_array(page);
263 return ret; 279 return ret;
@@ -272,7 +288,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri
272 if (diff < 0) 288 if (diff < 0)
273 goto out_eof; 289 goto out_eof;
274 if (diff >= array->size) { 290 if (diff >= array->size) {
275 if (array->eof_index > 0) 291 if (array->eof_index >= 0)
276 goto out_eof; 292 goto out_eof;
277 desc->current_index += array->size; 293 desc->current_index += array->size;
278 return -EAGAIN; 294 return -EAGAIN;
@@ -281,8 +297,6 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri
281 index = (unsigned int)diff; 297 index = (unsigned int)diff;
282 *desc->dir_cookie = array->array[index].cookie; 298 *desc->dir_cookie = array->array[index].cookie;
283 desc->cache_entry_index = index; 299 desc->cache_entry_index = index;
284 if (index == array->eof_index)
285 desc->eof = 1;
286 return 0; 300 return 0;
287out_eof: 301out_eof:
288 desc->eof = 1; 302 desc->eof = 1;
@@ -296,17 +310,17 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
296 int status = -EAGAIN; 310 int status = -EAGAIN;
297 311
298 for (i = 0; i < array->size; i++) { 312 for (i = 0; i < array->size; i++) {
299 if (i == array->eof_index) {
300 desc->eof = 1;
301 status = -EBADCOOKIE;
302 }
303 if (array->array[i].cookie == *desc->dir_cookie) { 313 if (array->array[i].cookie == *desc->dir_cookie) {
304 desc->cache_entry_index = i; 314 desc->cache_entry_index = i;
305 status = 0; 315 status = 0;
306 break; 316 goto out;
307 } 317 }
308 } 318 }
309 319 if (i == array->eof_index) {
320 desc->eof = 1;
321 status = -EBADCOOKIE;
322 }
323out:
310 return status; 324 return status;
311} 325}
312 326
@@ -381,13 +395,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x
381static 395static
382int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) 396int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
383{ 397{
384 struct nfs_inode *node;
385 if (dentry->d_inode == NULL) 398 if (dentry->d_inode == NULL)
386 goto different; 399 goto different;
387 node = NFS_I(dentry->d_inode); 400 if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0)
388 if (node->fh.size != entry->fh->size)
389 goto different;
390 if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0)
391 goto different; 401 goto different;
392 return 1; 402 return 1;
393different: 403different:
@@ -449,14 +459,15 @@ out:
449 459
450/* Perform conversion from xdr to cache array */ 460/* Perform conversion from xdr to cache array */
451static 461static
452void 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,
453 void *xdr_page, struct page *page, unsigned int buflen) 463 void *xdr_page, struct page *page, unsigned int buflen)
454{ 464{
455 struct xdr_stream stream; 465 struct xdr_stream stream;
456 struct xdr_buf buf; 466 struct xdr_buf buf;
457 __be32 *ptr = xdr_page; 467 __be32 *ptr = xdr_page;
458 int status;
459 struct nfs_cache_array *array; 468 struct nfs_cache_array *array;
469 unsigned int count = 0;
470 int status;
460 471
461 buf.head->iov_base = xdr_page; 472 buf.head->iov_base = xdr_page;
462 buf.head->iov_len = buflen; 473 buf.head->iov_len = buflen;
@@ -471,21 +482,32 @@ void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *e
471 482
472 do { 483 do {
473 status = xdr_decode(desc, entry, &stream); 484 status = xdr_decode(desc, entry, &stream);
474 if (status != 0) 485 if (status != 0) {
486 if (status == -EAGAIN)
487 status = 0;
475 break; 488 break;
489 }
490
491 count++;
476 492
477 if (nfs_readdir_add_to_array(entry, page) == -1)
478 break;
479 if (desc->plus == 1) 493 if (desc->plus == 1)
480 nfs_prime_dcache(desc->file->f_path.dentry, entry); 494 nfs_prime_dcache(desc->file->f_path.dentry, entry);
495
496 status = nfs_readdir_add_to_array(entry, page);
497 if (status != 0)
498 break;
481 } while (!entry->eof); 499 } while (!entry->eof);
482 500
483 if (status == -EBADCOOKIE && entry->eof) { 501 if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) {
484 array = nfs_readdir_get_array(page); 502 array = nfs_readdir_get_array(page);
485 array->eof_index = array->size - 1; 503 if (!IS_ERR(array)) {
486 status = 0; 504 array->eof_index = array->size;
487 nfs_readdir_release_array(page); 505 status = 0;
506 nfs_readdir_release_array(page);
507 } else
508 status = PTR_ERR(array);
488 } 509 }
510 return status;
489} 511}
490 512
491static 513static
@@ -537,7 +559,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
537 struct nfs_entry entry; 559 struct nfs_entry entry;
538 struct file *file = desc->file; 560 struct file *file = desc->file;
539 struct nfs_cache_array *array; 561 struct nfs_cache_array *array;
540 int status = 0; 562 int status = -ENOMEM;
541 unsigned int array_size = ARRAY_SIZE(pages); 563 unsigned int array_size = ARRAY_SIZE(pages);
542 564
543 entry.prev_cookie = 0; 565 entry.prev_cookie = 0;
@@ -549,6 +571,10 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
549 goto out; 571 goto out;
550 572
551 array = nfs_readdir_get_array(page); 573 array = nfs_readdir_get_array(page);
574 if (IS_ERR(array)) {
575 status = PTR_ERR(array);
576 goto out;
577 }
552 memset(array, 0, sizeof(struct nfs_cache_array)); 578 memset(array, 0, sizeof(struct nfs_cache_array));
553 array->eof_index = -1; 579 array->eof_index = -1;
554 580
@@ -556,12 +582,19 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
556 if (!pages_ptr) 582 if (!pages_ptr)
557 goto out_release_array; 583 goto out_release_array;
558 do { 584 do {
585 unsigned int pglen;
559 status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); 586 status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode);
560 587
561 if (status < 0) 588 if (status < 0)
562 break; 589 break;
563 nfs_readdir_page_filler(desc, &entry, pages_ptr, page, array_size * PAGE_SIZE); 590 pglen = status;
564 } while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY); 591 status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, pglen);
592 if (status < 0) {
593 if (status == -ENOSPC)
594 status = 0;
595 break;
596 }
597 } while (array->eof_index < 0);
565 598
566 nfs_readdir_free_large_page(pages_ptr, pages, array_size); 599 nfs_readdir_free_large_page(pages_ptr, pages, array_size);
567out_release_array: 600out_release_array:
@@ -582,8 +615,10 @@ static
582int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) 615int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
583{ 616{
584 struct inode *inode = desc->file->f_path.dentry->d_inode; 617 struct inode *inode = desc->file->f_path.dentry->d_inode;
618 int ret;
585 619
586 if (nfs_readdir_xdr_to_array(desc, page, inode) < 0) 620 ret = nfs_readdir_xdr_to_array(desc, page, inode);
621 if (ret < 0)
587 goto error; 622 goto error;
588 SetPageUptodate(page); 623 SetPageUptodate(page);
589 624
@@ -595,7 +630,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
595 return 0; 630 return 0;
596 error: 631 error:
597 unlock_page(page); 632 unlock_page(page);
598 return -EIO; 633 return ret;
599} 634}
600 635
601static 636static
@@ -608,12 +643,8 @@ void cache_page_release(nfs_readdir_descriptor_t *desc)
608static 643static
609struct page *get_cache_page(nfs_readdir_descriptor_t *desc) 644struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
610{ 645{
611 struct page *page; 646 return read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping,
612 page = read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping,
613 desc->page_index, (filler_t *)nfs_readdir_filler, desc); 647 desc->page_index, (filler_t *)nfs_readdir_filler, desc);
614 if (IS_ERR(page))
615 desc->eof = 1;
616 return page;
617} 648}
618 649
619/* 650/*
@@ -639,8 +670,10 @@ int find_cache_page(nfs_readdir_descriptor_t *desc)
639static inline 670static inline
640int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) 671int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
641{ 672{
642 int res = -EAGAIN; 673 int res;
643 674
675 if (desc->page_index == 0)
676 desc->current_index = 0;
644 while (1) { 677 while (1) {
645 res = find_cache_page(desc); 678 res = find_cache_page(desc);
646 if (res != -EAGAIN) 679 if (res != -EAGAIN)
@@ -666,35 +699,36 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
666 int i = 0; 699 int i = 0;
667 int res = 0; 700 int res = 0;
668 struct nfs_cache_array *array = NULL; 701 struct nfs_cache_array *array = NULL;
669 unsigned int d_type = DT_UNKNOWN;
670 struct dentry *dentry = NULL;
671 702
672 array = nfs_readdir_get_array(desc->page); 703 array = nfs_readdir_get_array(desc->page);
704 if (IS_ERR(array)) {
705 res = PTR_ERR(array);
706 goto out;
707 }
673 708
674 for (i = desc->cache_entry_index; i < array->size; i++) { 709 for (i = desc->cache_entry_index; i < array->size; i++) {
675 d_type = DT_UNKNOWN; 710 struct nfs_cache_array_entry *ent;
676 711
677 res = filldir(dirent, array->array[i].string.name, 712 ent = &array->array[i];
678 array->array[i].string.len, file->f_pos, 713 if (filldir(dirent, ent->string.name, ent->string.len,
679 nfs_compat_user_ino64(array->array[i].ino), d_type); 714 file->f_pos, nfs_compat_user_ino64(ent->ino),
680 if (res < 0) 715 ent->d_type) < 0) {
716 desc->eof = 1;
681 break; 717 break;
718 }
682 file->f_pos++; 719 file->f_pos++;
683 desc->cache_entry_index = i; 720 desc->cache_entry_index = i;
684 if (i < (array->size-1)) 721 if (i < (array->size-1))
685 *desc->dir_cookie = array->array[i+1].cookie; 722 *desc->dir_cookie = array->array[i+1].cookie;
686 else 723 else
687 *desc->dir_cookie = array->last_cookie; 724 *desc->dir_cookie = array->last_cookie;
688 if (i == array->eof_index) {
689 desc->eof = 1;
690 break;
691 }
692 } 725 }
726 if (i == array->eof_index)
727 desc->eof = 1;
693 728
694 nfs_readdir_release_array(desc->page); 729 nfs_readdir_release_array(desc->page);
730out:
695 cache_page_release(desc); 731 cache_page_release(desc);
696 if (dentry != NULL)
697 dput(dentry);
698 dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", 732 dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
699 (unsigned long long)*desc->dir_cookie, res); 733 (unsigned long long)*desc->dir_cookie, res);
700 return res; 734 return res;
@@ -729,13 +763,13 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
729 goto out; 763 goto out;
730 } 764 }
731 765
732 if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
733 status = -EIO;
734 goto out_release;
735 }
736
737 desc->page_index = 0; 766 desc->page_index = 0;
738 desc->page = page; 767 desc->page = page;
768
769 status = nfs_readdir_xdr_to_array(desc, page, inode);
770 if (status < 0)
771 goto out_release;
772
739 status = nfs_do_filldir(desc, dirent, filldir); 773 status = nfs_do_filldir(desc, dirent, filldir);
740 774
741 out: 775 out:
@@ -786,14 +820,14 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
786 res = readdir_search_pagecache(desc); 820 res = readdir_search_pagecache(desc);
787 821
788 if (res == -EBADCOOKIE) { 822 if (res == -EBADCOOKIE) {
823 res = 0;
789 /* This means either end of directory */ 824 /* This means either end of directory */
790 if (*desc->dir_cookie && desc->eof == 0) { 825 if (*desc->dir_cookie && desc->eof == 0) {
791 /* Or that the server has 'lost' a cookie */ 826 /* Or that the server has 'lost' a cookie */
792 res = uncached_readdir(desc, dirent, filldir); 827 res = uncached_readdir(desc, dirent, filldir);
793 if (res >= 0) 828 if (res == 0)
794 continue; 829 continue;
795 } 830 }
796 res = 0;
797 break; 831 break;
798 } 832 }
799 if (res == -ETOOSMALL && desc->plus) { 833 if (res == -ETOOSMALL && desc->plus) {
@@ -808,10 +842,8 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
808 break; 842 break;
809 843
810 res = nfs_do_filldir(desc, dirent, filldir); 844 res = nfs_do_filldir(desc, dirent, filldir);
811 if (res < 0) { 845 if (res < 0)
812 res = 0;
813 break; 846 break;
814 }
815 } 847 }
816out: 848out:
817 nfs_unblock_sillyrename(dentry); 849 nfs_unblock_sillyrename(dentry);
@@ -1345,12 +1377,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
1345 res = NULL; 1377 res = NULL;
1346 goto out; 1378 goto out;
1347 /* This turned out not to be a regular file */ 1379 /* This turned out not to be a regular file */
1348 case -EISDIR:
1349 case -ENOTDIR: 1380 case -ENOTDIR:
1350 goto no_open; 1381 goto no_open;
1351 case -ELOOP: 1382 case -ELOOP:
1352 if (!(nd->intent.open.flags & O_NOFOLLOW)) 1383 if (!(nd->intent.open.flags & O_NOFOLLOW))
1353 goto no_open; 1384 goto no_open;
1385 /* case -EISDIR: */
1354 /* case -EINVAL: */ 1386 /* case -EINVAL: */
1355 default: 1387 default:
1356 res = ERR_CAST(inode); 1388 res = ERR_CAST(inode);