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: Henrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Henrique Carvalho 2025-09-08 22:04:23 -03:00 committed by Steve French
parent 55580ad027
commit 316025335a

View File

@ -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);
}
}
/*