afs: Introduce a statistics proc file
authorDavid Howells <dhowells@redhat.com>
Fri, 6 Apr 2018 13:17:24 +0000 (14:17 +0100)
committerDavid Howells <dhowells@redhat.com>
Mon, 9 Apr 2018 20:53:54 +0000 (21:53 +0100)
Introduce a proc file that displays a bunch of statistics for the AFS
filesystem in the current network namespace.

Signed-off-by: David Howells <dhowells@redhat.com>
fs/afs/dir.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/proc.c

index b073976db8d2dab97dd1a5c6a4ece6475f43752d..538ca18efe0d8217725a05d873d566c61a8d4d87 100644 (file)
@@ -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);
index d5db9dead18ca1eabc8e2bd30870d80441e2ff9c..f4e62964efcb6d03f3e7a02b28582babf981b5f9 100644 (file)
@@ -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
index 27150bbc50d88eca06088969b3e293adddc154a2..ca65f121d2cc10457bc9e0036acf8829e71ffb66 100644 (file)
@@ -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
  */
index 76f6df32cde048ae6befba94fbe4fc502c8d71b6..8bffb17f9728ddd798ed6567f69df092b37d73a7 100644 (file)
@@ -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,
+};