aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-11 18:11:56 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-11 18:11:56 -0500
commitb9d919a4ac6cf031b8e065f82ad8f1b0c9ed74b1 (patch)
tree3139b066396956fd3794df0cb1aa74dcc9f1cb28 /fs/nfs/dir.c
parent7c955fca3e1d8132982148267d9efcafae849bb6 (diff)
parent357f54d6b38252737116a6d631f6ac28ded018ed (diff)
Merge branch 'nfs-for-2.6.38' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'nfs-for-2.6.38' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (89 commits) NFS fix the setting of exchange id flag NFS: Don't use vm_map_ram() in readdir NFSv4: Ensure continued open and lockowner name uniqueness NFS: Move cl_delegations to the nfs_server struct NFS: Introduce nfs_detach_delegations() NFS: Move cl_state_owners and related fields to the nfs_server struct NFS: Allow walking nfs_client.cl_superblocks list outside client.c pnfs: layout roc code pnfs: update nfs4_callback_recallany to handle layouts pnfs: add CB_LAYOUTRECALL handling pnfs: CB_LAYOUTRECALL xdr code pnfs: change lo refcounting to atomic_t pnfs: check that partial LAYOUTGET return is ignored pnfs: add layout to client list before sending rpc pnfs: serialize LAYOUTGET(openstateid) pnfs: layoutget rpc code cleanup pnfs: change how lsegs are removed from layout list pnfs: change layout state seqlock to a spinlock pnfs: add prefix to struct pnfs_layout_hdr fields pnfs: add prefix to struct pnfs_layout_segment fields ...
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c72
1 files changed, 36 insertions, 36 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d33da530097..abe4f0c8dc5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -33,8 +33,8 @@
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>
37#include <linux/xattr.h>
38 38
39#include "delegation.h" 39#include "delegation.h"
40#include "iostat.h" 40#include "iostat.h"
@@ -125,9 +125,10 @@ const struct inode_operations nfs4_dir_inode_operations = {
125 .permission = nfs_permission, 125 .permission = nfs_permission,
126 .getattr = nfs_getattr, 126 .getattr = nfs_getattr,
127 .setattr = nfs_setattr, 127 .setattr = nfs_setattr,
128 .getxattr = nfs4_getxattr, 128 .getxattr = generic_getxattr,
129 .setxattr = nfs4_setxattr, 129 .setxattr = generic_setxattr,
130 .listxattr = nfs4_listxattr, 130 .listxattr = generic_listxattr,
131 .removexattr = generic_removexattr,
131}; 132};
132 133
133#endif /* CONFIG_NFS_V4 */ 134#endif /* CONFIG_NFS_V4 */
@@ -172,7 +173,7 @@ struct nfs_cache_array {
172 struct nfs_cache_array_entry array[0]; 173 struct nfs_cache_array_entry array[0];
173}; 174};
174 175
175typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); 176typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int);
176typedef struct { 177typedef struct {
177 struct file *file; 178 struct file *file;
178 struct page *page; 179 struct page *page;
@@ -378,14 +379,14 @@ error:
378 return error; 379 return error;
379} 380}
380 381
381/* Fill in an entry based on the xdr code stored in desc->page */ 382static int xdr_decode(nfs_readdir_descriptor_t *desc,
382static 383 struct nfs_entry *entry, struct xdr_stream *xdr)
383int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct xdr_stream *stream)
384{ 384{
385 __be32 *p = desc->decode(stream, entry, NFS_SERVER(desc->file->f_path.dentry->d_inode), desc->plus); 385 int error;
386 if (IS_ERR(p))
387 return PTR_ERR(p);
388 386
387 error = desc->decode(xdr, entry, desc->plus);
388 if (error)
389 return error;
389 entry->fattr->time_start = desc->timestamp; 390 entry->fattr->time_start = desc->timestamp;
390 entry->fattr->gencount = desc->gencount; 391 entry->fattr->gencount = desc->gencount;
391 return 0; 392 return 0;
@@ -459,25 +460,26 @@ out:
459/* Perform conversion from xdr to cache array */ 460/* Perform conversion from xdr to cache array */
460static 461static
461int 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,
462 void *xdr_page, struct page *page, unsigned int buflen) 463 struct page **xdr_pages, struct page *page, unsigned int buflen)
463{ 464{
464 struct xdr_stream stream; 465 struct xdr_stream stream;
465 struct xdr_buf buf; 466 struct xdr_buf buf = {
466 __be32 *ptr = xdr_page; 467 .pages = xdr_pages,
468 .page_len = buflen,
469 .buflen = buflen,
470 .len = buflen,
471 };
472 struct page *scratch;
467 struct nfs_cache_array *array; 473 struct nfs_cache_array *array;
468 unsigned int count = 0; 474 unsigned int count = 0;
469 int status; 475 int status;
470 476
471 buf.head->iov_base = xdr_page; 477 scratch = alloc_page(GFP_KERNEL);
472 buf.head->iov_len = buflen; 478 if (scratch == NULL)
473 buf.tail->iov_len = 0; 479 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 480
481 xdr_init_decode(&stream, &buf, NULL);
482 xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
481 483
482 do { 484 do {
483 status = xdr_decode(desc, entry, &stream); 485 status = xdr_decode(desc, entry, &stream);
@@ -506,6 +508,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
506 } else 508 } else
507 status = PTR_ERR(array); 509 status = PTR_ERR(array);
508 } 510 }
511
512 put_page(scratch);
509 return status; 513 return status;
510} 514}
511 515
@@ -521,7 +525,6 @@ static
521void nfs_readdir_free_large_page(void *ptr, struct page **pages, 525void nfs_readdir_free_large_page(void *ptr, struct page **pages,
522 unsigned int npages) 526 unsigned int npages)
523{ 527{
524 vm_unmap_ram(ptr, npages);
525 nfs_readdir_free_pagearray(pages, npages); 528 nfs_readdir_free_pagearray(pages, npages);
526} 529}
527 530
@@ -530,9 +533,8 @@ void nfs_readdir_free_large_page(void *ptr, struct page **pages,
530 * to nfs_readdir_free_large_page 533 * to nfs_readdir_free_large_page
531 */ 534 */
532static 535static
533void *nfs_readdir_large_page(struct page **pages, unsigned int npages) 536int nfs_readdir_large_page(struct page **pages, unsigned int npages)
534{ 537{
535 void *ptr;
536 unsigned int i; 538 unsigned int i;
537 539
538 for (i = 0; i < npages; i++) { 540 for (i = 0; i < npages; i++) {
@@ -541,13 +543,11 @@ void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
541 goto out_freepages; 543 goto out_freepages;
542 pages[i] = page; 544 pages[i] = page;
543 } 545 }
546 return 0;
544 547
545 ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL);
546 if (!IS_ERR_OR_NULL(ptr))
547 return ptr;
548out_freepages: 548out_freepages:
549 nfs_readdir_free_pagearray(pages, i); 549 nfs_readdir_free_pagearray(pages, i);
550 return NULL; 550 return -ENOMEM;
551} 551}
552 552
553static 553static
@@ -566,6 +566,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
566 entry.eof = 0; 566 entry.eof = 0;
567 entry.fh = nfs_alloc_fhandle(); 567 entry.fh = nfs_alloc_fhandle();
568 entry.fattr = nfs_alloc_fattr(); 568 entry.fattr = nfs_alloc_fattr();
569 entry.server = NFS_SERVER(inode);
569 if (entry.fh == NULL || entry.fattr == NULL) 570 if (entry.fh == NULL || entry.fattr == NULL)
570 goto out; 571 goto out;
571 572
@@ -577,8 +578,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
577 memset(array, 0, sizeof(struct nfs_cache_array)); 578 memset(array, 0, sizeof(struct nfs_cache_array));
578 array->eof_index = -1; 579 array->eof_index = -1;
579 580
580 pages_ptr = nfs_readdir_large_page(pages, array_size); 581 status = nfs_readdir_large_page(pages, array_size);
581 if (!pages_ptr) 582 if (status < 0)
582 goto out_release_array; 583 goto out_release_array;
583 do { 584 do {
584 unsigned int pglen; 585 unsigned int pglen;
@@ -587,7 +588,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
587 if (status < 0) 588 if (status < 0)
588 break; 589 break;
589 pglen = status; 590 pglen = status;
590 status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, pglen); 591 status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen);
591 if (status < 0) { 592 if (status < 0) {
592 if (status == -ENOSPC) 593 if (status == -ENOSPC)
593 status = 0; 594 status = 0;
@@ -1221,7 +1222,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
1221 goto out_unblock_sillyrename; 1222 goto out_unblock_sillyrename;
1222 } 1223 }
1223 inode = nfs_fhget(dentry->d_sb, fhandle, fattr); 1224 inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
1224 res = (struct dentry *)inode; 1225 res = ERR_CAST(inode);
1225 if (IS_ERR(res)) 1226 if (IS_ERR(res))
1226 goto out_unblock_sillyrename; 1227 goto out_unblock_sillyrename;
1227 1228
@@ -1355,8 +1356,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
1355 if (nd->flags & LOOKUP_CREATE) { 1356 if (nd->flags & LOOKUP_CREATE) {
1356 attr.ia_mode = nd->intent.open.create_mode; 1357 attr.ia_mode = nd->intent.open.create_mode;
1357 attr.ia_valid = ATTR_MODE; 1358 attr.ia_valid = ATTR_MODE;
1358 if (!IS_POSIXACL(dir)) 1359 attr.ia_mode &= ~current_umask();
1359 attr.ia_mode &= ~current_umask();
1360 } else { 1360 } else {
1361 open_flags &= ~(O_EXCL | O_CREAT); 1361 open_flags &= ~(O_EXCL | O_CREAT);
1362 attr.ia_valid = 0; 1362 attr.ia_valid = 0;