Skip to content

Commit 589f1e8

Browse files
bharathsm-mspopcornmix
authored andcommitted
smb: improve directory cache reuse for readdir operations
commit 72dd796 upstream. Currently, cached directory contents were not reused across subsequent 'ls' operations because the cache validity check relied on comparing the ctx pointer, which changes with each readdir invocation. As a result, the cached dir entries was not marked as valid and the cache was not utilized for subsequent 'ls' operations. This change uses the file pointer, which remains consistent across all readdir calls for a given directory instance, to associate and validate the cache. As a result, cached directory contents can now be correctly reused, improving performance for repeated directory listings. Performance gains with local windows SMB server: Without the patch and default actimeo=1: 1000 directory enumeration operations on dir with 10k files took 135.0s With this patch and actimeo=0: 1000 directory enumeration operations on dir with 10k files took just 5.1s Signed-off-by: Bharath SM <bharathsm@microsoft.com> Reviewed-by: Shyam Prasad N <sprasad@microsoft.com> Cc: stable@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 796066f commit 589f1e8

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

fs/smb/client/cached_dir.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ struct cached_dirent {
2121
struct cached_dirents {
2222
bool is_valid:1;
2323
bool is_failed:1;
24-
struct dir_context *ctx; /*
25-
* Only used to make sure we only take entries
26-
* from a single context. Never dereferenced.
27-
*/
24+
struct file *file; /*
25+
* Used to associate the cache with a single
26+
* open file instance.
27+
*/
2828
struct mutex de_mutex;
2929
int pos; /* Expected ctx->pos */
3030
struct list_head entries;

fs/smb/client/readdir.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -850,9 +850,9 @@ static bool emit_cached_dirents(struct cached_dirents *cde,
850850
}
851851

852852
static void update_cached_dirents_count(struct cached_dirents *cde,
853-
struct dir_context *ctx)
853+
struct file *file)
854854
{
855-
if (cde->ctx != ctx)
855+
if (cde->file != file)
856856
return;
857857
if (cde->is_valid || cde->is_failed)
858858
return;
@@ -861,9 +861,9 @@ static void update_cached_dirents_count(struct cached_dirents *cde,
861861
}
862862

863863
static void finished_cached_dirents_count(struct cached_dirents *cde,
864-
struct dir_context *ctx)
864+
struct dir_context *ctx, struct file *file)
865865
{
866-
if (cde->ctx != ctx)
866+
if (cde->file != file)
867867
return;
868868
if (cde->is_valid || cde->is_failed)
869869
return;
@@ -876,11 +876,12 @@ static void finished_cached_dirents_count(struct cached_dirents *cde,
876876
static void add_cached_dirent(struct cached_dirents *cde,
877877
struct dir_context *ctx,
878878
const char *name, int namelen,
879-
struct cifs_fattr *fattr)
879+
struct cifs_fattr *fattr,
880+
struct file *file)
880881
{
881882
struct cached_dirent *de;
882883

883-
if (cde->ctx != ctx)
884+
if (cde->file != file)
884885
return;
885886
if (cde->is_valid || cde->is_failed)
886887
return;
@@ -910,7 +911,8 @@ static void add_cached_dirent(struct cached_dirents *cde,
910911
static bool cifs_dir_emit(struct dir_context *ctx,
911912
const char *name, int namelen,
912913
struct cifs_fattr *fattr,
913-
struct cached_fid *cfid)
914+
struct cached_fid *cfid,
915+
struct file *file)
914916
{
915917
bool rc;
916918
ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
@@ -922,7 +924,7 @@ static bool cifs_dir_emit(struct dir_context *ctx,
922924
if (cfid) {
923925
mutex_lock(&cfid->dirents.de_mutex);
924926
add_cached_dirent(&cfid->dirents, ctx, name, namelen,
925-
fattr);
927+
fattr, file);
926928
mutex_unlock(&cfid->dirents.de_mutex);
927929
}
928930

@@ -1022,7 +1024,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
10221024
cifs_prime_dcache(file_dentry(file), &name, &fattr);
10231025

10241026
return !cifs_dir_emit(ctx, name.name, name.len,
1025-
&fattr, cfid);
1027+
&fattr, cfid, file);
10261028
}
10271029

10281030

@@ -1073,8 +1075,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
10731075
* we need to initialize scanning and storing the
10741076
* directory content.
10751077
*/
1076-
if (ctx->pos == 0 && cfid->dirents.ctx == NULL) {
1077-
cfid->dirents.ctx = ctx;
1078+
if (ctx->pos == 0 && cfid->dirents.file == NULL) {
1079+
cfid->dirents.file = file;
10781080
cfid->dirents.pos = 2;
10791081
}
10801082
/*
@@ -1142,7 +1144,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
11421144
} else {
11431145
if (cfid) {
11441146
mutex_lock(&cfid->dirents.de_mutex);
1145-
finished_cached_dirents_count(&cfid->dirents, ctx);
1147+
finished_cached_dirents_count(&cfid->dirents, ctx, file);
11461148
mutex_unlock(&cfid->dirents.de_mutex);
11471149
}
11481150
cifs_dbg(FYI, "Could not find entry\n");
@@ -1183,7 +1185,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
11831185
ctx->pos++;
11841186
if (cfid) {
11851187
mutex_lock(&cfid->dirents.de_mutex);
1186-
update_cached_dirents_count(&cfid->dirents, ctx);
1188+
update_cached_dirents_count(&cfid->dirents, file);
11871189
mutex_unlock(&cfid->dirents.de_mutex);
11881190
}
11891191

0 commit comments

Comments
 (0)