sysctl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

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