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.c82
1 files changed, 36 insertions, 46 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8ea4a4180a87..996dd8989a91 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -57,7 +57,7 @@ static int nfs_rename(struct inode *, struct dentry *,
57 struct inode *, struct dentry *); 57 struct inode *, struct dentry *);
58static int nfs_fsync_dir(struct file *, int); 58static int nfs_fsync_dir(struct file *, int);
59static loff_t nfs_llseek_dir(struct file *, loff_t, int); 59static loff_t nfs_llseek_dir(struct file *, loff_t, int);
60static int nfs_readdir_clear_array(struct page*, gfp_t); 60static void nfs_readdir_clear_array(struct page*);
61 61
62const struct file_operations nfs_dir_operations = { 62const struct file_operations nfs_dir_operations = {
63 .llseek = nfs_llseek_dir, 63 .llseek = nfs_llseek_dir,
@@ -83,8 +83,8 @@ const struct inode_operations nfs_dir_inode_operations = {
83 .setattr = nfs_setattr, 83 .setattr = nfs_setattr,
84}; 84};
85 85
86const struct address_space_operations nfs_dir_addr_space_ops = { 86const struct address_space_operations nfs_dir_aops = {
87 .releasepage = nfs_readdir_clear_array, 87 .freepage = nfs_readdir_clear_array,
88}; 88};
89 89
90#ifdef CONFIG_NFS_V3 90#ifdef CONFIG_NFS_V3
@@ -178,6 +178,7 @@ typedef struct {
178 struct page *page; 178 struct page *page;
179 unsigned long page_index; 179 unsigned long page_index;
180 u64 *dir_cookie; 180 u64 *dir_cookie;
181 u64 last_cookie;
181 loff_t current_index; 182 loff_t current_index;
182 decode_dirent_t decode; 183 decode_dirent_t decode;
183 184
@@ -213,17 +214,15 @@ void nfs_readdir_release_array(struct page *page)
213 * we are freeing strings created by nfs_add_to_readdir_array() 214 * we are freeing strings created by nfs_add_to_readdir_array()
214 */ 215 */
215static 216static
216int nfs_readdir_clear_array(struct page *page, gfp_t mask) 217void nfs_readdir_clear_array(struct page *page)
217{ 218{
218 struct nfs_cache_array *array = nfs_readdir_get_array(page); 219 struct nfs_cache_array *array;
219 int i; 220 int i;
220 221
221 if (IS_ERR(array)) 222 array = kmap_atomic(page, KM_USER0);
222 return PTR_ERR(array);
223 for (i = 0; i < array->size; i++) 223 for (i = 0; i < array->size; i++)
224 kfree(array->array[i].string.name); 224 kfree(array->array[i].string.name);
225 nfs_readdir_release_array(page); 225 kunmap_atomic(array, KM_USER0);
226 return 0;
227} 226}
228 227
229/* 228/*
@@ -272,7 +271,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
272 goto out; 271 goto out;
273 array->last_cookie = entry->cookie; 272 array->last_cookie = entry->cookie;
274 array->size++; 273 array->size++;
275 if (entry->eof == 1) 274 if (entry->eof != 0)
276 array->eof_index = array->size; 275 array->eof_index = array->size;
277out: 276out:
278 nfs_readdir_release_array(page); 277 nfs_readdir_release_array(page);
@@ -312,15 +311,14 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
312 for (i = 0; i < array->size; i++) { 311 for (i = 0; i < array->size; i++) {
313 if (array->array[i].cookie == *desc->dir_cookie) { 312 if (array->array[i].cookie == *desc->dir_cookie) {
314 desc->cache_entry_index = i; 313 desc->cache_entry_index = i;
315 status = 0; 314 return 0;
316 goto out;
317 } 315 }
318 } 316 }
319 if (i == array->eof_index) { 317 if (array->eof_index >= 0) {
320 desc->eof = 1;
321 status = -EBADCOOKIE; 318 status = -EBADCOOKIE;
319 if (*desc->dir_cookie == array->last_cookie)
320 desc->eof = 1;
322 } 321 }
323out:
324 return status; 322 return status;
325} 323}
326 324
@@ -328,10 +326,7 @@ static
328int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) 326int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
329{ 327{
330 struct nfs_cache_array *array; 328 struct nfs_cache_array *array;
331 int status = -EBADCOOKIE; 329 int status;
332
333 if (desc->dir_cookie == NULL)
334 goto out;
335 330
336 array = nfs_readdir_get_array(desc->page); 331 array = nfs_readdir_get_array(desc->page);
337 if (IS_ERR(array)) { 332 if (IS_ERR(array)) {
@@ -344,6 +339,10 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
344 else 339 else
345 status = nfs_readdir_search_for_cookie(array, desc); 340 status = nfs_readdir_search_for_cookie(array, desc);
346 341
342 if (status == -EAGAIN) {
343 desc->last_cookie = array->last_cookie;
344 desc->page_index++;
345 }
347 nfs_readdir_release_array(desc->page); 346 nfs_readdir_release_array(desc->page);
348out: 347out:
349 return status; 348 return status;
@@ -395,13 +394,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x
395static 394static
396int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) 395int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
397{ 396{
398 struct nfs_inode *node;
399 if (dentry->d_inode == NULL) 397 if (dentry->d_inode == NULL)
400 goto different; 398 goto different;
401 node = NFS_I(dentry->d_inode); 399 if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0)
402 if (node->fh.size != entry->fh->size)
403 goto different;
404 if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0)
405 goto different; 400 goto different;
406 return 1; 401 return 1;
407different: 402different:
@@ -494,7 +489,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
494 489
495 count++; 490 count++;
496 491
497 if (desc->plus == 1) 492 if (desc->plus != 0)
498 nfs_prime_dcache(desc->file->f_path.dentry, entry); 493 nfs_prime_dcache(desc->file->f_path.dentry, entry);
499 494
500 status = nfs_readdir_add_to_array(entry, page); 495 status = nfs_readdir_add_to_array(entry, page);
@@ -502,7 +497,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
502 break; 497 break;
503 } while (!entry->eof); 498 } while (!entry->eof);
504 499
505 if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) { 500 if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
506 array = nfs_readdir_get_array(page); 501 array = nfs_readdir_get_array(page);
507 if (!IS_ERR(array)) { 502 if (!IS_ERR(array)) {
508 array->eof_index = array->size; 503 array->eof_index = array->size;
@@ -567,7 +562,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
567 unsigned int array_size = ARRAY_SIZE(pages); 562 unsigned int array_size = ARRAY_SIZE(pages);
568 563
569 entry.prev_cookie = 0; 564 entry.prev_cookie = 0;
570 entry.cookie = *desc->dir_cookie; 565 entry.cookie = desc->last_cookie;
571 entry.eof = 0; 566 entry.eof = 0;
572 entry.fh = nfs_alloc_fhandle(); 567 entry.fh = nfs_alloc_fhandle();
573 entry.fattr = nfs_alloc_fattr(); 568 entry.fattr = nfs_alloc_fattr();
@@ -640,6 +635,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
640static 635static
641void cache_page_release(nfs_readdir_descriptor_t *desc) 636void cache_page_release(nfs_readdir_descriptor_t *desc)
642{ 637{
638 if (!desc->page->mapping)
639 nfs_readdir_clear_array(desc->page);
643 page_cache_release(desc->page); 640 page_cache_release(desc->page);
644 desc->page = NULL; 641 desc->page = NULL;
645} 642}
@@ -664,9 +661,8 @@ int find_cache_page(nfs_readdir_descriptor_t *desc)
664 return PTR_ERR(desc->page); 661 return PTR_ERR(desc->page);
665 662
666 res = nfs_readdir_search_array(desc); 663 res = nfs_readdir_search_array(desc);
667 if (res == 0) 664 if (res != 0)
668 return 0; 665 cache_page_release(desc);
669 cache_page_release(desc);
670 return res; 666 return res;
671} 667}
672 668
@@ -676,22 +672,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
676{ 672{
677 int res; 673 int res;
678 674
679 if (desc->page_index == 0) 675 if (desc->page_index == 0) {
680 desc->current_index = 0; 676 desc->current_index = 0;
681 while (1) { 677 desc->last_cookie = 0;
682 res = find_cache_page(desc);
683 if (res != -EAGAIN)
684 break;
685 desc->page_index++;
686 } 678 }
679 do {
680 res = find_cache_page(desc);
681 } while (res == -EAGAIN);
687 return res; 682 return res;
688} 683}
689 684
690static inline unsigned int dt_type(struct inode *inode)
691{
692 return (inode->i_mode >> 12) & 15;
693}
694
695/* 685/*
696 * Once we've found the start of the dirent within a page: fill 'er up... 686 * Once we've found the start of the dirent within a page: fill 'er up...
697 */ 687 */
@@ -721,13 +711,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
721 break; 711 break;
722 } 712 }
723 file->f_pos++; 713 file->f_pos++;
724 desc->cache_entry_index = i;
725 if (i < (array->size-1)) 714 if (i < (array->size-1))
726 *desc->dir_cookie = array->array[i+1].cookie; 715 *desc->dir_cookie = array->array[i+1].cookie;
727 else 716 else
728 *desc->dir_cookie = array->last_cookie; 717 *desc->dir_cookie = array->last_cookie;
729 } 718 }
730 if (i == array->eof_index) 719 if (array->eof_index >= 0)
731 desc->eof = 1; 720 desc->eof = 1;
732 721
733 nfs_readdir_release_array(desc->page); 722 nfs_readdir_release_array(desc->page);
@@ -768,6 +757,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
768 } 757 }
769 758
770 desc->page_index = 0; 759 desc->page_index = 0;
760 desc->last_cookie = *desc->dir_cookie;
771 desc->page = page; 761 desc->page = page;
772 762
773 status = nfs_readdir_xdr_to_array(desc, page, inode); 763 status = nfs_readdir_xdr_to_array(desc, page, inode);
@@ -795,7 +785,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
795 struct inode *inode = dentry->d_inode; 785 struct inode *inode = dentry->d_inode;
796 nfs_readdir_descriptor_t my_desc, 786 nfs_readdir_descriptor_t my_desc,
797 *desc = &my_desc; 787 *desc = &my_desc;
798 int res = -ENOMEM; 788 int res;
799 789
800 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", 790 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
801 dentry->d_parent->d_name.name, dentry->d_name.name, 791 dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -820,7 +810,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
820 if (res < 0) 810 if (res < 0)
821 goto out; 811 goto out;
822 812
823 while (desc->eof != 1) { 813 do {
824 res = readdir_search_pagecache(desc); 814 res = readdir_search_pagecache(desc);
825 815
826 if (res == -EBADCOOKIE) { 816 if (res == -EBADCOOKIE) {
@@ -848,7 +838,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
848 res = nfs_do_filldir(desc, dirent, filldir); 838 res = nfs_do_filldir(desc, dirent, filldir);
849 if (res < 0) 839 if (res < 0)
850 break; 840 break;
851 } 841 } while (!desc->eof);
852out: 842out:
853 nfs_unblock_sillyrename(dentry); 843 nfs_unblock_sillyrename(dentry);
854 if (res > 0) 844 if (res > 0)