OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [coda/] [sysctl.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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/sched.h>
16
#include <linux/mm.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>
28
 
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>
35
 
36
static struct ctl_table_header *fs_table_header;
37
 
38
#define FS_CODA         1       /* Coda file system */
39
 
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 */
50
 
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},
61
        { 0 }
62
};
63
 
64
static ctl_table fs_table[] = {
65
       {FS_CODA, "coda",    NULL, 0, 0555, coda_table},
66
       {0}
67
};
68
 
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;
75
 
76
/* keep this in sync with coda.h! */
77
char *coda_upcall_names[] = {
78
        "totals      ",   /*  0 */
79
        "-           ",   /*  1 */
80
        "root        ",   /*  2 */
81
        "open_by_fd  ",   /*  3 */
82
        "open        ",   /*  4 */
83
        "close       ",   /*  5 */
84
        "ioctl       ",   /*  6 */
85
        "getattr     ",   /*  7 */
86
        "setattr     ",   /*  8 */
87
        "access      ",   /*  9 */
88
        "lookup      ",   /* 10 */
89
        "create      ",   /* 11 */
90
        "remove      ",   /* 12 */
91
        "link        ",   /* 13 */
92
        "rename      ",   /* 14 */
93
        "mkdir       ",   /* 15 */
94
        "rmdir       ",   /* 16 */
95
        "readdir     ",   /* 17 */
96
        "symlink     ",   /* 18 */
97
        "readlink    ",   /* 19 */
98
        "fsync       ",   /* 20 */
99
        "-           ",   /* 21 */
100
        "vget        ",   /* 22 */
101
        "signal      ",   /* 23 */
102
        "replace     ",   /* 24 */
103
        "flush       ",   /* 25 */
104
        "purgeuser   ",   /* 26 */
105
        "zapfile     ",   /* 27 */
106
        "zapdir      ",   /* 28 */
107
        "-           ",   /* 29 */
108
        "purgefid    ",   /* 30 */
109
        "open_by_path",   /* 31 */
110
        "resolve     ",   /* 32 */
111
        "reintegrate ",   /* 33 */
112
        "statfs      ",   /* 34 */
113
        "store       ",   /* 35 */
114
        "release     "    /* 36 */
115
};
116
 
117
 
118
void reset_coda_vfs_stats( void )
119
{
120
        memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
121
}
122
 
123
void reset_coda_upcall_stats( void )
124
{
125
        memset( &coda_upcall_stat, 0, sizeof( coda_upcall_stat ) );
126
}
127
 
128
void reset_coda_permission_stats( void )
129
{
130
        memset( &coda_permission_stat, 0, sizeof( coda_permission_stat ) );
131
}
132
 
133
void reset_coda_cache_inv_stats( void )
134
{
135
        memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
136
}
137
 
138
 
139
void do_time_stats( struct coda_upcall_stats_entry * pentry,
140
                    unsigned long runtime )
141
{
142
        unsigned long time = runtime;   /* time in us */
143
        CDEBUG(D_SPECIAL, "time: %ld\n", time);
144
 
145
        if ( pentry->count == 0 ) {
146
                pentry->time_sum = pentry->time_squared_sum = 0;
147
        }
148
 
149
        pentry->count++;
150
        pentry->time_sum += time;
151
        pentry->time_squared_sum += time*time;
152
}
153
 
154
 
155
 
156
void coda_upcall_stats(int opcode, long unsigned runtime)
157
{
158
        struct coda_upcall_stats_entry * pentry;
159
 
160
        if ( opcode < 0 || opcode > CODA_NCALLS - 1) {
161
                printk("Nasty opcode %d passed to coda_upcall_stats\n",
162
                       opcode);
163
                return;
164
        }
165
 
166
        pentry = &coda_upcall_stat[opcode];
167
        do_time_stats(pentry, runtime);
168
 
169
        /* fill in the totals */
170
        pentry = &coda_upcall_stat[0];
171
        do_time_stats(pentry, runtime);
172
 
173
}
174
 
175
unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry )
176
{
177
        return ( pentry->count == 0 ) ? 0 : pentry->time_sum / pentry->count;
178
}
179
 
180
static inline unsigned long absolute( unsigned long x )
181
{
182
        return x >= 0 ? x : -x;
183
}
184
 
185
static unsigned long sqr_root( unsigned long x )
186
{
187
        unsigned long y = x, r;
188
        int n_bit = 0;
189
 
190
        if ( x == 0 )
191
                return 0;
192
        if ( x < 0)
193
                x = -x;
194
 
195
        while ( y ) {
196
                y >>= 1;
197
                n_bit++;
198
        }
199
 
200
        r = 1 << (n_bit/2);
201
 
202
        while ( 1 ) {
203
                r = (r + x/r)/2;
204
                if ( r*r <= x && x < (r+1)*(r+1) )
205
                        break;
206
        }
207
 
208
        return r;
209
}
210
 
211
unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry )
212
{
213
        unsigned long time_avg;
214
 
215
        if ( pentry->count <= 1 )
216
                return 0;
217
 
218
        time_avg = get_time_average( pentry );
219
 
220
        return sqr_root( (pentry->time_squared_sum / pentry->count) -
221
                            time_avg * time_avg );
222
}
223
 
224
int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
225
                             void * buffer, size_t * lenp )
226
{
227
        if ( write ) {
228
                reset_coda_vfs_stats();
229
 
230
                filp->f_pos += *lenp;
231
        } else {
232
                *lenp = 0;
233
        }
234
 
235
        return 0;
236
}
237
 
238
int do_reset_coda_upcall_stats( ctl_table * table, int write,
239
                                struct file * filp, void * buffer,
240
                                size_t * lenp )
241
{
242
        if ( write ) {
243
                if (*lenp > 0) {
244
                        char c;
245
                        if (get_user(c, (char *)buffer))
246
                                return -EFAULT;
247
                        coda_upcall_timestamping = (c == '1');
248
                }
249
                reset_coda_upcall_stats();
250
 
251
                filp->f_pos += *lenp;
252
        } else {
253
                *lenp = 0;
254
        }
255
 
256
        return 0;
257
}
258
 
259
int do_reset_coda_permission_stats( ctl_table * table, int write,
260
                                    struct file * filp, void * buffer,
261
                                    size_t * lenp )
262
{
263
        if ( write ) {
264
                reset_coda_permission_stats();
265
 
266
                filp->f_pos += *lenp;
267
        } else {
268
                *lenp = 0;
269
        }
270
 
271
        return 0;
272
}
273
 
274
int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
275
                                   struct file * filp, void * buffer,
276
                                   size_t * lenp )
277
{
278
        if ( write ) {
279
                reset_coda_cache_inv_stats();
280
 
281
                filp->f_pos += *lenp;
282
        } else {
283
                *lenp = 0;
284
        }
285
 
286
        return 0;
287
}
288
 
289
int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
290
                             int length)
291
{
292
        int len=0;
293
        off_t begin;
294
        struct coda_vfs_stats * ps = & coda_vfs_stat;
295
 
296
  /* this works as long as we are below 1024 characters! */
297
        len += sprintf( buffer,
298
                        "Coda VFS statistics\n"
299
                        "===================\n\n"
300
                        "File Operations:\n"
301
                        "\topen\t\t%9d\n"
302
                        "\tflush\t\t%9d\n"
303
                        "\trelease\t\t%9d\n"
304
                        "\tfsync\t\t%9d\n\n"
305
                        "Dir Operations:\n"
306
                        "\treaddir\t\t%9d\n\n"
307
                        "Inode Operations\n"
308
                        "\tcreate\t\t%9d\n"
309
                        "\tlookup\t\t%9d\n"
310
                        "\tlink\t\t%9d\n"
311
                        "\tunlink\t\t%9d\n"
312
                        "\tsymlink\t\t%9d\n"
313
                        "\tmkdir\t\t%9d\n"
314
                        "\trmdir\t\t%9d\n"
315
                        "\trename\t\t%9d\n"
316
                        "\tpermission\t%9d\n",
317
 
318
                        /* file operations */
319
                        ps->open,
320
                        ps->flush,
321
                        ps->release,
322
                        ps->fsync,
323
 
324
                        /* dir operations */
325
                        ps->readdir,
326
 
327
                        /* inode operations */
328
                        ps->create,
329
                        ps->lookup,
330
                        ps->link,
331
                        ps->unlink,
332
                        ps->symlink,
333
                        ps->mkdir,
334
                        ps->rmdir,
335
                        ps->rename,
336
                        ps->permission);
337
 
338
        begin = offset;
339
        *start = buffer + begin;
340
        len -= begin;
341
 
342
        if ( len > length )
343
                len = length;
344
        if ( len < 0 )
345
                len = 0;
346
 
347
        return len;
348
}
349
 
350
int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
351
                                int length)
352
{
353
        int len=0;
354
        int i;
355
        off_t begin;
356
        off_t pos = 0;
357
        char tmpbuf[80];
358
        int tmplen = 0;
359
 
360
        /* this works as long as we are below 1024 characters! */
361
        if ( offset < 80 )
362
                len += sprintf( buffer,"%-79s\n",       "Coda upcall statistics");
363
        if ( offset < 160)
364
                len += sprintf( buffer + len,"%-79s\n", "======================");
365
        if ( offset < 240)
366
                len += sprintf( buffer + len,"%-79s\n", "upcall              count       avg time(us)    std deviation(us)");
367
        if ( offset < 320)
368
                len += sprintf( buffer + len,"%-79s\n", "------              -----       ------------    -----------------");
369
        pos = 320;
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);
376
                pos += 80;
377
                if ( pos < offset )
378
                        continue;
379
                len += sprintf(buffer + len, "%-79s\n", tmpbuf);
380
                if ( len >= length )
381
                        break;
382
        }
383
 
384
        begin = len- (pos - offset);
385
        *start = buffer + begin;
386
        len -= begin;
387
 
388
        if ( len > length )
389
                len = length;
390
        if ( len < 0 )
391
                len = 0;
392
 
393
        return len;
394
}
395
 
396
int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
397
                                    int length)
398
{
399
        int len=0;
400
        off_t begin;
401
        struct coda_permission_stats * ps = & coda_permission_stat;
402
 
403
        /* this works as long as we are below 1024 characters! */
404
        len += sprintf( buffer,
405
                        "Coda permission statistics\n"
406
                        "==========================\n\n"
407
                        "count\t\t%9d\n"
408
                        "hit count\t%9d\n",
409
 
410
                        ps->count,
411
                        ps->hit_count );
412
 
413
        begin = offset;
414
        *start = buffer + begin;
415
        len -= begin;
416
 
417
        if ( len > length )
418
                len = length;
419
        if ( len < 0 )
420
                len = 0;
421
 
422
        return len;
423
}
424
 
425
int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
426
                                   int length)
427
{
428
        int len=0;
429
        off_t begin;
430
        struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
431
 
432
        /* this works as long as we are below 1024 characters! */
433
        len += sprintf( buffer,
434
                        "Coda cache invalidation statistics\n"
435
                        "==================================\n\n"
436
                        "flush\t\t%9d\n"
437
                        "purge user\t%9d\n"
438
                        "zap_dir\t\t%9d\n"
439
                        "zap_file\t%9d\n"
440
                        "zap_vnode\t%9d\n"
441
                        "purge_fid\t%9d\n"
442
                        "replace\t\t%9d\n",
443
                        ps->flush,
444
                        ps->purge_user,
445
                        ps->zap_dir,
446
                        ps->zap_file,
447
                        ps->zap_vnode,
448
                        ps->purge_fid,
449
                        ps->replace );
450
 
451
        begin = offset;
452
        *start = buffer + begin;
453
        len -= begin;
454
 
455
        if ( len > length )
456
                len = length;
457
        if ( len < 0 )
458
                len = 0;
459
 
460
        return len;
461
}
462
 
463
 
464
#ifdef CONFIG_PROC_FS
465
 
466
/*
467
 target directory structure:
468
   /proc/fs  (see linux/fs/proc/root.c)
469
   /proc/fs/coda
470
   /proc/fs/coda/{vfs_stats,
471
 
472
*/
473
 
474
struct proc_dir_entry* proc_fs_coda;
475
 
476
#endif
477
 
478
#define coda_proc_create(name,get_info) \
479
        create_proc_info_entry(name, 0, proc_fs_coda, get_info)
480
 
481
void coda_sysctl_init()
482
{
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();
488
 
489
#ifdef CONFIG_PROC_FS
490
        proc_fs_coda = proc_mkdir("coda", proc_root_fs);
491
        if (proc_fs_coda) {
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);
497
        }
498
#endif
499
 
500
#ifdef CONFIG_SYSCTL
501
        if ( !fs_table_header )
502
                fs_table_header = register_sysctl_table(fs_table, 0);
503
#endif 
504
}
505
 
506
void coda_sysctl_clean()
507
{
508
 
509
#ifdef CONFIG_SYSCTL
510
        if ( fs_table_header ) {
511
                unregister_sysctl_table(fs_table_header);
512
                fs_table_header = 0;
513
        }
514
#endif
515
 
516
#if CONFIG_PROC_FS
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);
522
#endif 
523
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.