1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* CacheFiles statistics
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/proc_fs.h>
10*4882a593Smuzhiyun #include <linux/seq_file.h>
11*4882a593Smuzhiyun #include "internal.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun atomic_t cachefiles_lookup_histogram[HZ];
14*4882a593Smuzhiyun atomic_t cachefiles_mkdir_histogram[HZ];
15*4882a593Smuzhiyun atomic_t cachefiles_create_histogram[HZ];
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /*
18*4882a593Smuzhiyun * display the latency histogram
19*4882a593Smuzhiyun */
cachefiles_histogram_show(struct seq_file * m,void * v)20*4882a593Smuzhiyun static int cachefiles_histogram_show(struct seq_file *m, void *v)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun unsigned long index;
23*4882a593Smuzhiyun unsigned x, y, z, t;
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun switch ((unsigned long) v) {
26*4882a593Smuzhiyun case 1:
27*4882a593Smuzhiyun seq_puts(m, "JIFS SECS LOOKUPS MKDIRS CREATES\n");
28*4882a593Smuzhiyun return 0;
29*4882a593Smuzhiyun case 2:
30*4882a593Smuzhiyun seq_puts(m, "===== ===== ========= ========= =========\n");
31*4882a593Smuzhiyun return 0;
32*4882a593Smuzhiyun default:
33*4882a593Smuzhiyun index = (unsigned long) v - 3;
34*4882a593Smuzhiyun x = atomic_read(&cachefiles_lookup_histogram[index]);
35*4882a593Smuzhiyun y = atomic_read(&cachefiles_mkdir_histogram[index]);
36*4882a593Smuzhiyun z = atomic_read(&cachefiles_create_histogram[index]);
37*4882a593Smuzhiyun if (x == 0 && y == 0 && z == 0)
38*4882a593Smuzhiyun return 0;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun t = (index * 1000) / HZ;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun seq_printf(m, "%4lu 0.%03u %9u %9u %9u\n", index, t, x, y, z);
43*4882a593Smuzhiyun return 0;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun * set up the iterator to start reading from the first line
49*4882a593Smuzhiyun */
cachefiles_histogram_start(struct seq_file * m,loff_t * _pos)50*4882a593Smuzhiyun static void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun if ((unsigned long long)*_pos >= HZ + 2)
53*4882a593Smuzhiyun return NULL;
54*4882a593Smuzhiyun if (*_pos == 0)
55*4882a593Smuzhiyun *_pos = 1;
56*4882a593Smuzhiyun return (void *)(unsigned long) *_pos;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /*
60*4882a593Smuzhiyun * move to the next line
61*4882a593Smuzhiyun */
cachefiles_histogram_next(struct seq_file * m,void * v,loff_t * pos)62*4882a593Smuzhiyun static void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun (*pos)++;
65*4882a593Smuzhiyun return (unsigned long long)*pos > HZ + 2 ?
66*4882a593Smuzhiyun NULL : (void *)(unsigned long) *pos;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /*
70*4882a593Smuzhiyun * clean up after reading
71*4882a593Smuzhiyun */
cachefiles_histogram_stop(struct seq_file * m,void * v)72*4882a593Smuzhiyun static void cachefiles_histogram_stop(struct seq_file *m, void *v)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun static const struct seq_operations cachefiles_histogram_ops = {
77*4882a593Smuzhiyun .start = cachefiles_histogram_start,
78*4882a593Smuzhiyun .stop = cachefiles_histogram_stop,
79*4882a593Smuzhiyun .next = cachefiles_histogram_next,
80*4882a593Smuzhiyun .show = cachefiles_histogram_show,
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /*
84*4882a593Smuzhiyun * initialise the /proc/fs/cachefiles/ directory
85*4882a593Smuzhiyun */
cachefiles_proc_init(void)86*4882a593Smuzhiyun int __init cachefiles_proc_init(void)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun _enter("");
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (!proc_mkdir("fs/cachefiles", NULL))
91*4882a593Smuzhiyun goto error_dir;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun if (!proc_create_seq("fs/cachefiles/histogram", S_IFREG | 0444, NULL,
94*4882a593Smuzhiyun &cachefiles_histogram_ops))
95*4882a593Smuzhiyun goto error_histogram;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun _leave(" = 0");
98*4882a593Smuzhiyun return 0;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun error_histogram:
101*4882a593Smuzhiyun remove_proc_entry("fs/cachefiles", NULL);
102*4882a593Smuzhiyun error_dir:
103*4882a593Smuzhiyun _leave(" = -ENOMEM");
104*4882a593Smuzhiyun return -ENOMEM;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /*
108*4882a593Smuzhiyun * clean up the /proc/fs/cachefiles/ directory
109*4882a593Smuzhiyun */
cachefiles_proc_cleanup(void)110*4882a593Smuzhiyun void cachefiles_proc_cleanup(void)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun remove_proc_entry("fs/cachefiles/histogram", NULL);
113*4882a593Smuzhiyun remove_proc_entry("fs/cachefiles", NULL);
114*4882a593Smuzhiyun }
115