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.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index be38b573495a..c8e48c26418b 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
@@ -437,6 +444,22 @@ void nfs_advise_use_readdirplus(struct inode *dir)
437 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags); 444 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags);
438} 445}
439 446
447/*
448 * This function is mainly for use by nfs_getattr().
449 *
450 * If this is an 'ls -l', we want to force use of readdirplus.
451 * Do this by checking if there is an active file descriptor
452 * and calling nfs_advise_use_readdirplus, then forcing a
453 * cache flush.
454 */
455void nfs_force_use_readdirplus(struct inode *dir)
456{
457 if (!list_empty(&NFS_I(dir)->open_files)) {
458 nfs_advise_use_readdirplus(dir);
459 nfs_zap_mapping(dir, dir->i_mapping);
460 }
461}
462
440static 463static
441void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) 464void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
442{ 465{
@@ -815,6 +838,17 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc)
815 goto out; 838 goto out;
816} 839}
817 840
841static bool nfs_dir_mapping_need_revalidate(struct inode *dir)
842{
843 struct nfs_inode *nfsi = NFS_I(dir);
844
845 if (nfs_attribute_cache_expired(dir))
846 return true;
847 if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
848 return true;
849 return false;
850}
851
818/* The file offset position represents the dirent entry number. A 852/* The file offset position represents the dirent entry number. A
819 last cookie cache takes care of the common case of reading the 853 last cookie cache takes care of the common case of reading the
820 whole directory. 854 whole directory.
@@ -847,7 +881,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
847 desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; 881 desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
848 882
849 nfs_block_sillyrename(dentry); 883 nfs_block_sillyrename(dentry);
850 if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) 884 if (ctx->pos == 0 || nfs_dir_mapping_need_revalidate(inode))
851 res = nfs_revalidate_mapping(inode, file->f_mapping); 885 res = nfs_revalidate_mapping(inode, file->f_mapping);
852 if (res < 0) 886 if (res < 0)
853 goto out; 887 goto out;