Skip to content

Commit 3160253

Browse files
hac-vsmfrench
authored andcommitted
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 <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 55580ad commit 3160253

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

fs/smb/client/dir.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
683683
const char *full_path;
684684
void *page;
685685
int retry_count = 0;
686+
struct cached_fid *cfid = NULL;
686687

687688
xid = get_xid();
688689

@@ -722,6 +723,28 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
722723
cifs_dbg(FYI, "non-NULL inode in lookup\n");
723724
} else {
724725
cifs_dbg(FYI, "NULL inode in lookup\n");
726+
727+
/*
728+
* We can only rely on negative dentries having the same
729+
* spelling as the cached dirent if case insensitivity is
730+
* forced on mount.
731+
*
732+
* XXX: if servers correctly announce Case Sensitivity Search
733+
* on GetInfo of FileFSAttributeInformation, then we can take
734+
* correct action even if case insensitive is not forced on
735+
* mount.
736+
*/
737+
if (pTcon->nocase && !open_cached_dir_by_dentry(pTcon, direntry->d_parent, &cfid)) {
738+
/*
739+
* dentry is negative and parent is fully cached:
740+
* we can assume file does not exist
741+
*/
742+
if (cfid->dirents.is_valid) {
743+
close_cached_dir(cfid);
744+
goto out;
745+
}
746+
close_cached_dir(cfid);
747+
}
725748
}
726749
cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
727750
full_path, d_inode(direntry));
@@ -755,6 +778,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
755778
}
756779
newInode = ERR_PTR(rc);
757780
}
781+
782+
out:
758783
free_dentry_path(page);
759784
cifs_put_tlink(tlink);
760785
free_xid(xid);
@@ -765,7 +790,8 @@ static int
765790
cifs_d_revalidate(struct inode *dir, const struct qstr *name,
766791
struct dentry *direntry, unsigned int flags)
767792
{
768-
struct inode *inode;
793+
struct inode *inode = NULL;
794+
struct cached_fid *cfid;
769795
int rc;
770796

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

813839
return 1;
814840
}
841+
} else {
842+
struct cifs_sb_info *cifs_sb = CIFS_SB(dir->i_sb);
843+
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
844+
845+
if (!open_cached_dir_by_dentry(tcon, direntry->d_parent, &cfid)) {
846+
/*
847+
* dentry is negative and parent is fully cached:
848+
* we can assume file does not exist
849+
*/
850+
if (cfid->dirents.is_valid) {
851+
close_cached_dir(cfid);
852+
return 1;
853+
}
854+
close_cached_dir(cfid);
855+
}
815856
}
816857

817858
/*

0 commit comments

Comments
 (0)