aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/dir.c33
-rw-r--r--fs/nfs/inode.c2
2 files changed, 31 insertions, 4 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 82b42e2ea65..d0884c0d946 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -475,6 +475,29 @@ different:
475} 475}
476 476
477static 477static
478bool nfs_use_readdirplus(struct inode *dir, struct file *filp)
479{
480 if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS))
481 return false;
482 if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags))
483 return true;
484 if (filp->f_pos == 0)
485 return true;
486 return false;
487}
488
489/*
490 * This function is called by the lookup code to request the use of
491 * readdirplus to accelerate any future lookups in the same
492 * directory.
493 */
494static
495void nfs_advise_use_readdirplus(struct inode *dir)
496{
497 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags);
498}
499
500static
478void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) 501void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
479{ 502{
480 struct qstr filename = { 503 struct qstr filename = {
@@ -874,7 +897,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
874 desc->file = filp; 897 desc->file = filp;
875 desc->dir_cookie = &dir_ctx->dir_cookie; 898 desc->dir_cookie = &dir_ctx->dir_cookie;
876 desc->decode = NFS_PROTO(inode)->decode_dirent; 899 desc->decode = NFS_PROTO(inode)->decode_dirent;
877 desc->plus = NFS_USE_READDIRPLUS(inode); 900 desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0;
878 901
879 nfs_block_sillyrename(dentry); 902 nfs_block_sillyrename(dentry);
880 res = nfs_revalidate_mapping(inode, filp->f_mapping); 903 res = nfs_revalidate_mapping(inode, filp->f_mapping);
@@ -1114,7 +1137,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
1114 if (!inode) { 1137 if (!inode) {
1115 if (nfs_neg_need_reval(dir, dentry, nd)) 1138 if (nfs_neg_need_reval(dir, dentry, nd))
1116 goto out_bad; 1139 goto out_bad;
1117 goto out_valid; 1140 goto out_valid_noent;
1118 } 1141 }
1119 1142
1120 if (is_bad_inode(inode)) { 1143 if (is_bad_inode(inode)) {
@@ -1156,6 +1179,9 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
1156out_set_verifier: 1179out_set_verifier:
1157 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1180 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1158 out_valid: 1181 out_valid:
1182 /* Success: notify readdir to use READDIRPLUS */
1183 nfs_advise_use_readdirplus(dir);
1184 out_valid_noent:
1159 dput(parent); 1185 dput(parent);
1160 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n", 1186 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n",
1161 __func__, dentry->d_parent->d_name.name, 1187 __func__, dentry->d_parent->d_name.name,
@@ -1311,6 +1337,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
1311 if (IS_ERR(res)) 1337 if (IS_ERR(res))
1312 goto out_unblock_sillyrename; 1338 goto out_unblock_sillyrename;
1313 1339
1340 /* Success: notify readdir to use READDIRPLUS */
1341 nfs_advise_use_readdirplus(dir);
1342
1314no_entry: 1343no_entry:
1315 res = d_materialise_unique(dentry, inode); 1344 res = d_materialise_unique(dentry, inode);
1316 if (res != NULL) { 1345 if (res != NULL) {
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 0d53113207e..9f17cd19e71 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -298,8 +298,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
298 inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; 298 inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
299 inode->i_fop = &nfs_dir_operations; 299 inode->i_fop = &nfs_dir_operations;
300 inode->i_data.a_ops = &nfs_dir_aops; 300 inode->i_data.a_ops = &nfs_dir_aops;
301 if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
302 set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
303 /* Deal with crossing mountpoints */ 301 /* Deal with crossing mountpoints */
304 if (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT || 302 if (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT ||
305 fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { 303 fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {