|
@@ -474,6 +474,29 @@ different:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static
|
|
|
+bool nfs_use_readdirplus(struct inode *dir, struct file *filp)
|
|
|
+{
|
|
|
+ if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS))
|
|
|
+ return false;
|
|
|
+ if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags))
|
|
|
+ return true;
|
|
|
+ if (filp->f_pos == 0)
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * This function is called by the lookup code to request the use of
|
|
|
+ * readdirplus to accelerate any future lookups in the same
|
|
|
+ * directory.
|
|
|
+ */
|
|
|
+static
|
|
|
+void nfs_advise_use_readdirplus(struct inode *dir)
|
|
|
+{
|
|
|
+ set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags);
|
|
|
+}
|
|
|
+
|
|
|
static
|
|
|
void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
|
|
|
{
|
|
@@ -874,7 +897,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|
|
desc->file = filp;
|
|
|
desc->dir_cookie = &dir_ctx->dir_cookie;
|
|
|
desc->decode = NFS_PROTO(inode)->decode_dirent;
|
|
|
- desc->plus = NFS_USE_READDIRPLUS(inode);
|
|
|
+ desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0;
|
|
|
|
|
|
nfs_block_sillyrename(dentry);
|
|
|
res = nfs_revalidate_mapping(inode, filp->f_mapping);
|
|
@@ -1114,7 +1137,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
|
|
|
if (!inode) {
|
|
|
if (nfs_neg_need_reval(dir, dentry, nd))
|
|
|
goto out_bad;
|
|
|
- goto out_valid;
|
|
|
+ goto out_valid_noent;
|
|
|
}
|
|
|
|
|
|
if (is_bad_inode(inode)) {
|
|
@@ -1156,6 +1179,9 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
|
|
|
out_set_verifier:
|
|
|
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
|
|
out_valid:
|
|
|
+ /* Success: notify readdir to use READDIRPLUS */
|
|
|
+ nfs_advise_use_readdirplus(dir);
|
|
|
+ out_valid_noent:
|
|
|
dput(parent);
|
|
|
dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n",
|
|
|
__func__, dentry->d_parent->d_name.name,
|
|
@@ -1311,6 +1337,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
|
|
|
if (IS_ERR(res))
|
|
|
goto out_unblock_sillyrename;
|
|
|
|
|
|
+ /* Success: notify readdir to use READDIRPLUS */
|
|
|
+ nfs_advise_use_readdirplus(dir);
|
|
|
+
|
|
|
no_entry:
|
|
|
res = d_materialise_unique(dentry, inode);
|
|
|
if (res != NULL) {
|