From d55b4da4331efdfe2be1bcc7bc217bd3f7c47870 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 6 Apr 2018 14:17:24 +0100 Subject: afs: Introduce a statistics proc file Introduce a proc file that displays a bunch of statistics for the AFS filesystem in the current network namespace. Signed-off-by: David Howells --- fs/afs/dir.c | 3 +++ fs/afs/inode.c | 3 +++ fs/afs/internal.h | 15 ++++++++++++++- fs/afs/proc.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/fs/afs/dir.c b/fs/afs/dir.c index b073976..538ca18 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -206,6 +206,7 @@ bool afs_dir_check_page(struct inode *dir, struct page *page) } checked: + afs_stat_v(vnode, n_read_dir); SetPageChecked(page); return true; @@ -868,6 +869,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, dentry->d_name.name[dentry->d_name.len - 1] == 's') return afs_lookup_atsys(dir, dentry, key); + afs_stat_v(dvnode, n_lookup); inode = afs_do_lookup(dir, dentry, key); if (IS_ERR(inode)) { ret = PTR_ERR(inode); @@ -1062,6 +1064,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) goto out_valid; /* the dir contents are unchanged */ _debug("dir modified"); + afs_stat_v(dir, n_reval); /* search the directory for this vnode */ ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key); diff --git a/fs/afs/inode.c b/fs/afs/inode.c index d5db9de..f4e6296 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -366,6 +366,9 @@ void afs_zap_data(struct afs_vnode *vnode) { _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); + if (S_ISDIR(vnode->vfs_inode.i_mode)) + afs_stat_v(vnode, n_inval); + #ifdef CONFIG_AFS_FSCACHE fscache_invalidate(vnode->cache); #endif diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 27150bb..ca65f12 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -257,9 +257,15 @@ struct afs_net { struct mutex lock_manager_mutex; /* Misc */ - struct proc_dir_entry *proc_afs; /* /proc/net/afs directory */ + struct proc_dir_entry *proc_afs; /* /proc/net/afs directory */ struct afs_sysnames *sysnames; rwlock_t sysnames_lock; + + /* Statistics counters */ + atomic_t n_lookup; /* Number of lookups done */ + atomic_t n_reval; /* Number of dentries needing revalidation */ + atomic_t n_inval; /* Number of invalidations by the server */ + atomic_t n_read_dir; /* Number of directory pages read */ }; extern const char afs_init_sysname[]; @@ -777,6 +783,13 @@ static inline void afs_put_net(struct afs_net *net) { } +static inline void __afs_stat(atomic_t *s) +{ + atomic_inc(s); +} + +#define afs_stat_v(vnode, n) __afs_stat(&afs_v2net(vnode)->n) + /* * misc.c */ diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 76f6df3..8bffb17 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c @@ -152,6 +152,8 @@ static const struct file_operations afs_proc_sysname_fops = { .write = afs_proc_sysname_write, }; +static const struct file_operations afs_proc_stats_fops; + /* * initialise the /proc/fs/afs/ directory */ @@ -166,6 +168,7 @@ int afs_proc_init(struct afs_net *net) if (!proc_create("cells", 0644, net->proc_afs, &afs_proc_cells_fops) || !proc_create("rootcell", 0644, net->proc_afs, &afs_proc_rootcell_fops) || !proc_create("servers", 0644, net->proc_afs, &afs_proc_servers_fops) || + !proc_create("stats", 0644, net->proc_afs, &afs_proc_stats_fops) || !proc_create("sysname", 0644, net->proc_afs, &afs_proc_sysname_fops)) goto error_tree; @@ -897,3 +900,37 @@ static int afs_proc_sysname_show(struct seq_file *m, void *v) seq_printf(m, "%s\n", sysnames->subs[i]); return 0; } + +/* + * Display general per-net namespace statistics + */ +static int afs_proc_stats_show(struct seq_file *m, void *v) +{ + struct afs_net *net = afs_seq2net(m); + + seq_puts(m, "kAFS statistics\n"); + + seq_printf(m, "dir-mgmt: look=%u reval=%u inval=%u\n", + atomic_read(&net->n_lookup), + atomic_read(&net->n_reval), + atomic_read(&net->n_inval)); + + seq_printf(m, "dir-data: rdpg=%u\n", + atomic_read(&net->n_read_dir)); + return 0; +} + +/* + * Open "/proc/fs/afs/stats" to allow reading of the stat counters. + */ +static int afs_proc_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, afs_proc_stats_show, NULL); +} + +static const struct file_operations afs_proc_stats_fops = { + .open = afs_proc_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; -- cgit v1.1