diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/dir.c | 33 | ||||
-rw-r--r-- | fs/nfs/inode.c | 2 |
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 | ||
477 | static | 477 | static |
478 | bool 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 | */ | ||
494 | static | ||
495 | void nfs_advise_use_readdirplus(struct inode *dir) | ||
496 | { | ||
497 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags); | ||
498 | } | ||
499 | |||
500 | static | ||
478 | void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | 501 | void 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) | |||
1156 | out_set_verifier: | 1179 | out_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 | |||
1314 | no_entry: | 1343 | no_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) { |