Commit 31602533 authored by Henrique Carvalho's avatar Henrique Carvalho Committed by Steve French
Browse files

smb: client: short-circuit negative lookups when parent dir is fully cached



When the parent directory has a valid and complete cached enumeration we
can assume that negative dentries are not present in the directory, thus
we can return without issuing a request.

This reduces traffic for common ENOENT when the directory entries are
cached.

Signed-off-by: default avatarHenrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 55580ad0
Loading
Loading
Loading
Loading
+42 −1
Original line number Diff line number Diff line
@@ -683,6 +683,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
	const char *full_path;
	void *page;
	int retry_count = 0;
	struct cached_fid *cfid = NULL;

	xid = get_xid();

@@ -722,6 +723,28 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		cifs_dbg(FYI, "non-NULL inode in lookup\n");
	} else {
		cifs_dbg(FYI, "NULL inode in lookup\n");

		/*
		 * We can only rely on negative dentries having the same
		 * spelling as the cached dirent if case insensitivity is
		 * forced on mount.
		 *
		 * XXX: if servers correctly announce Case Sensitivity Search
		 * on GetInfo of FileFSAttributeInformation, then we can take
		 * correct action even if case insensitive is not forced on
		 * mount.
		 */
		if (pTcon->nocase && !open_cached_dir_by_dentry(pTcon, direntry->d_parent, &cfid)) {
			/*
			 * dentry is negative and parent is fully cached:
			 * we can assume file does not exist
			 */
			if (cfid->dirents.is_valid) {
				close_cached_dir(cfid);
				goto out;
			}
			close_cached_dir(cfid);
		}
	}
	cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
		 full_path, d_inode(direntry));
@@ -755,6 +778,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		}
		newInode = ERR_PTR(rc);
	}

out:
	free_dentry_path(page);
	cifs_put_tlink(tlink);
	free_xid(xid);
@@ -765,7 +790,8 @@ static int
cifs_d_revalidate(struct inode *dir, const struct qstr *name,
		  struct dentry *direntry, unsigned int flags)
{
	struct inode *inode;
	struct inode *inode = NULL;
	struct cached_fid *cfid;
	int rc;

	if (flags & LOOKUP_RCU)
@@ -812,6 +838,21 @@ cifs_d_revalidate(struct inode *dir, const struct qstr *name,

			return 1;
		}
	} else {
		struct cifs_sb_info *cifs_sb = CIFS_SB(dir->i_sb);
		struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);

		if (!open_cached_dir_by_dentry(tcon, direntry->d_parent, &cfid)) {
			/*
			 * dentry is negative and parent is fully cached:
			 * we can assume file does not exist
			 */
			if (cfid->dirents.is_valid) {
				close_cached_dir(cfid);
				return 1;
			}
			close_cached_dir(cfid);
		}
	}

	/*