Skip to content

Commit 72dd796

Browse files
bharathsm-msSteve French
authored andcommitted
smb: improve directory cache reuse for readdir operations
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 <[email protected]> Reviewed-by: Shyam Prasad N <[email protected]> Cc: [email protected] Signed-off-by: Steve French <[email protected]>
1 parent b64af6b commit 72dd796

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
@@ -851,9 +851,9 @@ static bool emit_cached_dirents(struct cached_dirents *cde,
851851
}
852852

853853
static void update_cached_dirents_count(struct cached_dirents *cde,
854-
struct dir_context *ctx)
854+
struct file *file)
855855
{
856-
if (cde->ctx != ctx)
856+
if (cde->file != file)
857857
return;
858858
if (cde->is_valid || cde->is_failed)
859859
return;
@@ -862,9 +862,9 @@ static void update_cached_dirents_count(struct cached_dirents *cde,
862862
}
863863

864864
static void finished_cached_dirents_count(struct cached_dirents *cde,
865-
struct dir_context *ctx)
865+
struct dir_context *ctx, struct file *file)
866866
{
867-
if (cde->ctx != ctx)
867+
if (cde->file != file)
868868
return;
869869
if (cde->is_valid || cde->is_failed)
870870
return;
@@ -877,11 +877,12 @@ static void finished_cached_dirents_count(struct cached_dirents *cde,
877877
static void add_cached_dirent(struct cached_dirents *cde,
878878
struct dir_context *ctx,
879879
const char *name, int namelen,
880-
struct cifs_fattr *fattr)
880+
struct cifs_fattr *fattr,
881+
struct file *file)
881882
{
882883
struct cached_dirent *de;
883884

884-
if (cde->ctx != ctx)
885+
if (cde->file != file)
885886
return;
886887
if (cde->is_valid || cde->is_failed)
887888
return;
@@ -911,7 +912,8 @@ static void add_cached_dirent(struct cached_dirents *cde,
911912
static bool cifs_dir_emit(struct dir_context *ctx,
912913
const char *name, int namelen,
913914
struct cifs_fattr *fattr,
914-
struct cached_fid *cfid)
915+
struct cached_fid *cfid,
916+
struct file *file)
915917
{
916918
bool rc;
917919
ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
@@ -923,7 +925,7 @@ static bool cifs_dir_emit(struct dir_context *ctx,
923925
if (cfid) {
924926
mutex_lock(&cfid->dirents.de_mutex);
925927
add_cached_dirent(&cfid->dirents, ctx, name, namelen,
926-
fattr);
928+
fattr, file);
927929
mutex_unlock(&cfid->dirents.de_mutex);
928930
}
929931

@@ -1023,7 +1025,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
10231025
cifs_prime_dcache(file_dentry(file), &name, &fattr);
10241026

10251027
return !cifs_dir_emit(ctx, name.name, name.len,
1026-
&fattr, cfid);
1028+
&fattr, cfid, file);
10271029
}
10281030

10291031

@@ -1074,8 +1076,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
10741076
* we need to initialize scanning and storing the
10751077
* directory content.
10761078
*/
1077-
if (ctx->pos == 0 && cfid->dirents.ctx == NULL) {
1078-
cfid->dirents.ctx = ctx;
1079+
if (ctx->pos == 0 && cfid->dirents.file == NULL) {
1080+
cfid->dirents.file = file;
10791081
cfid->dirents.pos = 2;
10801082
}
10811083
/*
@@ -1143,7 +1145,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
11431145
} else {
11441146
if (cfid) {
11451147
mutex_lock(&cfid->dirents.de_mutex);
1146-
finished_cached_dirents_count(&cfid->dirents, ctx);
1148+
finished_cached_dirents_count(&cfid->dirents, ctx, file);
11471149
mutex_unlock(&cfid->dirents.de_mutex);
11481150
}
11491151
cifs_dbg(FYI, "Could not find entry\n");
@@ -1184,7 +1186,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
11841186
ctx->pos++;
11851187
if (cfid) {
11861188
mutex_lock(&cfid->dirents.de_mutex);
1187-
update_cached_dirents_count(&cfid->dirents, ctx);
1189+
update_cached_dirents_count(&cfid->dirents, file);
11881190
mutex_unlock(&cfid->dirents.de_mutex);
11891191
}
11901192

0 commit comments

Comments
 (0)