Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[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 < ARRAY_SIZE(xstats); 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_each_possible_cpu(c)
66                                 val += *(((__u32*)&per_cpu(xfsstats, c) + j));
67                         len += sprintf(buffer + len, " %u", val);
68                         j++;
69                 }
70                 buffer[len++] = '\n';
71         }
72         /* extra precision counters */
73         for_each_possible_cpu(i) {
74                 xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes;
75                 xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes;
76                 xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes;
77         }
78
79         len += sprintf(buffer + len, "xpc %Lu %Lu %Lu\n",
80                         xs_xstrat_bytes, xs_write_bytes, xs_read_bytes);
81         len += sprintf(buffer + len, "debug %u\n",
82 #if defined(DEBUG)
83                 1);
84 #else
85                 0);
86 #endif
87
88         if (offset >= len) {
89                 *start = buffer;
90                 *eof = 1;
91                 return 0;
92         }
93         *start = buffer + offset;
94         if ((len -= offset) > count)
95                 return count;
96         *eof = 1;
97
98         return len;
99 }
100
101 int
102 xfs_init_procfs(void)
103 {
104         if (!proc_mkdir("fs/xfs", NULL))
105                 goto out;
106
107         if (!create_proc_read_entry("fs/xfs/stat", 0, NULL,
108                         xfs_read_xfsstats, NULL))
109                 goto out_remove_entry;
110         return 0;
111
112  out_remove_entry:
113         remove_proc_entry("fs/xfs", NULL);
114  out:
115         return -ENOMEM;
116 }
117
118 void
119 xfs_cleanup_procfs(void)
120 {
121         remove_proc_entry("fs/xfs/stat", NULL);
122         remove_proc_entry("fs/xfs", NULL);
123 }