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
6 * Carnegie Mellon encourages users to contribute improvements to
7 * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
9 * CODA operation statistics
10 * (c) March, 1998 Zhanyong Wan <zhanyong.wan@yale.edu>
14 #include <linux/config.h>
15 #include <linux/sched.h>
17 #include <linux/sysctl.h>
18 #include <linux/swapctl.h>
19 #include <linux/proc_fs.h>
20 #include <linux/slab.h>
21 #include <linux/stat.h>
22 #include <linux/ctype.h>
23 #include <asm/bitops.h>
24 #include <asm/uaccess.h>
25 #include <linux/utsname.h>
26 #define __NO_VERSION__
27 #include <linux/module.h>
29 #include <linux/coda.h>
30 #include <linux/coda_linux.h>
31 #include <linux/coda_fs_i.h>
32 #include <linux/coda_psdev.h>
33 #include <linux/coda_cache.h>
34 #include <linux/coda_proc.h>
36 static struct ctl_table_header *fs_table_header;
38 #define FS_CODA 1 /* Coda file system */
40 #define CODA_DEBUG 1 /* control debugging */
41 #define CODA_ENTRY 2 /* control enter/leave pattern */
42 #define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */
43 #define CODA_MC 4 /* use/do not use the access cache */
44 #define CODA_HARD 5 /* mount type "hard" or "soft" */
45 #define CODA_VFS 6 /* vfs statistics */
46 #define CODA_UPCALL 7 /* upcall statistics */
47 #define CODA_PERMISSION 8 /* permission statistics */
48 #define CODA_CACHE_INV 9 /* cache invalidation statistics */
49 #define CODA_FAKE_STATFS 10 /* don't query venus for actual cache usage */
51 static ctl_table coda_table[] = {
52 {CODA_DEBUG, "debug", &coda_debug, sizeof(int), 0644, NULL, &proc_dointvec},
53 {CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &proc_dointvec},
54 {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
55 {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
56 {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
57 {CODA_UPCALL, "upcall_stats", NULL, 0, 0644, NULL, &do_reset_coda_upcall_stats},
58 {CODA_PERMISSION, "permission_stats", NULL, 0, 0644, NULL, &do_reset_coda_permission_stats},
59 {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
60 {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},
64 static ctl_table fs_table[] = {
65 {FS_CODA, "coda", NULL, 0, 0555, coda_table},
69 struct coda_vfs_stats coda_vfs_stat;
70 struct coda_permission_stats coda_permission_stat;
71 struct coda_cache_inv_stats coda_cache_inv_stat;
72 struct coda_upcall_stats_entry coda_upcall_stat[CODA_NCALLS];
73 struct coda_upcallstats coda_callstats;
74 int coda_upcall_timestamping = 0;
76 /* keep this in sync with coda.h! */
77 char *coda_upcall_names[] = {
81 "open_by_fd ", /* 3 */
104 "purgeuser ", /* 26 */
108 "purgefid ", /* 30 */
109 "open_by_path", /* 31 */
111 "reintegrate ", /* 33 */
118 void reset_coda_vfs_stats( void )
120 memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
123 void reset_coda_upcall_stats( void )
125 memset( &coda_upcall_stat, 0, sizeof( coda_upcall_stat ) );
128 void reset_coda_permission_stats( void )
130 memset( &coda_permission_stat, 0, sizeof( coda_permission_stat ) );
133 void reset_coda_cache_inv_stats( void )
135 memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
139 void do_time_stats( struct coda_upcall_stats_entry * pentry,
140 unsigned long runtime )
142 unsigned long time = runtime; /* time in us */
143 CDEBUG(D_SPECIAL, "time: %ld\n", time);
145 if ( pentry->count == 0 ) {
146 pentry->time_sum = pentry->time_squared_sum = 0;
150 pentry->time_sum += time;
151 pentry->time_squared_sum += time*time;
156 void coda_upcall_stats(int opcode, long unsigned runtime)
158 struct coda_upcall_stats_entry * pentry;
160 if ( opcode < 0 || opcode > CODA_NCALLS - 1) {
161 printk("Nasty opcode %d passed to coda_upcall_stats\n",
166 pentry = &coda_upcall_stat[opcode];
167 do_time_stats(pentry, runtime);
169 /* fill in the totals */
170 pentry = &coda_upcall_stat[0];
171 do_time_stats(pentry, runtime);
175 unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry )
177 return ( pentry->count == 0 ) ? 0 : pentry->time_sum / pentry->count;
180 static inline unsigned long absolute( unsigned long x )
182 return x >= 0 ? x : -x;
185 static unsigned long sqr_root( unsigned long x )
187 unsigned long y = x, r;
204 if ( r*r <= x && x < (r+1)*(r+1) )
211 unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry )
213 unsigned long time_avg;
215 if ( pentry->count <= 1 )
218 time_avg = get_time_average( pentry );
220 return sqr_root( (pentry->time_squared_sum / pentry->count) -
221 time_avg * time_avg );
224 int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
225 void * buffer, size_t * lenp )
228 reset_coda_vfs_stats();
230 filp->f_pos += *lenp;
238 int do_reset_coda_upcall_stats( ctl_table * table, int write,
239 struct file * filp, void * buffer,
245 if (get_user(c, (char *)buffer))
247 coda_upcall_timestamping = (c == '1');
249 reset_coda_upcall_stats();
251 filp->f_pos += *lenp;
259 int do_reset_coda_permission_stats( ctl_table * table, int write,
260 struct file * filp, void * buffer,
264 reset_coda_permission_stats();
266 filp->f_pos += *lenp;
274 int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
275 struct file * filp, void * buffer,
279 reset_coda_cache_inv_stats();
281 filp->f_pos += *lenp;
289 int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
294 struct coda_vfs_stats * ps = & coda_vfs_stat;
296 /* this works as long as we are below 1024 characters! */
297 len += sprintf( buffer,
298 "Coda VFS statistics\n"
299 "===================\n\n"
306 "\treaddir\t\t%9d\n\n"
316 "\tpermission\t%9d\n",
318 /* file operations */
327 /* inode operations */
339 *start = buffer + begin;
350 int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
360 /* this works as long as we are below 1024 characters! */
362 len += sprintf( buffer,"%-79s\n", "Coda upcall statistics");
364 len += sprintf( buffer + len,"%-79s\n", "======================");
366 len += sprintf( buffer + len,"%-79s\n", "upcall count avg time(us) std deviation(us)");
368 len += sprintf( buffer + len,"%-79s\n", "------ ----- ------------ -----------------");
370 for ( i = 0 ; i < CODA_NCALLS ; i++ ) {
371 tmplen += sprintf(tmpbuf,"%s %9d %10ld %10ld",
372 coda_upcall_names[i],
373 coda_upcall_stat[i].count,
374 get_time_average(&coda_upcall_stat[i]),
375 coda_upcall_stat[i].time_squared_sum);
379 len += sprintf(buffer + len, "%-79s\n", tmpbuf);
384 begin = len- (pos - offset);
385 *start = buffer + begin;
396 int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
401 struct coda_permission_stats * ps = & coda_permission_stat;
403 /* this works as long as we are below 1024 characters! */
404 len += sprintf( buffer,
405 "Coda permission statistics\n"
406 "==========================\n\n"
414 *start = buffer + begin;
425 int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
430 struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
432 /* this works as long as we are below 1024 characters! */
433 len += sprintf( buffer,
434 "Coda cache invalidation statistics\n"
435 "==================================\n\n"
452 *start = buffer + begin;
464 #ifdef CONFIG_PROC_FS
467 target directory structure:
468 /proc/fs (see linux/fs/proc/root.c)
470 /proc/fs/coda/{vfs_stats,
474 struct proc_dir_entry* proc_fs_coda;
478 #define coda_proc_create(name,get_info) \
479 create_proc_info_entry(name, 0, proc_fs_coda, get_info)
481 void coda_sysctl_init()
483 memset(&coda_callstats, 0, sizeof(coda_callstats));
484 reset_coda_vfs_stats();
485 reset_coda_upcall_stats();
486 reset_coda_permission_stats();
487 reset_coda_cache_inv_stats();
489 #ifdef CONFIG_PROC_FS
490 proc_fs_coda = proc_mkdir("coda", proc_root_fs);
492 proc_fs_coda->owner = THIS_MODULE;
493 coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
494 coda_proc_create("upcall_stats", coda_upcall_stats_get_info);
495 coda_proc_create("permission_stats", coda_permission_stats_get_info);
496 coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);
501 if ( !fs_table_header )
502 fs_table_header = register_sysctl_table(fs_table, 0);
506 void coda_sysctl_clean()
510 if ( fs_table_header ) {
511 unregister_sysctl_table(fs_table_header);
517 remove_proc_entry("cache_inv_stats", proc_fs_coda);
518 remove_proc_entry("permission_stats", proc_fs_coda);
519 remove_proc_entry("upcall_stats", proc_fs_coda);
520 remove_proc_entry("vfs_stats", proc_fs_coda);
521 remove_proc_entry("coda", proc_root_fs);