aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c142
-rw-r--r--fs/nfs/direct.c2
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/nfs/inode.c1
-rw-r--r--fs/nfs/internal.h9
-rw-r--r--fs/nfs/mount_clnt.c4
-rw-r--r--fs/nfs/nfs2xdr.c4
-rw-r--r--fs/nfs/nfs3xdr.c4
-rw-r--r--fs/nfs/nfs4proc.c9
-rw-r--r--fs/nfs/nfs4xdr.c6
-rw-r--r--fs/nfs/pagelist.c4
-rw-r--r--fs/nfs/read.c1
-rw-r--r--fs/nfs/super.c4
-rw-r--r--fs/nfs/write.c3
14 files changed, 108 insertions, 87 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 662df2a5fad5..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
@@ -162,6 +162,7 @@ struct nfs_cache_array_entry {
162 u64 cookie; 162 u64 cookie;
163 u64 ino; 163 u64 ino;
164 struct qstr string; 164 struct qstr string;
165 unsigned char d_type;
165}; 166};
166 167
167struct nfs_cache_array { 168struct nfs_cache_array {
@@ -171,14 +172,13 @@ struct nfs_cache_array {
171 struct nfs_cache_array_entry array[0]; 172 struct nfs_cache_array_entry array[0];
172}; 173};
173 174
174#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
175
176typedef __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);
177typedef struct { 176typedef struct {
178 struct file *file; 177 struct file *file;
179 struct page *page; 178 struct page *page;
180 unsigned long page_index; 179 unsigned long page_index;
181 u64 *dir_cookie; 180 u64 *dir_cookie;
181 u64 last_cookie;
182 loff_t current_index; 182 loff_t current_index;
183 decode_dirent_t decode; 183 decode_dirent_t decode;
184 184
@@ -214,17 +214,15 @@ void nfs_readdir_release_array(struct page *page)
214 * we are freeing strings created by nfs_add_to_readdir_array() 214 * we are freeing strings created by nfs_add_to_readdir_array()
215 */ 215 */
216static 216static
217int nfs_readdir_clear_array(struct page *page, gfp_t mask) 217void nfs_readdir_clear_array(struct page *page)
218{ 218{
219 struct nfs_cache_array *array = nfs_readdir_get_array(page); 219 struct nfs_cache_array *array;
220 int i; 220 int i;
221 221
222 if (IS_ERR(array)) 222 array = kmap_atomic(page, KM_USER0);
223 return PTR_ERR(array);
224 for (i = 0; i < array->size; i++) 223 for (i = 0; i < array->size; i++)
225 kfree(array->array[i].string.name); 224 kfree(array->array[i].string.name);
226 nfs_readdir_release_array(page); 225 kunmap_atomic(array, KM_USER0);
227 return 0;
228} 226}
229 227
230/* 228/*
@@ -257,19 +255,23 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
257 255
258 if (IS_ERR(array)) 256 if (IS_ERR(array))
259 return PTR_ERR(array); 257 return PTR_ERR(array);
258
259 cache_entry = &array->array[array->size];
260
261 /* Check that this entry lies within the page bounds */
260 ret = -ENOSPC; 262 ret = -ENOSPC;
261 if (array->size >= MAX_READDIR_ARRAY) 263 if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE)
262 goto out; 264 goto out;
263 265
264 cache_entry = &array->array[array->size];
265 cache_entry->cookie = entry->prev_cookie; 266 cache_entry->cookie = entry->prev_cookie;
266 cache_entry->ino = entry->ino; 267 cache_entry->ino = entry->ino;
268 cache_entry->d_type = entry->d_type;
267 ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); 269 ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
268 if (ret) 270 if (ret)
269 goto out; 271 goto out;
270 array->last_cookie = entry->cookie; 272 array->last_cookie = entry->cookie;
271 array->size++; 273 array->size++;
272 if (entry->eof == 1) 274 if (entry->eof != 0)
273 array->eof_index = array->size; 275 array->eof_index = array->size;
274out: 276out:
275 nfs_readdir_release_array(page); 277 nfs_readdir_release_array(page);
@@ -309,15 +311,14 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
309 for (i = 0; i < array->size; i++) { 311 for (i = 0; i < array->size; i++) {
310 if (array->array[i].cookie == *desc->dir_cookie) { 312 if (array->array[i].cookie == *desc->dir_cookie) {
311 desc->cache_entry_index = i; 313 desc->cache_entry_index = i;
312 status = 0; 314 return 0;
313 goto out;
314 } 315 }
315 } 316 }
316 if (i == array->eof_index) { 317 if (array->eof_index >= 0) {
317 desc->eof = 1;
318 status = -EBADCOOKIE; 318 status = -EBADCOOKIE;
319 if (*desc->dir_cookie == array->last_cookie)
320 desc->eof = 1;
319 } 321 }
320out:
321 return status; 322 return status;
322} 323}
323 324
@@ -325,10 +326,7 @@ static
325int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) 326int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
326{ 327{
327 struct nfs_cache_array *array; 328 struct nfs_cache_array *array;
328 int status = -EBADCOOKIE; 329 int status;
329
330 if (desc->dir_cookie == NULL)
331 goto out;
332 330
333 array = nfs_readdir_get_array(desc->page); 331 array = nfs_readdir_get_array(desc->page);
334 if (IS_ERR(array)) { 332 if (IS_ERR(array)) {
@@ -341,6 +339,10 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
341 else 339 else
342 status = nfs_readdir_search_for_cookie(array, desc); 340 status = nfs_readdir_search_for_cookie(array, desc);
343 341
342 if (status == -EAGAIN) {
343 desc->last_cookie = array->last_cookie;
344 desc->page_index++;
345 }
344 nfs_readdir_release_array(desc->page); 346 nfs_readdir_release_array(desc->page);
345out: 347out:
346 return status; 348 return status;
@@ -392,13 +394,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x
392static 394static
393int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) 395int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
394{ 396{
395 struct nfs_inode *node;
396 if (dentry->d_inode == NULL) 397 if (dentry->d_inode == NULL)
397 goto different; 398 goto different;
398 node = NFS_I(dentry->d_inode); 399 if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0)
399 if (node->fh.size != entry->fh->size)
400 goto different;
401 if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0)
402 goto different; 400 goto different;
403 return 1; 401 return 1;
404different: 402different:
@@ -466,8 +464,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
466 struct xdr_stream stream; 464 struct xdr_stream stream;
467 struct xdr_buf buf; 465 struct xdr_buf buf;
468 __be32 *ptr = xdr_page; 466 __be32 *ptr = xdr_page;
469 int status;
470 struct nfs_cache_array *array; 467 struct nfs_cache_array *array;
468 unsigned int count = 0;
469 int status;
471 470
472 buf.head->iov_base = xdr_page; 471 buf.head->iov_base = xdr_page;
473 buf.head->iov_len = buflen; 472 buf.head->iov_len = buflen;
@@ -488,7 +487,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
488 break; 487 break;
489 } 488 }
490 489
491 if (desc->plus == 1) 490 count++;
491
492 if (desc->plus != 0)
492 nfs_prime_dcache(desc->file->f_path.dentry, entry); 493 nfs_prime_dcache(desc->file->f_path.dentry, entry);
493 494
494 status = nfs_readdir_add_to_array(entry, page); 495 status = nfs_readdir_add_to_array(entry, page);
@@ -496,13 +497,14 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
496 break; 497 break;
497 } while (!entry->eof); 498 } while (!entry->eof);
498 499
499 if (status == -EBADCOOKIE && entry->eof) { 500 if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
500 array = nfs_readdir_get_array(page); 501 array = nfs_readdir_get_array(page);
501 if (!IS_ERR(array)) { 502 if (!IS_ERR(array)) {
502 array->eof_index = array->size; 503 array->eof_index = array->size;
503 status = 0; 504 status = 0;
504 nfs_readdir_release_array(page); 505 nfs_readdir_release_array(page);
505 } 506 } else
507 status = PTR_ERR(array);
506 } 508 }
507 return status; 509 return status;
508} 510}
@@ -560,7 +562,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
560 unsigned int array_size = ARRAY_SIZE(pages); 562 unsigned int array_size = ARRAY_SIZE(pages);
561 563
562 entry.prev_cookie = 0; 564 entry.prev_cookie = 0;
563 entry.cookie = *desc->dir_cookie; 565 entry.cookie = desc->last_cookie;
564 entry.eof = 0; 566 entry.eof = 0;
565 entry.fh = nfs_alloc_fhandle(); 567 entry.fh = nfs_alloc_fhandle();
566 entry.fattr = nfs_alloc_fattr(); 568 entry.fattr = nfs_alloc_fattr();
@@ -633,6 +635,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
633static 635static
634void cache_page_release(nfs_readdir_descriptor_t *desc) 636void cache_page_release(nfs_readdir_descriptor_t *desc)
635{ 637{
638 if (!desc->page->mapping)
639 nfs_readdir_clear_array(desc->page);
636 page_cache_release(desc->page); 640 page_cache_release(desc->page);
637 desc->page = NULL; 641 desc->page = NULL;
638} 642}
@@ -657,9 +661,8 @@ int find_cache_page(nfs_readdir_descriptor_t *desc)
657 return PTR_ERR(desc->page); 661 return PTR_ERR(desc->page);
658 662
659 res = nfs_readdir_search_array(desc); 663 res = nfs_readdir_search_array(desc);
660 if (res == 0) 664 if (res != 0)
661 return 0; 665 cache_page_release(desc);
662 cache_page_release(desc);
663 return res; 666 return res;
664} 667}
665 668
@@ -669,22 +672,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
669{ 672{
670 int res; 673 int res;
671 674
672 if (desc->page_index == 0) 675 if (desc->page_index == 0) {
673 desc->current_index = 0; 676 desc->current_index = 0;
674 while (1) { 677 desc->last_cookie = 0;
675 res = find_cache_page(desc);
676 if (res != -EAGAIN)
677 break;
678 desc->page_index++;
679 } 678 }
679 do {
680 res = find_cache_page(desc);
681 } while (res == -EAGAIN);
680 return res; 682 return res;
681} 683}
682 684
683static inline unsigned int dt_type(struct inode *inode)
684{
685 return (inode->i_mode >> 12) & 15;
686}
687
688/* 685/*
689 * 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...
690 */ 687 */
@@ -696,35 +693,35 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
696 int i = 0; 693 int i = 0;
697 int res = 0; 694 int res = 0;
698 struct nfs_cache_array *array = NULL; 695 struct nfs_cache_array *array = NULL;
699 unsigned int d_type = DT_UNKNOWN;
700 struct dentry *dentry = NULL;
701 696
702 array = nfs_readdir_get_array(desc->page); 697 array = nfs_readdir_get_array(desc->page);
703 if (IS_ERR(array)) 698 if (IS_ERR(array)) {
704 return PTR_ERR(array); 699 res = PTR_ERR(array);
700 goto out;
701 }
705 702
706 for (i = desc->cache_entry_index; i < array->size; i++) { 703 for (i = desc->cache_entry_index; i < array->size; i++) {
707 d_type = DT_UNKNOWN; 704 struct nfs_cache_array_entry *ent;
708 705
709 res = filldir(dirent, array->array[i].string.name, 706 ent = &array->array[i];
710 array->array[i].string.len, file->f_pos, 707 if (filldir(dirent, ent->string.name, ent->string.len,
711 nfs_compat_user_ino64(array->array[i].ino), d_type); 708 file->f_pos, nfs_compat_user_ino64(ent->ino),
712 if (res < 0) 709 ent->d_type) < 0) {
710 desc->eof = 1;
713 break; 711 break;
712 }
714 file->f_pos++; 713 file->f_pos++;
715 desc->cache_entry_index = i;
716 if (i < (array->size-1)) 714 if (i < (array->size-1))
717 *desc->dir_cookie = array->array[i+1].cookie; 715 *desc->dir_cookie = array->array[i+1].cookie;
718 else 716 else
719 *desc->dir_cookie = array->last_cookie; 717 *desc->dir_cookie = array->last_cookie;
720 } 718 }
721 if (i == array->eof_index) 719 if (array->eof_index >= 0)
722 desc->eof = 1; 720 desc->eof = 1;
723 721
724 nfs_readdir_release_array(desc->page); 722 nfs_readdir_release_array(desc->page);
723out:
725 cache_page_release(desc); 724 cache_page_release(desc);
726 if (dentry != NULL)
727 dput(dentry);
728 dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", 725 dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
729 (unsigned long long)*desc->dir_cookie, res); 726 (unsigned long long)*desc->dir_cookie, res);
730 return res; 727 return res;
@@ -759,13 +756,14 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
759 goto out; 756 goto out;
760 } 757 }
761 758
762 if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
763 status = -EIO;
764 goto out_release;
765 }
766
767 desc->page_index = 0; 759 desc->page_index = 0;
760 desc->last_cookie = *desc->dir_cookie;
768 desc->page = page; 761 desc->page = page;
762
763 status = nfs_readdir_xdr_to_array(desc, page, inode);
764 if (status < 0)
765 goto out_release;
766
769 status = nfs_do_filldir(desc, dirent, filldir); 767 status = nfs_do_filldir(desc, dirent, filldir);
770 768
771 out: 769 out:
@@ -787,7 +785,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
787 struct inode *inode = dentry->d_inode; 785 struct inode *inode = dentry->d_inode;
788 nfs_readdir_descriptor_t my_desc, 786 nfs_readdir_descriptor_t my_desc,
789 *desc = &my_desc; 787 *desc = &my_desc;
790 int res = -ENOMEM; 788 int res;
791 789
792 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", 790 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
793 dentry->d_parent->d_name.name, dentry->d_name.name, 791 dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -812,18 +810,18 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
812 if (res < 0) 810 if (res < 0)
813 goto out; 811 goto out;
814 812
815 while (desc->eof != 1) { 813 do {
816 res = readdir_search_pagecache(desc); 814 res = readdir_search_pagecache(desc);
817 815
818 if (res == -EBADCOOKIE) { 816 if (res == -EBADCOOKIE) {
817 res = 0;
819 /* This means either end of directory */ 818 /* This means either end of directory */
820 if (*desc->dir_cookie && desc->eof == 0) { 819 if (*desc->dir_cookie && desc->eof == 0) {
821 /* Or that the server has 'lost' a cookie */ 820 /* Or that the server has 'lost' a cookie */
822 res = uncached_readdir(desc, dirent, filldir); 821 res = uncached_readdir(desc, dirent, filldir);
823 if (res >= 0) 822 if (res == 0)
824 continue; 823 continue;
825 } 824 }
826 res = 0;
827 break; 825 break;
828 } 826 }
829 if (res == -ETOOSMALL && desc->plus) { 827 if (res == -ETOOSMALL && desc->plus) {
@@ -838,11 +836,9 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
838 break; 836 break;
839 837
840 res = nfs_do_filldir(desc, dirent, filldir); 838 res = nfs_do_filldir(desc, dirent, filldir);
841 if (res < 0) { 839 if (res < 0)
842 res = 0;
843 break; 840 break;
844 } 841 } while (!desc->eof);
845 }
846out: 842out:
847 nfs_unblock_sillyrename(dentry); 843 nfs_unblock_sillyrename(dentry);
848 if (res > 0) 844 if (res > 0)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 84d3c8b90206..e6ace0d93c71 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -867,7 +867,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
867 goto out; 867 goto out;
868 nfs_alloc_commit_data(dreq); 868 nfs_alloc_commit_data(dreq);
869 869
870 if (dreq->commit_data == NULL || count < wsize) 870 if (dreq->commit_data == NULL || count <= wsize)
871 sync = NFS_FILE_SYNC; 871 sync = NFS_FILE_SYNC;
872 872
873 dreq->inode = inode; 873 dreq->inode = inode;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 60677f9f1311..7bf029ef4084 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -693,6 +693,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
693{ 693{
694 struct inode *inode = filp->f_mapping->host; 694 struct inode *inode = filp->f_mapping->host;
695 int status = 0; 695 int status = 0;
696 unsigned int saved_type = fl->fl_type;
696 697
697 /* Try local locking first */ 698 /* Try local locking first */
698 posix_test_lock(filp, fl); 699 posix_test_lock(filp, fl);
@@ -700,6 +701,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
700 /* found a conflict */ 701 /* found a conflict */
701 goto out; 702 goto out;
702 } 703 }
704 fl->fl_type = saved_type;
703 705
704 if (nfs_have_delegation(inode, FMODE_READ)) 706 if (nfs_have_delegation(inode, FMODE_READ))
705 goto out_noconflict; 707 goto out_noconflict;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 314f57164602..e67e31c73416 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -289,6 +289,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
289 } else if (S_ISDIR(inode->i_mode)) { 289 } else if (S_ISDIR(inode->i_mode)) {
290 inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; 290 inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
291 inode->i_fop = &nfs_dir_operations; 291 inode->i_fop = &nfs_dir_operations;
292 inode->i_data.a_ops = &nfs_dir_aops;
292 if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) 293 if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
293 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); 294 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
294 /* Deal with crossing mountpoints */ 295 /* Deal with crossing mountpoints */
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index db08ff3ff454..e6356b750b77 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -362,6 +362,15 @@ unsigned int nfs_page_length(struct page *page)
362} 362}
363 363
364/* 364/*
365 * Convert a umode to a dirent->d_type
366 */
367static inline
368unsigned char nfs_umode_to_dtype(umode_t mode)
369{
370 return (mode >> 12) & 15;
371}
372
373/*
365 * Determine the number of pages in an array of length 'len' and 374 * Determine the number of pages in an array of length 'len' and
366 * with a base offset of 'base' 375 * with a base offset of 'base'
367 */ 376 */
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index eceafe74f473..4f981f1f6689 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -505,13 +505,13 @@ static struct rpc_procinfo mnt3_procedures[] = {
505 505
506static struct rpc_version mnt_version1 = { 506static struct rpc_version mnt_version1 = {
507 .number = 1, 507 .number = 1,
508 .nrprocs = 2, 508 .nrprocs = ARRAY_SIZE(mnt_procedures),
509 .procs = mnt_procedures, 509 .procs = mnt_procedures,
510}; 510};
511 511
512static struct rpc_version mnt_version3 = { 512static struct rpc_version mnt_version3 = {
513 .number = 3, 513 .number = 3,
514 .nrprocs = 2, 514 .nrprocs = ARRAY_SIZE(mnt3_procedures),
515 .procs = mnt3_procedures, 515 .procs = mnt3_procedures,
516}; 516};
517 517
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 2563f765c9b4..5914a1911c95 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -485,6 +485,8 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
485 entry->prev_cookie = entry->cookie; 485 entry->prev_cookie = entry->cookie;
486 entry->cookie = ntohl(*p++); 486 entry->cookie = ntohl(*p++);
487 487
488 entry->d_type = DT_UNKNOWN;
489
488 p = xdr_inline_peek(xdr, 8); 490 p = xdr_inline_peek(xdr, 8);
489 if (p != NULL) 491 if (p != NULL)
490 entry->eof = !p[0] && p[1]; 492 entry->eof = !p[0] && p[1];
@@ -495,7 +497,7 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
495 497
496out_overflow: 498out_overflow:
497 print_overflow_msg(__func__, xdr); 499 print_overflow_msg(__func__, xdr);
498 return ERR_PTR(-EIO); 500 return ERR_PTR(-EAGAIN);
499} 501}
500 502
501/* 503/*
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 748dc91a4a14..f6cc60f06dac 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -622,11 +622,13 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
622 entry->prev_cookie = entry->cookie; 622 entry->prev_cookie = entry->cookie;
623 p = xdr_decode_hyper(p, &entry->cookie); 623 p = xdr_decode_hyper(p, &entry->cookie);
624 624
625 entry->d_type = DT_UNKNOWN;
625 if (plus) { 626 if (plus) {
626 entry->fattr->valid = 0; 627 entry->fattr->valid = 0;
627 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr); 628 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
628 if (IS_ERR(p)) 629 if (IS_ERR(p))
629 goto out_overflow_exit; 630 goto out_overflow_exit;
631 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
630 /* In fact, a post_op_fh3: */ 632 /* In fact, a post_op_fh3: */
631 p = xdr_inline_decode(xdr, 4); 633 p = xdr_inline_decode(xdr, 4);
632 if (unlikely(!p)) 634 if (unlikely(!p))
@@ -656,7 +658,7 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
656out_overflow: 658out_overflow:
657 print_overflow_msg(__func__, xdr); 659 print_overflow_msg(__func__, xdr);
658out_overflow_exit: 660out_overflow_exit:
659 return ERR_PTR(-EIO); 661 return ERR_PTR(-EAGAIN);
660} 662}
661 663
662/* 664/*
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6a653ffd8e4e..4435e5e1f904 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3361,6 +3361,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
3361 ret = nfs_revalidate_inode(server, inode); 3361 ret = nfs_revalidate_inode(server, inode);
3362 if (ret < 0) 3362 if (ret < 0)
3363 return ret; 3363 return ret;
3364 if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
3365 nfs_zap_acl_cache(inode);
3364 ret = nfs4_read_cached_acl(inode, buf, buflen); 3366 ret = nfs4_read_cached_acl(inode, buf, buflen);
3365 if (ret != -ENOENT) 3367 if (ret != -ENOENT)
3366 return ret; 3368 return ret;
@@ -3389,6 +3391,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
3389 nfs_inode_return_delegation(inode); 3391 nfs_inode_return_delegation(inode);
3390 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); 3392 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
3391 ret = nfs4_call_sync(server, &msg, &arg, &res, 1); 3393 ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
3394 /*
3395 * Acl update can result in inode attribute update.
3396 * so mark the attribute cache invalid.
3397 */
3398 spin_lock(&inode->i_lock);
3399 NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
3400 spin_unlock(&inode->i_lock);
3392 nfs_access_zap_cache(inode); 3401 nfs_access_zap_cache(inode);
3393 nfs_zap_acl_cache(inode); 3402 nfs_zap_acl_cache(inode);
3394 return ret; 3403 return ret;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index b7a204ff6fe1..9f1826b012e6 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -6208,6 +6208,10 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6208 if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) 6208 if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
6209 entry->ino = entry->fattr->fileid; 6209 entry->ino = entry->fattr->fileid;
6210 6210
6211 entry->d_type = DT_UNKNOWN;
6212 if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
6213 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
6214
6211 if (verify_attr_len(xdr, p, len) < 0) 6215 if (verify_attr_len(xdr, p, len) < 0)
6212 goto out_overflow; 6216 goto out_overflow;
6213 6217
@@ -6221,7 +6225,7 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6221 6225
6222out_overflow: 6226out_overflow:
6223 print_overflow_msg(__func__, xdr); 6227 print_overflow_msg(__func__, xdr);
6224 return ERR_PTR(-EIO); 6228 return ERR_PTR(-EAGAIN);
6225} 6229}
6226 6230
6227/* 6231/*
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 137b549e63db..b68536cc9046 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -115,7 +115,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
115{ 115{
116 if (!nfs_lock_request_dontget(req)) 116 if (!nfs_lock_request_dontget(req))
117 return 0; 117 return 0;
118 if (req->wb_page != NULL) 118 if (test_bit(PG_MAPPED, &req->wb_flags))
119 radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); 119 radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
120 return 1; 120 return 1;
121} 121}
@@ -125,7 +125,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
125 */ 125 */
126void nfs_clear_page_tag_locked(struct nfs_page *req) 126void nfs_clear_page_tag_locked(struct nfs_page *req)
127{ 127{
128 if (req->wb_page != NULL) { 128 if (test_bit(PG_MAPPED, &req->wb_flags)) {
129 struct inode *inode = req->wb_context->path.dentry->d_inode; 129 struct inode *inode = req->wb_context->path.dentry->d_inode;
130 struct nfs_inode *nfsi = NFS_I(inode); 130 struct nfs_inode *nfsi = NFS_I(inode);
131 131
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index e4b62c6f5a6e..aedcaa7f291f 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -152,7 +152,6 @@ static void nfs_readpage_release(struct nfs_page *req)
152 (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), 152 (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
153 req->wb_bytes, 153 req->wb_bytes,
154 (long long)req_offset(req)); 154 (long long)req_offset(req));
155 nfs_clear_request(req);
156 nfs_release_request(req); 155 nfs_release_request(req);
157} 156}
158 157
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 3c045044fca2..4100630c9a5b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1069,12 +1069,10 @@ static int nfs_parse_mount_options(char *raw,
1069 mnt->flags |= NFS_MOUNT_VER3; 1069 mnt->flags |= NFS_MOUNT_VER3;
1070 mnt->version = 3; 1070 mnt->version = 3;
1071 break; 1071 break;
1072#ifdef CONFIG_NFS_V4
1073 case Opt_v4: 1072 case Opt_v4:
1074 mnt->flags &= ~NFS_MOUNT_VER3; 1073 mnt->flags &= ~NFS_MOUNT_VER3;
1075 mnt->version = 4; 1074 mnt->version = 4;
1076 break; 1075 break;
1077#endif
1078 case Opt_udp: 1076 case Opt_udp:
1079 mnt->flags &= ~NFS_MOUNT_TCP; 1077 mnt->flags &= ~NFS_MOUNT_TCP;
1080 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; 1078 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
@@ -1286,12 +1284,10 @@ static int nfs_parse_mount_options(char *raw,
1286 mnt->flags |= NFS_MOUNT_VER3; 1284 mnt->flags |= NFS_MOUNT_VER3;
1287 mnt->version = 3; 1285 mnt->version = 3;
1288 break; 1286 break;
1289#ifdef CONFIG_NFS_V4
1290 case NFS4_VERSION: 1287 case NFS4_VERSION:
1291 mnt->flags &= ~NFS_MOUNT_VER3; 1288 mnt->flags &= ~NFS_MOUNT_VER3;
1292 mnt->version = 4; 1289 mnt->version = 4;
1293 break; 1290 break;
1294#endif
1295 default: 1291 default:
1296 goto out_invalid_value; 1292 goto out_invalid_value;
1297 } 1293 }
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 4c14c17a5276..10d648ea128b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -390,6 +390,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
390 if (nfs_have_delegation(inode, FMODE_WRITE)) 390 if (nfs_have_delegation(inode, FMODE_WRITE))
391 nfsi->change_attr++; 391 nfsi->change_attr++;
392 } 392 }
393 set_bit(PG_MAPPED, &req->wb_flags);
393 SetPagePrivate(req->wb_page); 394 SetPagePrivate(req->wb_page);
394 set_page_private(req->wb_page, (unsigned long)req); 395 set_page_private(req->wb_page, (unsigned long)req);
395 nfsi->npages++; 396 nfsi->npages++;
@@ -415,6 +416,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
415 spin_lock(&inode->i_lock); 416 spin_lock(&inode->i_lock);
416 set_page_private(req->wb_page, 0); 417 set_page_private(req->wb_page, 0);
417 ClearPagePrivate(req->wb_page); 418 ClearPagePrivate(req->wb_page);
419 clear_bit(PG_MAPPED, &req->wb_flags);
418 radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); 420 radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
419 nfsi->npages--; 421 nfsi->npages--;
420 if (!nfsi->npages) { 422 if (!nfsi->npages) {
@@ -422,7 +424,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
422 iput(inode); 424 iput(inode);
423 } else 425 } else
424 spin_unlock(&inode->i_lock); 426 spin_unlock(&inode->i_lock);
425 nfs_clear_request(req);
426 nfs_release_request(req); 427 nfs_release_request(req);
427} 428}
428 429