Skip to content

Commit 63eb8bd

Browse files
bharathsm-mssmfrench
authored andcommitted
smb: client: account smb directory cache usage and per-tcon totals
Add lightweight accounting for directory lease cache usage to aid debugging and limiting cache size in future. Track per-directory entry/byte counts and maintain per-tcon aggregates. Also expose the totals in /proc/fs/cifs/open_dirs. Signed-off-by: Bharath SM <bharathsm@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent dde6667 commit 63eb8bd

5 files changed

Lines changed: 63 additions & 14 deletions

File tree

fs/smb/client/cached_dir.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,21 @@ static void free_cached_dir(struct cached_fid *cfid)
697697
kfree(dirent);
698698
}
699699

700+
/* adjust tcon-level counters and reset per-dir accounting */
701+
if (cfid->cfids) {
702+
if (cfid->dirents.entries_count)
703+
atomic_long_sub((long)cfid->dirents.entries_count,
704+
&cfid->cfids->total_dirents_entries);
705+
if (cfid->dirents.bytes_used) {
706+
atomic64_sub((long long)cfid->dirents.bytes_used,
707+
&cfid->cfids->total_dirents_bytes);
708+
atomic64_sub((long long)cfid->dirents.bytes_used,
709+
&cifs_dircache_bytes_used);
710+
}
711+
}
712+
cfid->dirents.entries_count = 0;
713+
cfid->dirents.bytes_used = 0;
714+
700715
kfree(cfid->path);
701716
cfid->path = NULL;
702717
kfree(cfid);
@@ -792,6 +807,9 @@ struct cached_fids *init_cached_dirs(void)
792807
queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
793808
dir_cache_timeout * HZ);
794809

810+
atomic_long_set(&cfids->total_dirents_entries, 0);
811+
atomic64_set(&cfids->total_dirents_bytes, 0);
812+
795813
return cfids;
796814
}
797815

fs/smb/client/cached_dir.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ struct cached_dirents {
2727
struct mutex de_mutex;
2828
loff_t pos; /* Expected ctx->pos */
2929
struct list_head entries;
30+
/* accounting for cached entries in this directory */
31+
unsigned long entries_count;
32+
unsigned long bytes_used;
3033
};
3134

3235
struct cached_fid {
@@ -62,8 +65,14 @@ struct cached_fids {
6265
struct list_head dying;
6366
struct work_struct invalidation_work;
6467
struct delayed_work laundromat_work;
68+
/* aggregate accounting for all cached dirents under this tcon */
69+
atomic_long_t total_dirents_entries;
70+
atomic64_t total_dirents_bytes;
6571
};
6672

73+
/* Module-wide directory cache accounting (defined in cifsfs.c) */
74+
extern atomic64_t cifs_dircache_bytes_used; /* bytes across all mounts */
75+
6776
extern struct cached_fids *init_cached_dirs(void);
6877
extern void free_cached_dirs(struct cached_fids *cfids);
6978
extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,

fs/smb/client/cifs_debug.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,10 @@ static int cifs_debug_dirs_proc_show(struct seq_file *m, void *v)
331331
if (!cfids)
332332
continue;
333333
spin_lock(&cfids->cfid_list_lock); /* check lock ordering */
334-
seq_printf(m, "Num entries: %d\n", cfids->num_entries);
334+
seq_printf(m, "Num entries: %d, cached_dirents: %lu entries, %llu bytes\n",
335+
cfids->num_entries,
336+
(unsigned long)atomic_long_read(&cfids->total_dirents_entries),
337+
(unsigned long long)atomic64_read(&cfids->total_dirents_bytes));
335338
list_for_each_entry(cfid, &cfids->entries, entry) {
336339
seq_printf(m, "0x%x 0x%llx 0x%llx %s",
337340
tcon->tid,
@@ -342,6 +345,9 @@ static int cifs_debug_dirs_proc_show(struct seq_file *m, void *v)
342345
seq_printf(m, "\tvalid file info");
343346
if (cfid->dirents.is_valid)
344347
seq_printf(m, ", valid dirents");
348+
if (!list_empty(&cfid->dirents.entries))
349+
seq_printf(m, ", dirents: %lu entries, %lu bytes",
350+
cfid->dirents.entries_count, cfid->dirents.bytes_used);
345351
seq_printf(m, "\n");
346352
}
347353
spin_unlock(&cfids->cfid_list_lock);

fs/smb/client/cifsfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ unsigned int dir_cache_timeout = 30;
121121
module_param(dir_cache_timeout, uint, 0644);
122122
MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory contents for which we have a lease. Default: 30 "
123123
"Range: 1 to 65000 seconds, 0 to disable caching dir contents");
124+
/* Module-wide total cached dirents (in bytes) across all tcons */
125+
atomic64_t cifs_dircache_bytes_used = ATOMIC64_INIT(0);
124126

125127
/*
126128
* Write-only module parameter to drop all cached directory entries across

fs/smb/client/readdir.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -874,39 +874,42 @@ static void finished_cached_dirents_count(struct cached_dirents *cde,
874874
cde->is_valid = 1;
875875
}
876876

877-
static void add_cached_dirent(struct cached_dirents *cde,
878-
struct dir_context *ctx,
879-
const char *name, int namelen,
880-
struct cifs_fattr *fattr,
881-
struct file *file)
877+
static bool add_cached_dirent(struct cached_dirents *cde,
878+
struct dir_context *ctx, const char *name,
879+
int namelen, struct cifs_fattr *fattr,
880+
struct file *file)
882881
{
883882
struct cached_dirent *de;
884883

885884
if (cde->file != file)
886-
return;
885+
return false;
887886
if (cde->is_valid || cde->is_failed)
888-
return;
887+
return false;
889888
if (ctx->pos != cde->pos) {
890889
cde->is_failed = 1;
891-
return;
890+
return false;
892891
}
893892
de = kzalloc(sizeof(*de), GFP_ATOMIC);
894893
if (de == NULL) {
895894
cde->is_failed = 1;
896-
return;
895+
return false;
897896
}
898897
de->namelen = namelen;
899898
de->name = kstrndup(name, namelen, GFP_ATOMIC);
900899
if (de->name == NULL) {
901900
kfree(de);
902901
cde->is_failed = 1;
903-
return;
902+
return false;
904903
}
905904
de->pos = ctx->pos;
906905

907906
memcpy(&de->fattr, fattr, sizeof(struct cifs_fattr));
908907

909908
list_add_tail(&de->entry, &cde->entries);
909+
/* update accounting */
910+
cde->entries_count++;
911+
cde->bytes_used += sizeof(*de) + (size_t)namelen + 1;
912+
return true;
910913
}
911914

912915
static bool cifs_dir_emit(struct dir_context *ctx,
@@ -915,18 +918,29 @@ static bool cifs_dir_emit(struct dir_context *ctx,
915918
struct cached_fid *cfid,
916919
struct file *file)
917920
{
918-
bool rc;
921+
size_t delta_bytes = 0;
922+
bool rc, added = false;
919923
ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
920924

921925
rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype);
922926
if (!rc)
923927
return rc;
924928

925929
if (cfid) {
930+
/* Cost of this entry */
931+
delta_bytes = sizeof(struct cached_dirent) + (size_t)namelen + 1;
932+
926933
mutex_lock(&cfid->dirents.de_mutex);
927-
add_cached_dirent(&cfid->dirents, ctx, name, namelen,
928-
fattr, file);
934+
added = add_cached_dirent(&cfid->dirents, ctx, name, namelen,
935+
fattr, file);
929936
mutex_unlock(&cfid->dirents.de_mutex);
937+
938+
if (added) {
939+
/* per-tcon then global for consistency with free path */
940+
atomic64_add((long long)delta_bytes, &cfid->cfids->total_dirents_bytes);
941+
atomic_long_inc(&cfid->cfids->total_dirents_entries);
942+
atomic64_add((long long)delta_bytes, &cifs_dircache_bytes_used);
943+
}
930944
}
931945

932946
return rc;

0 commit comments

Comments
 (0)