sysctl.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:12k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. #include <linux/config.h>
  14. #include <linux/sched.h>
  15. #include <linux/mm.h>
  16. #include <linux/sysctl.h>
  17. #include <linux/swapctl.h>
  18. #include <linux/proc_fs.h>
  19. #include <linux/slab.h>
  20. #include <linux/stat.h>
  21. #include <linux/ctype.h>
  22. #include <asm/bitops.h>
  23. #include <asm/segment.h>
  24. #include <asm/uaccess.h>
  25. #include <linux/utsname.h>
  26. #define __NO_VERSION__
  27. #include <linux/module.h>
  28. #include <linux/coda.h>
  29. #include <linux/coda_linux.h>
  30. #include <linux/coda_fs_i.h>
  31. #include <linux/coda_psdev.h>
  32. #include <linux/coda_cache.h>
  33. #include <linux/coda_proc.h>
  34. static struct ctl_table_header *fs_table_header;
  35. #define FS_CODA         1       /* Coda file system */
  36. #define CODA_DEBUG    1  /* control debugging */
  37. #define CODA_ENTRY  2       /* control enter/leave pattern */
  38. #define CODA_TIMEOUT    3       /* timeout on upcalls to become intrble */
  39. #define CODA_MC         4       /* use/do not use the access cache */
  40. #define CODA_HARD       5       /* mount type "hard" or "soft" */
  41. #define CODA_VFS   6       /* vfs statistics */
  42. #define CODA_UPCALL   7       /* upcall statistics */
  43. #define CODA_PERMISSION  8       /* permission statistics */
  44. #define CODA_CACHE_INV   9       /* cache invalidation statistics */
  45. #define CODA_FAKE_STATFS 10  /* don't query venus for actual cache usage */
  46. static ctl_table coda_table[] = {
  47. {CODA_DEBUG, "debug", &coda_debug, sizeof(int), 0644, NULL, &proc_dointvec},
  48. {CODA_ENTRY, "printentry", &coda_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
  49.   {CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &proc_dointvec}, 
  50.   {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
  51.   {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
  52.   {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
  53.   {CODA_UPCALL, "upcall_stats", NULL, 0, 0644, NULL, &do_reset_coda_upcall_stats},
  54.   {CODA_PERMISSION, "permission_stats", NULL, 0, 0644, NULL, &do_reset_coda_permission_stats},
  55.   {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
  56.   {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},
  57. { 0 }
  58. };
  59. static ctl_table fs_table[] = {
  60.        {FS_CODA, "coda",    NULL, 0, 0555, coda_table},
  61.        {0}
  62. };
  63. struct coda_vfs_stats coda_vfs_stat;
  64. struct coda_permission_stats coda_permission_stat;
  65. struct coda_cache_inv_stats coda_cache_inv_stat;
  66. struct coda_upcall_stats_entry  coda_upcall_stat[CODA_NCALLS];
  67. struct coda_upcallstats         coda_callstats;
  68. int                             coda_upcall_timestamping = 0;
  69. /* keep this in sync with coda.h! */
  70. char *coda_upcall_names[] = {
  71. "totals      ",   /*  0 */
  72. "-           ",   /*  1 */
  73. "root        ",   /*  2 */
  74. "open_by_fd  ",   /*  3 */
  75. "open        ",   /*  4 */
  76. "close       ",   /*  5 */
  77. "ioctl       ",   /*  6 */
  78. "getattr     ",   /*  7 */
  79. "setattr     ",   /*  8 */
  80. "access      ",   /*  9 */
  81. "lookup      ",   /* 10 */
  82. "create      ",   /* 11 */
  83. "remove      ",   /* 12 */
  84. "link        ",   /* 13 */
  85. "rename      ",   /* 14 */
  86. "mkdir       ",   /* 15 */
  87. "rmdir       ",   /* 16 */
  88. "readdir     ",   /* 17 */
  89. "symlink     ",   /* 18 */
  90. "readlink    ",   /* 19 */
  91. "fsync       ",   /* 20 */
  92. "-           ",   /* 21 */
  93. "vget        ",   /* 22 */
  94. "signal      ",   /* 23 */
  95. "replace     ",   /* 24 */
  96. "flush       ",   /* 25 */
  97. "purgeuser   ",   /* 26 */
  98. "zapfile     ",   /* 27 */
  99. "zapdir      ",   /* 28 */
  100. "-           ",   /* 29 */
  101. "purgefid    ",   /* 30 */
  102. "open_by_path",   /* 31 */
  103. "resolve     ",   /* 32 */
  104. "reintegrate ",   /* 33 */
  105. "statfs      ",   /* 34 */
  106. "store       ",   /* 35 */
  107. "release     "    /* 36 */
  108. };
  109. void reset_coda_vfs_stats( void )
  110. {
  111. memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
  112. }
  113. void reset_coda_upcall_stats( void )
  114. {
  115. memset( &coda_upcall_stat, 0, sizeof( coda_upcall_stat ) );
  116. }
  117. void reset_coda_permission_stats( void )
  118. {
  119. memset( &coda_permission_stat, 0, sizeof( coda_permission_stat ) );
  120. }
  121. void reset_coda_cache_inv_stats( void )
  122. {
  123. memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
  124. }
  125. void do_time_stats( struct coda_upcall_stats_entry * pentry, 
  126.     unsigned long runtime )
  127. {
  128. unsigned long time = runtime; /* time in us */
  129. CDEBUG(D_SPECIAL, "time: %ldn", time);
  130. if ( pentry->count == 0 ) {
  131. pentry->time_sum = pentry->time_squared_sum = 0;
  132. }
  133. pentry->count++;
  134. pentry->time_sum += time;
  135. pentry->time_squared_sum += time*time;
  136. }
  137. void coda_upcall_stats(int opcode, long unsigned runtime) 
  138. {
  139. struct coda_upcall_stats_entry * pentry;
  140. if ( opcode < 0 || opcode > CODA_NCALLS - 1) {
  141. printk("Nasty opcode %d passed to coda_upcall_statsn",
  142.        opcode);
  143. return;
  144. }
  145. pentry = &coda_upcall_stat[opcode];
  146. do_time_stats(pentry, runtime);
  147.         /* fill in the totals */
  148. pentry = &coda_upcall_stat[0];
  149. do_time_stats(pentry, runtime);
  150. }
  151. unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry )
  152. {
  153. return ( pentry->count == 0 ) ? 0 : pentry->time_sum / pentry->count;
  154. }
  155. static inline unsigned long absolute( unsigned long x )
  156. {
  157. return x >= 0 ? x : -x;
  158. }
  159. static unsigned long sqr_root( unsigned long x )
  160. {
  161. unsigned long y = x, r;
  162. int n_bit = 0;
  163.   
  164. if ( x == 0 )
  165. return 0;
  166. if ( x < 0)
  167. x = -x;
  168. while ( y ) {
  169. y >>= 1;
  170. n_bit++;
  171. }
  172.   
  173. r = 1 << (n_bit/2);
  174.   
  175. while ( 1 ) {
  176. r = (r + x/r)/2;
  177. if ( r*r <= x && x < (r+1)*(r+1) )
  178. break;
  179. }
  180.   
  181. return r;
  182. }
  183. unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry )
  184. {
  185. unsigned long time_avg;
  186.   
  187. if ( pentry->count <= 1 )
  188. return 0;
  189.   
  190. time_avg = get_time_average( pentry );
  191. return sqr_root( (pentry->time_squared_sum / pentry->count) - 
  192.     time_avg * time_avg );
  193. }
  194. int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
  195.      void * buffer, size_t * lenp )
  196. {
  197. if ( write ) {
  198. reset_coda_vfs_stats();
  199. filp->f_pos += *lenp;
  200. } else {
  201. *lenp = 0;
  202. }
  203. return 0;
  204. }
  205. int do_reset_coda_upcall_stats( ctl_table * table, int write, 
  206. struct file * filp, void * buffer, 
  207. size_t * lenp )
  208. {
  209. if ( write ) {
  210.          if (*lenp > 0) {
  211. char c;
  212.                  if (get_user(c, (char *)buffer))
  213.         return -EFAULT;
  214.                         coda_upcall_timestamping = (c == '1');
  215.                 }
  216. reset_coda_upcall_stats();
  217. filp->f_pos += *lenp;
  218. } else {
  219. *lenp = 0;
  220. }
  221. return 0;
  222. }
  223. int do_reset_coda_permission_stats( ctl_table * table, int write, 
  224.     struct file * filp, void * buffer, 
  225.     size_t * lenp )
  226. {
  227. if ( write ) {
  228. reset_coda_permission_stats();
  229. filp->f_pos += *lenp;
  230. } else {
  231. *lenp = 0;
  232. }
  233. return 0;
  234. }
  235. int do_reset_coda_cache_inv_stats( ctl_table * table, int write, 
  236.    struct file * filp, void * buffer, 
  237.    size_t * lenp )
  238. {
  239. if ( write ) {
  240. reset_coda_cache_inv_stats();
  241. filp->f_pos += *lenp;
  242. } else {
  243. *lenp = 0;
  244. }
  245.   
  246. return 0;
  247. }
  248. int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
  249.      int length)
  250. {
  251. int len=0;
  252. off_t begin;
  253. struct coda_vfs_stats * ps = & coda_vfs_stat;
  254.   
  255.   /* this works as long as we are below 1024 characters! */
  256. len += sprintf( buffer,
  257. "Coda VFS statisticsn"
  258. "===================nn"
  259. "File Operations:n"
  260. "topentt%9dn"
  261. "tflushtt%9dn"
  262. "treleasett%9dn"
  263. "tfsynctt%9dnn"
  264. "Dir Operations:n"
  265. "treaddirtt%9dnn"
  266. "Inode Operationsn"
  267. "tcreatett%9dn"
  268. "tlookuptt%9dn"
  269. "tlinktt%9dn"
  270. "tunlinktt%9dn"
  271. "tsymlinktt%9dn"
  272. "tmkdirtt%9dn"
  273. "trmdirtt%9dn"
  274. "trenamett%9dn"
  275. "tpermissiont%9dn",
  276. /* file operations */
  277. ps->open,
  278. ps->flush,
  279. ps->release,
  280. ps->fsync,
  281. /* dir operations */
  282. ps->readdir,
  283.   
  284. /* inode operations */
  285. ps->create,
  286. ps->lookup,
  287. ps->link,
  288. ps->unlink,
  289. ps->symlink,
  290. ps->mkdir,
  291. ps->rmdir,
  292. ps->rename,
  293. ps->permission); 
  294. begin = offset;
  295. *start = buffer + begin;
  296. len -= begin;
  297. if ( len > length )
  298. len = length;
  299. if ( len < 0 )
  300. len = 0;
  301. return len;
  302. }
  303. int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
  304. int length)
  305. {
  306. int len=0;
  307. int i;
  308. off_t begin;
  309. off_t pos = 0;
  310. char tmpbuf[80];
  311. int tmplen = 0;
  312. /* this works as long as we are below 1024 characters! */
  313. if ( offset < 80 ) 
  314. len += sprintf( buffer,"%-79sn", "Coda upcall statistics");
  315. if ( offset < 160) 
  316. len += sprintf( buffer + len,"%-79sn", "======================");
  317. if ( offset < 240) 
  318. len += sprintf( buffer + len,"%-79sn", "upcall              count       avg time(us)    std deviation(us)");
  319. if ( offset < 320) 
  320. len += sprintf( buffer + len,"%-79sn", "------              -----       ------------    -----------------");
  321. pos = 320; 
  322. for ( i = 0 ; i < CODA_NCALLS ; i++ ) {
  323. tmplen += sprintf(tmpbuf,"%s    %9d       %10ld      %10ld", 
  324.   coda_upcall_names[i],
  325.   coda_upcall_stat[i].count, 
  326.   get_time_average(&coda_upcall_stat[i]),
  327.   coda_upcall_stat[i].time_squared_sum);
  328. pos += 80;
  329. if ( pos < offset ) 
  330. continue; 
  331. len += sprintf(buffer + len, "%-79sn", tmpbuf);
  332. if ( len >= length ) 
  333. break; 
  334. }
  335.   
  336. begin = len- (pos - offset);
  337. *start = buffer + begin;
  338. len -= begin;
  339. if ( len > length )
  340. len = length;
  341. if ( len < 0 )
  342. len = 0;
  343. return len;
  344. }
  345. int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
  346.     int length)
  347. {
  348. int len=0;
  349. off_t begin;
  350. struct coda_permission_stats * ps = & coda_permission_stat;
  351.   
  352. /* this works as long as we are below 1024 characters! */
  353. len += sprintf( buffer,
  354. "Coda permission statisticsn"
  355. "==========================nn"
  356. "counttt%9dn"
  357. "hit countt%9dn",
  358. ps->count,
  359. ps->hit_count );
  360.   
  361. begin = offset;
  362. *start = buffer + begin;
  363. len -= begin;
  364. if ( len > length )
  365. len = length;
  366. if ( len < 0 )
  367. len = 0;
  368. return len;
  369. }
  370. int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
  371.    int length)
  372. {
  373. int len=0;
  374. off_t begin;
  375. struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
  376.   
  377. /* this works as long as we are below 1024 characters! */
  378. len += sprintf( buffer,
  379. "Coda cache invalidation statisticsn"
  380. "==================================nn"
  381. "flushtt%9dn"
  382. "purge usert%9dn"
  383. "zap_dirtt%9dn"
  384. "zap_filet%9dn"
  385. "zap_vnodet%9dn"
  386. "purge_fidt%9dn"
  387. "replacett%9dn",
  388. ps->flush,
  389. ps->purge_user,
  390. ps->zap_dir,
  391. ps->zap_file,
  392. ps->zap_vnode,
  393. ps->purge_fid,
  394. ps->replace );
  395.   
  396. begin = offset;
  397. *start = buffer + begin;
  398. len -= begin;
  399. if ( len > length )
  400. len = length;
  401. if ( len < 0 )
  402. len = 0;
  403. return len;
  404. }
  405. #ifdef CONFIG_PROC_FS
  406. /*
  407.  target directory structure:
  408.    /proc/fs  (see linux/fs/proc/root.c)
  409.    /proc/fs/coda
  410.    /proc/fs/coda/{vfs_stats,
  411. */
  412. struct proc_dir_entry* proc_fs_coda;
  413. #endif
  414. #define coda_proc_create(name,get_info) 
  415. create_proc_info_entry(name, 0, proc_fs_coda, get_info)
  416. void coda_sysctl_init()
  417. {
  418. memset(&coda_callstats, 0, sizeof(coda_callstats));
  419. reset_coda_vfs_stats();
  420. reset_coda_upcall_stats();
  421. reset_coda_permission_stats();
  422. reset_coda_cache_inv_stats();
  423. #ifdef CONFIG_PROC_FS
  424. proc_fs_coda = proc_mkdir("coda", proc_root_fs);
  425. if (proc_fs_coda) {
  426. proc_fs_coda->owner = THIS_MODULE;
  427. coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
  428. coda_proc_create("upcall_stats", coda_upcall_stats_get_info);
  429. coda_proc_create("permission_stats", coda_permission_stats_get_info);
  430. coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);
  431. }
  432. #endif
  433. #ifdef CONFIG_SYSCTL
  434. if ( !fs_table_header )
  435. fs_table_header = register_sysctl_table(fs_table, 0);
  436. #endif 
  437. }
  438. void coda_sysctl_clean() 
  439. {
  440. #ifdef CONFIG_SYSCTL
  441. if ( fs_table_header ) {
  442. unregister_sysctl_table(fs_table_header);
  443. fs_table_header = 0;
  444. }
  445. #endif
  446. #if CONFIG_PROC_FS
  447.         remove_proc_entry("cache_inv_stats", proc_fs_coda);
  448.         remove_proc_entry("permission_stats", proc_fs_coda);
  449.         remove_proc_entry("upcall_stats", proc_fs_coda);
  450.         remove_proc_entry("vfs_stats", proc_fs_coda);
  451. remove_proc_entry("coda", proc_root_fs);
  452. #endif 
  453. }