Merge branch 'upstream'
[linux-2.6] / fs / xfs / linux-2.6 / xfs_stats.c
1 /*
2  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include <linux/proc_fs.h>
20
21 DEFINE_PER_CPU(struct xfsstats, xfsstats);
22
23 STATIC int
24 xfs_read_xfsstats(
25         char            *buffer,
26         char            **start,
27         off_t           offset,
28         int             count,
29         int             *eof,
30         void            *data)
31 {
32         int             c, i, j, len, val;
33         __uint64_t      xs_xstrat_bytes = 0;
34         __uint64_t      xs_write_bytes = 0;
35         __uint64_t      xs_read_bytes = 0;
36
37         static const struct xstats_entry {
38                 char    *desc;
39                 int     endpoint;
40         } xstats[] = {
41                 { "extent_alloc",       XFSSTAT_END_EXTENT_ALLOC        },
42                 { "abt",                XFSSTAT_END_ALLOC_BTREE         },
43                 { "blk_map",            XFSSTAT_END_BLOCK_MAPPING       },
44                 { "bmbt",               XFSSTAT_END_BLOCK_MAP_BTREE     },
45                 { "dir",                XFSSTAT_END_DIRECTORY_OPS       },
46                 { "trans",              XFSSTAT_END_TRANSACTIONS        },
47                 { "ig",                 XFSSTAT_END_INODE_OPS           },
48                 { "log",                XFSSTAT_END_LOG_OPS             },
49                 { "push_ail",           XFSSTAT_END_TAIL_PUSHING        },
50                 { "xstrat",             XFSSTAT_END_WRITE_CONVERT       },
51                 { "rw",                 XFSSTAT_END_READ_WRITE_OPS      },
52                 { "attr",               XFSSTAT_END_ATTRIBUTE_OPS       },
53                 { "icluster",           XFSSTAT_END_INODE_CLUSTER       },
54                 { "vnodes",             XFSSTAT_END_VNODE_OPS           },
55                 { "buf",                XFSSTAT_END_BUF                 },
56         };
57
58         /* Loop over all stats groups */
59         for (i=j=len = 0; i < sizeof(xstats)/sizeof(struct xstats_entry); i++) {
60                 len += sprintf(buffer + len, xstats[i].desc);
61                 /* inner loop does each group */
62                 while (j < xstats[i].endpoint) {
63                         val = 0;
64                         /* sum over all cpus */
65                         for (c = 0; c < NR_CPUS; c++) {
66                                 if (!cpu_possible(c)) continue;
67                                 val += *(((__u32*)&per_cpu(xfsstats, c) + j));
68                         }
69                         len += sprintf(buffer + len, " %u", val);
70                         j++;
71                 }
72                 buffer[len++] = '\n';
73         }
74         /* extra precision counters */
75         for (i = 0; i < NR_CPUS; i++) {
76                 if (!cpu_possible(i)) continue;
77                 xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes;
78                 xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes;
79                 xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes;
80         }
81
82         len += sprintf(buffer + len, "xpc %Lu %Lu %Lu\n",
83                         xs_xstrat_bytes, xs_write_bytes, xs_read_bytes);
84         len += sprintf(buffer + len, "debug %u\n",
85 #if defined(DEBUG)
86                 1);
87 #else
88                 0);
89 #endif
90
91         if (offset >= len) {
92                 *start = buffer;
93                 *eof = 1;
94                 return 0;
95         }
96         *start = buffer + offset;
97         if ((len -= offset) > count)
98                 return count;
99         *eof = 1;
100
101         return len;
102 }
103
104 void
105 xfs_init_procfs(void)
106 {
107         if (!proc_mkdir("fs/xfs", NULL))
108                 return;
109         create_proc_read_entry("fs/xfs/stat", 0, NULL, xfs_read_xfsstats, NULL);
110 }
111
112 void
113 xfs_cleanup_procfs(void)
114 {
115         remove_proc_entry("fs/xfs/stat", NULL);
116         remove_proc_entry("fs/xfs", NULL);
117 }