diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 42 |
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 | ||
70 | static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, struct rpc_cred *cred) | 70 | static 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 | ||
85 | static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx) | 89 | static 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: | |||
126 | static int | 133 | static int |
127 | nfs_closedir(struct inode *inode, struct file *filp) | 134 | nfs_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 | */ | ||
455 | void 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 | |||
440 | static | 463 | static |
441 | void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | 464 | void 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 | ||
841 | static 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; |