Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Sysctl operations for Coda filesystem | |
3 | * Original version: (C) 1996 P. Braam and M. Callahan | |
4 | * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University | |
5 | * | |
6 | * Carnegie Mellon encourages users to contribute improvements to | |
7 | * the Coda project. Contact Peter Braam (coda@cs.cmu.edu). | |
8 | * | |
9 | * CODA operation statistics | |
10 | * (c) March, 1998 Zhanyong Wan <zhanyong.wan@yale.edu> | |
11 | * | |
12 | */ | |
13 | ||
14 | #include <linux/config.h> | |
15 | #include <linux/time.h> | |
16 | #include <linux/mm.h> | |
17 | #include <linux/sysctl.h> | |
18 | #include <linux/proc_fs.h> | |
19 | #include <linux/slab.h> | |
20 | #include <linux/stat.h> | |
21 | #include <linux/ctype.h> | |
22 | #include <linux/bitops.h> | |
23 | #include <asm/uaccess.h> | |
24 | #include <linux/utsname.h> | |
25 | #include <linux/module.h> | |
26 | ||
27 | #include <linux/coda.h> | |
28 | #include <linux/coda_linux.h> | |
29 | #include <linux/coda_fs_i.h> | |
30 | #include <linux/coda_psdev.h> | |
31 | #include <linux/coda_cache.h> | |
32 | #include <linux/coda_proc.h> | |
33 | ||
34 | static struct ctl_table_header *fs_table_header; | |
35 | ||
36 | #define FS_CODA 1 /* Coda file system */ | |
37 | ||
38 | #define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */ | |
39 | #define CODA_HARD 5 /* mount type "hard" or "soft" */ | |
40 | #define CODA_VFS 6 /* vfs statistics */ | |
41 | #define CODA_CACHE_INV 9 /* cache invalidation statistics */ | |
42 | #define CODA_FAKE_STATFS 10 /* don't query venus for actual cache usage */ | |
43 | ||
44 | struct coda_vfs_stats coda_vfs_stat; | |
45 | static struct coda_cache_inv_stats coda_cache_inv_stat; | |
46 | ||
47 | static void reset_coda_vfs_stats( void ) | |
48 | { | |
49 | memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) ); | |
50 | } | |
51 | ||
52 | static void reset_coda_cache_inv_stats( void ) | |
53 | { | |
54 | memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) ); | |
55 | } | |
56 | ||
57 | static int do_reset_coda_vfs_stats( ctl_table * table, int write, | |
58 | struct file * filp, void __user * buffer, | |
59 | size_t * lenp, loff_t * ppos ) | |
60 | { | |
61 | if ( write ) { | |
62 | reset_coda_vfs_stats(); | |
63 | ||
64 | *ppos += *lenp; | |
65 | } else { | |
66 | *lenp = 0; | |
67 | } | |
68 | ||
69 | return 0; | |
70 | } | |
71 | ||
72 | static int do_reset_coda_cache_inv_stats( ctl_table * table, int write, | |
73 | struct file * filp, | |
74 | void __user * buffer, | |
75 | size_t * lenp, loff_t * ppos ) | |
76 | { | |
77 | if ( write ) { | |
78 | reset_coda_cache_inv_stats(); | |
79 | ||
80 | *ppos += *lenp; | |
81 | } else { | |
82 | *lenp = 0; | |
83 | } | |
84 | ||
85 | return 0; | |
86 | } | |
87 | ||
88 | static int coda_vfs_stats_get_info( char * buffer, char ** start, | |
89 | off_t offset, int length) | |
90 | { | |
91 | int len=0; | |
92 | off_t begin; | |
93 | struct coda_vfs_stats * ps = & coda_vfs_stat; | |
94 | ||
95 | /* this works as long as we are below 1024 characters! */ | |
96 | len += sprintf( buffer, | |
97 | "Coda VFS statistics\n" | |
98 | "===================\n\n" | |
99 | "File Operations:\n" | |
100 | "\topen\t\t%9d\n" | |
101 | "\tflush\t\t%9d\n" | |
102 | "\trelease\t\t%9d\n" | |
103 | "\tfsync\t\t%9d\n\n" | |
104 | "Dir Operations:\n" | |
105 | "\treaddir\t\t%9d\n\n" | |
106 | "Inode Operations\n" | |
107 | "\tcreate\t\t%9d\n" | |
108 | "\tlookup\t\t%9d\n" | |
109 | "\tlink\t\t%9d\n" | |
110 | "\tunlink\t\t%9d\n" | |
111 | "\tsymlink\t\t%9d\n" | |
112 | "\tmkdir\t\t%9d\n" | |
113 | "\trmdir\t\t%9d\n" | |
114 | "\trename\t\t%9d\n" | |
115 | "\tpermission\t%9d\n", | |
116 | ||
117 | /* file operations */ | |
118 | ps->open, | |
119 | ps->flush, | |
120 | ps->release, | |
121 | ps->fsync, | |
122 | ||
123 | /* dir operations */ | |
124 | ps->readdir, | |
125 | ||
126 | /* inode operations */ | |
127 | ps->create, | |
128 | ps->lookup, | |
129 | ps->link, | |
130 | ps->unlink, | |
131 | ps->symlink, | |
132 | ps->mkdir, | |
133 | ps->rmdir, | |
134 | ps->rename, | |
135 | ps->permission); | |
136 | ||
137 | begin = offset; | |
138 | *start = buffer + begin; | |
139 | len -= begin; | |
140 | ||
141 | if ( len > length ) | |
142 | len = length; | |
143 | if ( len < 0 ) | |
144 | len = 0; | |
145 | ||
146 | return len; | |
147 | } | |
148 | ||
149 | static int coda_cache_inv_stats_get_info( char * buffer, char ** start, | |
150 | off_t offset, int length) | |
151 | { | |
152 | int len=0; | |
153 | off_t begin; | |
154 | struct coda_cache_inv_stats * ps = & coda_cache_inv_stat; | |
155 | ||
156 | /* this works as long as we are below 1024 characters! */ | |
157 | len += sprintf( buffer, | |
158 | "Coda cache invalidation statistics\n" | |
159 | "==================================\n\n" | |
160 | "flush\t\t%9d\n" | |
161 | "purge user\t%9d\n" | |
162 | "zap_dir\t\t%9d\n" | |
163 | "zap_file\t%9d\n" | |
164 | "zap_vnode\t%9d\n" | |
165 | "purge_fid\t%9d\n" | |
166 | "replace\t\t%9d\n", | |
167 | ps->flush, | |
168 | ps->purge_user, | |
169 | ps->zap_dir, | |
170 | ps->zap_file, | |
171 | ps->zap_vnode, | |
172 | ps->purge_fid, | |
173 | ps->replace ); | |
174 | ||
175 | begin = offset; | |
176 | *start = buffer + begin; | |
177 | len -= begin; | |
178 | ||
179 | if ( len > length ) | |
180 | len = length; | |
181 | if ( len < 0 ) | |
182 | len = 0; | |
183 | ||
184 | return len; | |
185 | } | |
186 | ||
187 | static ctl_table coda_table[] = { | |
188 | {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, | |
189 | {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec}, | |
190 | {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats}, | |
191 | {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats}, | |
192 | {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec}, | |
193 | { 0 } | |
194 | }; | |
195 | ||
196 | static ctl_table fs_table[] = { | |
197 | {FS_CODA, "coda", NULL, 0, 0555, coda_table}, | |
198 | {0} | |
199 | }; | |
200 | ||
201 | ||
202 | #ifdef CONFIG_PROC_FS | |
203 | ||
204 | /* | |
205 | target directory structure: | |
206 | /proc/fs (see linux/fs/proc/root.c) | |
207 | /proc/fs/coda | |
208 | /proc/fs/coda/{vfs_stats, | |
209 | ||
210 | */ | |
211 | ||
212 | static struct proc_dir_entry* proc_fs_coda; | |
213 | ||
214 | #endif | |
215 | ||
216 | #define coda_proc_create(name,get_info) \ | |
217 | create_proc_info_entry(name, 0, proc_fs_coda, get_info) | |
218 | ||
219 | void coda_sysctl_init(void) | |
220 | { | |
221 | reset_coda_vfs_stats(); | |
222 | reset_coda_cache_inv_stats(); | |
223 | ||
224 | #ifdef CONFIG_PROC_FS | |
225 | proc_fs_coda = proc_mkdir("coda", proc_root_fs); | |
226 | if (proc_fs_coda) { | |
227 | proc_fs_coda->owner = THIS_MODULE; | |
228 | coda_proc_create("vfs_stats", coda_vfs_stats_get_info); | |
229 | coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info); | |
230 | } | |
231 | #endif | |
232 | ||
233 | #ifdef CONFIG_SYSCTL | |
234 | if ( !fs_table_header ) | |
235 | fs_table_header = register_sysctl_table(fs_table, 0); | |
236 | #endif | |
237 | } | |
238 | ||
239 | void coda_sysctl_clean(void) | |
240 | { | |
241 | ||
242 | #ifdef CONFIG_SYSCTL | |
243 | if ( fs_table_header ) { | |
244 | unregister_sysctl_table(fs_table_header); | |
245 | fs_table_header = NULL; | |
246 | } | |
247 | #endif | |
248 | ||
249 | #ifdef CONFIG_PROC_FS | |
250 | remove_proc_entry("cache_inv_stats", proc_fs_coda); | |
251 | remove_proc_entry("vfs_stats", proc_fs_coda); | |
252 | remove_proc_entry("coda", proc_root_fs); | |
253 | #endif | |
254 | } |