⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysctl.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
字号:
/* * Sysctl operations for Coda filesystem * Original version: (C) 1996 P. Braam and M. Callahan * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University *  * Carnegie Mellon encourages users to contribute improvements to * the Coda project. Contact Peter Braam (coda@cs.cmu.edu). *  * CODA operation statistics * (c) March, 1998 Zhanyong Wan <zhanyong.wan@yale.edu> * */#include <linux/config.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/sysctl.h>#include <linux/swapctl.h>#include <linux/proc_fs.h>#include <linux/slab.h>#include <linux/stat.h>#include <linux/ctype.h>#include <asm/bitops.h>#include <asm/segment.h>#include <asm/uaccess.h>#include <linux/utsname.h>#define __NO_VERSION__#include <linux/module.h>#include <linux/coda.h>#include <linux/coda_linux.h>#include <linux/coda_fs_i.h>#include <linux/coda_psdev.h>#include <linux/coda_cache.h>#include <linux/coda_proc.h>static struct ctl_table_header *fs_table_header;#define FS_CODA         1       /* Coda file system */#define CODA_DEBUG  	 1	 /* control debugging */#define CODA_ENTRY	 2       /* control enter/leave pattern */#define CODA_TIMEOUT    3       /* timeout on upcalls to become intrble */#define CODA_MC         4       /* use/do not use the access cache */#define CODA_HARD       5       /* mount type "hard" or "soft" */#define CODA_VFS 	 6       /* vfs statistics */#define CODA_UPCALL 	 7       /* upcall statistics */#define CODA_PERMISSION	 8       /* permission statistics */#define CODA_CACHE_INV 	 9       /* cache invalidation statistics */#define CODA_FAKE_STATFS 10	 /* don't query venus for actual cache usage */static ctl_table coda_table[] = {	{CODA_DEBUG, "debug", &coda_debug, sizeof(int), 0644, NULL, &proc_dointvec},	{CODA_ENTRY, "printentry", &coda_print_entry, sizeof(int), 0644, NULL, &proc_dointvec}, 	{CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &proc_dointvec},  	{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, 	{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec}, 	{CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats}, 	{CODA_UPCALL, "upcall_stats", NULL, 0, 0644, NULL, &do_reset_coda_upcall_stats}, 	{CODA_PERMISSION, "permission_stats", NULL, 0, 0644, NULL, &do_reset_coda_permission_stats}, 	{CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats}, 	{CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},	{ 0 }};static ctl_table fs_table[] = {       {FS_CODA, "coda",    NULL, 0, 0555, coda_table},       {0}};struct coda_vfs_stats		coda_vfs_stat;struct coda_permission_stats	coda_permission_stat;struct coda_cache_inv_stats	coda_cache_inv_stat;struct coda_upcall_stats_entry  coda_upcall_stat[CODA_NCALLS];struct coda_upcallstats         coda_callstats;int                             coda_upcall_timestamping = 0;/* keep this in sync with coda.h! */char *coda_upcall_names[] = {	"totals      ",   /*  0 */	"-           ",   /*  1 */	"root        ",   /*  2 */	"open_by_fd  ",   /*  3 */	"open        ",   /*  4 */	"close       ",   /*  5 */	"ioctl       ",   /*  6 */	"getattr     ",   /*  7 */	"setattr     ",   /*  8 */	"access      ",   /*  9 */	"lookup      ",   /* 10 */	"create      ",   /* 11 */	"remove      ",   /* 12 */	"link        ",   /* 13 */	"rename      ",   /* 14 */	"mkdir       ",   /* 15 */	"rmdir       ",   /* 16 */	"readdir     ",   /* 17 */	"symlink     ",   /* 18 */	"readlink    ",   /* 19 */	"fsync       ",   /* 20 */	"-           ",   /* 21 */	"vget        ",   /* 22 */	"signal      ",   /* 23 */	"replace     ",   /* 24 */	"flush       ",   /* 25 */	"purgeuser   ",   /* 26 */	"zapfile     ",   /* 27 */	"zapdir      ",   /* 28 */	"-           ",   /* 29 */	"purgefid    ",   /* 30 */	"open_by_path",   /* 31 */	"resolve     ",   /* 32 */	"reintegrate ",   /* 33 */	"statfs      ",   /* 34 */	"store       ",   /* 35 */	"release     "    /* 36 */};void reset_coda_vfs_stats( void ){	memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );}void reset_coda_upcall_stats( void ){	memset( &coda_upcall_stat, 0, sizeof( coda_upcall_stat ) );}void reset_coda_permission_stats( void ){	memset( &coda_permission_stat, 0, sizeof( coda_permission_stat ) );}void reset_coda_cache_inv_stats( void ){	memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );}void do_time_stats( struct coda_upcall_stats_entry * pentry, 		    unsigned long runtime ){	unsigned long time = runtime;	/* time in us */	CDEBUG(D_SPECIAL, "time: %ld\n", time);	if ( pentry->count == 0 ) {		pentry->time_sum = pentry->time_squared_sum = 0;	}		pentry->count++;	pentry->time_sum += time;	pentry->time_squared_sum += time*time;}void coda_upcall_stats(int opcode, long unsigned runtime) {	struct coda_upcall_stats_entry * pentry;		if ( opcode < 0 || opcode > CODA_NCALLS - 1) {		printk("Nasty opcode %d passed to coda_upcall_stats\n",		       opcode);		return;	}			pentry = &coda_upcall_stat[opcode];	do_time_stats(pentry, runtime);        /* fill in the totals */	pentry = &coda_upcall_stat[0];	do_time_stats(pentry, runtime);}unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry ){	return ( pentry->count == 0 ) ? 0 : pentry->time_sum / pentry->count;}static inline unsigned long absolute( unsigned long x ){	return x >= 0 ? x : -x;}static unsigned long sqr_root( unsigned long x ){	unsigned long y = x, r;	int n_bit = 0;  	if ( x == 0 )		return 0;	if ( x < 0)		x = -x;	while ( y ) {		y >>= 1;		n_bit++;	}  	r = 1 << (n_bit/2);  	while ( 1 ) {		r = (r + x/r)/2;		if ( r*r <= x && x < (r+1)*(r+1) )			break;	}  	return r;}unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry ){	unsigned long time_avg;  	if ( pentry->count <= 1 )		return 0;  	time_avg = get_time_average( pentry );	return sqr_root( (pentry->time_squared_sum / pentry->count) - 			    time_avg * time_avg );}int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,			     void * buffer, size_t * lenp ){	if ( write ) {		reset_coda_vfs_stats();		filp->f_pos += *lenp;	} else {		*lenp = 0;	}	return 0;}int do_reset_coda_upcall_stats( ctl_table * table, int write, 				struct file * filp, void * buffer, 				size_t * lenp ){	if ( write ) {        	if (*lenp > 0) {			char c;                	if (get_user(c, (char *)buffer))			       	return -EFAULT;                        coda_upcall_timestamping = (c == '1');                }		reset_coda_upcall_stats();		filp->f_pos += *lenp;	} else {		*lenp = 0;	}	return 0;}int do_reset_coda_permission_stats( ctl_table * table, int write, 				    struct file * filp, void * buffer, 				    size_t * lenp ){	if ( write ) {		reset_coda_permission_stats();		filp->f_pos += *lenp;	} else {		*lenp = 0;	}	return 0;}int do_reset_coda_cache_inv_stats( ctl_table * table, int write, 				   struct file * filp, void * buffer, 				   size_t * lenp ){	if ( write ) {		reset_coda_cache_inv_stats();		filp->f_pos += *lenp;	} else {		*lenp = 0;	}  	return 0;}int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,			     int length){	int len=0;	off_t begin;	struct coda_vfs_stats * ps = & coda_vfs_stat;    /* this works as long as we are below 1024 characters! */	len += sprintf( buffer,			"Coda VFS statistics\n"			"===================\n\n"			"File Operations:\n"			"\topen\t\t%9d\n"			"\tflush\t\t%9d\n"			"\trelease\t\t%9d\n"			"\tfsync\t\t%9d\n\n"			"Dir Operations:\n"			"\treaddir\t\t%9d\n\n"			"Inode Operations\n"			"\tcreate\t\t%9d\n"			"\tlookup\t\t%9d\n"			"\tlink\t\t%9d\n"			"\tunlink\t\t%9d\n"			"\tsymlink\t\t%9d\n"			"\tmkdir\t\t%9d\n"			"\trmdir\t\t%9d\n"			"\trename\t\t%9d\n"			"\tpermission\t%9d\n",			/* file operations */			ps->open,			ps->flush,			ps->release,			ps->fsync,			/* dir operations */			ps->readdir,		  			/* inode operations */			ps->create,			ps->lookup,			ps->link,			ps->unlink,			ps->symlink,			ps->mkdir,			ps->rmdir,			ps->rename,			ps->permission); 	begin = offset;	*start = buffer + begin;	len -= begin;	if ( len > length )		len = length;	if ( len < 0 )		len = 0;	return len;}int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,				int length){	int len=0;	int i;	off_t begin;	off_t pos = 0;	char tmpbuf[80];	int tmplen = 0;	/* this works as long as we are below 1024 characters! */	if ( offset < 80 ) 		len += sprintf( buffer,"%-79s\n",	"Coda upcall statistics");	if ( offset < 160) 		len += sprintf( buffer + len,"%-79s\n",	"======================");	if ( offset < 240) 		len += sprintf( buffer + len,"%-79s\n",	"upcall              count       avg time(us)    std deviation(us)");	if ( offset < 320) 		len += sprintf( buffer + len,"%-79s\n",	"------              -----       ------------    -----------------");	pos = 320; 	for ( i = 0 ; i < CODA_NCALLS ; i++ ) {		tmplen += sprintf(tmpbuf,"%s    %9d       %10ld      %10ld", 				  coda_upcall_names[i],				  coda_upcall_stat[i].count, 				  get_time_average(&coda_upcall_stat[i]),				  coda_upcall_stat[i].time_squared_sum);		pos += 80;		if ( pos < offset ) 			continue; 		len += sprintf(buffer + len, "%-79s\n", tmpbuf);		if ( len >= length ) 			break; 	}  	begin = len- (pos - offset);	*start = buffer + begin;	len -= begin;	if ( len > length )		len = length;	if ( len < 0 )		len = 0;	return len;}int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,				    int length){	int len=0;	off_t begin;	struct coda_permission_stats * ps = & coda_permission_stat;  	/* this works as long as we are below 1024 characters! */	len += sprintf( buffer,			"Coda permission statistics\n"			"==========================\n\n"			"count\t\t%9d\n"			"hit count\t%9d\n",			ps->count,			ps->hit_count );  	begin = offset;	*start = buffer + begin;	len -= begin;	if ( len > length )		len = length;	if ( len < 0 )		len = 0;	return len;}int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,				   int length){	int len=0;	off_t begin;	struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;  	/* this works as long as we are below 1024 characters! */	len += sprintf( buffer,			"Coda cache invalidation statistics\n"			"==================================\n\n"			"flush\t\t%9d\n"			"purge user\t%9d\n"			"zap_dir\t\t%9d\n"			"zap_file\t%9d\n"			"zap_vnode\t%9d\n"			"purge_fid\t%9d\n"			"replace\t\t%9d\n",			ps->flush,			ps->purge_user,			ps->zap_dir,			ps->zap_file,			ps->zap_vnode,			ps->purge_fid,			ps->replace );  	begin = offset;	*start = buffer + begin;	len -= begin;	if ( len > length )		len = length;	if ( len < 0 )		len = 0;	return len;}#ifdef CONFIG_PROC_FS/* target directory structure:   /proc/fs  (see linux/fs/proc/root.c)   /proc/fs/coda   /proc/fs/coda/{vfs_stats,*/struct proc_dir_entry* proc_fs_coda;#endif#define coda_proc_create(name,get_info) \	create_proc_info_entry(name, 0, proc_fs_coda, get_info)void coda_sysctl_init(){	memset(&coda_callstats, 0, sizeof(coda_callstats));	reset_coda_vfs_stats();	reset_coda_upcall_stats();	reset_coda_permission_stats();	reset_coda_cache_inv_stats();#ifdef CONFIG_PROC_FS	proc_fs_coda = proc_mkdir("coda", proc_root_fs);	if (proc_fs_coda) {		proc_fs_coda->owner = THIS_MODULE;		coda_proc_create("vfs_stats", coda_vfs_stats_get_info);		coda_proc_create("upcall_stats", coda_upcall_stats_get_info);		coda_proc_create("permission_stats", coda_permission_stats_get_info);		coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);	}#endif#ifdef CONFIG_SYSCTL	if ( !fs_table_header )		fs_table_header = register_sysctl_table(fs_table, 0);#endif }void coda_sysctl_clean() {#ifdef CONFIG_SYSCTL	if ( fs_table_header ) {		unregister_sysctl_table(fs_table_header);		fs_table_header = 0;	}#endif#if CONFIG_PROC_FS        remove_proc_entry("cache_inv_stats", proc_fs_coda);        remove_proc_entry("permission_stats", proc_fs_coda);        remove_proc_entry("upcall_stats", proc_fs_coda);        remove_proc_entry("vfs_stats", proc_fs_coda);	remove_proc_entry("coda", proc_root_fs);#endif }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -