aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-06 13:09:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-06 13:09:38 -0400
commit2b3a8fd735f86ebeb2b9d061054003000c36b654 (patch)
tree209c969216b0f46315fc1f53a6c999a980d3ed15 /fs/nfs/dir.c
parent6f4c98e1c22c28e00b8f050cce895a6b74db15d1 (diff)
parent9581a4ae75517099bc87e1c43d1a8f35b55741b9 (diff)
Merge tag 'nfs-for-3.15-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include: - Stable fix for a use after free issue in the NFSv4.1 open code - Fix the SUNRPC bi-directional RPC code to account for TCP segmentation - Optimise usage of readdirplus when confronted with 'ls -l' situations - Soft mount bugfixes - NFS over RDMA bugfixes - NFSv4 close locking fixes - Various NFSv4.x client state management optimisations - Rename/unlink code cleanups" * tag 'nfs-for-3.15-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (28 commits) nfs: pass string length to pr_notice message about readdir loops NFSv4: Fix a use-after-free problem in open() SUNRPC: rpc_restart_call/rpc_restart_call_prepare should clear task->tk_status SUNRPC: Don't let rpc_delay() clobber non-timeout errors SUNRPC: Ensure call_connect_status() deals correctly with SOFTCONN tasks SUNRPC: Ensure call_status() deals correctly with SOFTCONN tasks NFSv4: Ensure we respect soft mount timeouts during trunking discovery NFSv4: Schedule recovery if nfs40_walk_client_list() is interrupted NFS: advertise only supported callback netids SUNRPC: remove KERN_INFO from dprintk() call sites SUNRPC: Fix large reads on NFS/RDMA NFS: Clean up: revert increase in READDIR RPC buffer max size SUNRPC: Ensure that call_bind times out correctly SUNRPC: Ensure that call_connect times out correctly nfs: emit a fsnotify_nameremove call in sillyrename codepath nfs: remove synchronous rename code nfs: convert nfs_rename to use async_rename infrastructure nfs: make nfs_async_rename non-static nfs: abstract out code needed to complete a sillyrename NFSv4: Clear the open state flags if the new stateid does not match ...
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 4a48fe4b84b6..d9f3d067cd15 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -69,21 +69,28 @@ const struct address_space_operations nfs_dir_aops = {
69 69
70static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, struct rpc_cred *cred) 70static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, struct rpc_cred *cred)
71{ 71{
72 struct nfs_inode *nfsi = NFS_I(dir);
72 struct nfs_open_dir_context *ctx; 73 struct nfs_open_dir_context *ctx;
73 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 74 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
74 if (ctx != NULL) { 75 if (ctx != NULL) {
75 ctx->duped = 0; 76 ctx->duped = 0;
76 ctx->attr_gencount = NFS_I(dir)->attr_gencount; 77 ctx->attr_gencount = nfsi->attr_gencount;
77 ctx->dir_cookie = 0; 78 ctx->dir_cookie = 0;
78 ctx->dup_cookie = 0; 79 ctx->dup_cookie = 0;
79 ctx->cred = get_rpccred(cred); 80 ctx->cred = get_rpccred(cred);
81 spin_lock(&dir->i_lock);
82 list_add(&ctx->list, &nfsi->open_files);
83 spin_unlock(&dir->i_lock);
80 return ctx; 84 return ctx;
81 } 85 }
82 return ERR_PTR(-ENOMEM); 86 return ERR_PTR(-ENOMEM);
83} 87}
84 88
85static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx) 89static void put_nfs_open_dir_context(struct inode *dir, struct nfs_open_dir_context *ctx)
86{ 90{
91 spin_lock(&dir->i_lock);
92 list_del(&ctx->list);
93 spin_unlock(&dir->i_lock);
87 put_rpccred(ctx->cred); 94 put_rpccred(ctx->cred);
88 kfree(ctx); 95 kfree(ctx);
89} 96}
@@ -126,7 +133,7 @@ out:
126static int 133static int
127nfs_closedir(struct inode *inode, struct file *filp) 134nfs_closedir(struct inode *inode, struct file *filp)
128{ 135{
129 put_nfs_open_dir_context(filp->private_data); 136 put_nfs_open_dir_context(filp->f_path.dentry->d_inode, filp->private_data);
130 return 0; 137 return 0;
131} 138}
132 139
@@ -306,10 +313,9 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
306 if (printk_ratelimit()) { 313 if (printk_ratelimit()) {
307 pr_notice("NFS: directory %pD2 contains a readdir loop." 314 pr_notice("NFS: directory %pD2 contains a readdir loop."
308 "Please contact your server vendor. " 315 "Please contact your server vendor. "
309 "The file: %s has duplicate cookie %llu\n", 316 "The file: %.*s has duplicate cookie %llu\n",
310 desc->file, 317 desc->file, array->array[i].string.len,
311 array->array[i].string.name, 318 array->array[i].string.name, *desc->dir_cookie);
312 *desc->dir_cookie);
313 } 319 }
314 status = -ELOOP; 320 status = -ELOOP;
315 goto out; 321 goto out;
@@ -437,6 +443,22 @@ void nfs_advise_use_readdirplus(struct inode *dir)
437 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags); 443 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags);
438} 444}
439 445
446/*
447 * This function is mainly for use by nfs_getattr().
448 *
449 * If this is an 'ls -l', we want to force use of readdirplus.
450 * Do this by checking if there is an active file descriptor
451 * and calling nfs_advise_use_readdirplus, then forcing a
452 * cache flush.
453 */
454void nfs_force_use_readdirplus(struct inode *dir)
455{
456 if (!list_empty(&NFS_I(dir)->open_files)) {
457 nfs_advise_use_readdirplus(dir);
458 nfs_zap_mapping(dir, dir->i_mapping);
459 }
460}
461
440static 462static
441void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) 463void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
442{ 464{
@@ -815,6 +837,17 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc)
815 goto out; 837 goto out;
816} 838}
817 839
840static bool nfs_dir_mapping_need_revalidate(struct inode *dir)
841{
842 struct nfs_inode *nfsi = NFS_I(dir);
843
844 if (nfs_attribute_cache_expired(dir))
845 return true;
846 if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
847 return true;
848 return false;
849}
850
818/* The file offset position represents the dirent entry number. A 851/* The file offset position represents the dirent entry number. A
819 last cookie cache takes care of the common case of reading the 852 last cookie cache takes care of the common case of reading the
820 whole directory. 853 whole directory.
@@ -847,7 +880,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
847 desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; 880 desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
848 881
849 nfs_block_sillyrename(dentry); 882 nfs_block_sillyrename(dentry);
850 if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) 883 if (ctx->pos == 0 || nfs_dir_mapping_need_revalidate(inode))
851 res = nfs_revalidate_mapping(inode, file->f_mapping); 884 res = nfs_revalidate_mapping(inode, file->f_mapping);
852 if (res < 0) 885 if (res < 0)
853 goto out; 886 goto out;
@@ -1911,6 +1944,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1911 struct inode *old_inode = old_dentry->d_inode; 1944 struct inode *old_inode = old_dentry->d_inode;
1912 struct inode *new_inode = new_dentry->d_inode; 1945 struct inode *new_inode = new_dentry->d_inode;
1913 struct dentry *dentry = NULL, *rehash = NULL; 1946 struct dentry *dentry = NULL, *rehash = NULL;
1947 struct rpc_task *task;
1914 int error = -EBUSY; 1948 int error = -EBUSY;
1915 1949
1916 dfprintk(VFS, "NFS: rename(%pd2 -> %pd2, ct=%d)\n", 1950 dfprintk(VFS, "NFS: rename(%pd2 -> %pd2, ct=%d)\n",
@@ -1958,8 +1992,16 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1958 if (new_inode != NULL) 1992 if (new_inode != NULL)
1959 NFS_PROTO(new_inode)->return_delegation(new_inode); 1993 NFS_PROTO(new_inode)->return_delegation(new_inode);
1960 1994
1961 error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, 1995 task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
1962 new_dir, &new_dentry->d_name); 1996 if (IS_ERR(task)) {
1997 error = PTR_ERR(task);
1998 goto out;
1999 }
2000
2001 error = rpc_wait_for_completion_task(task);
2002 if (error == 0)
2003 error = task->tk_status;
2004 rpc_put_task(task);
1963 nfs_mark_for_revalidate(old_inode); 2005 nfs_mark_for_revalidate(old_inode);
1964out: 2006out:
1965 if (rehash) 2007 if (rehash)