The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/coda/sysctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/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 }

Cache object: 8bee75ab431de5dd928c70e55c15b576


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.