diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-06-30 00:21:34 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-06-30 00:21:34 +0000 |
commit | 3917ac5846dd0f9ad1238166f90caab9912052e6 (patch) | |
tree | 1c298935def4f29edb39192365a65d73de999155 /fs/coda | |
parent | af2f803c8b2d469fe38e4a7ce952658dfcb6681a (diff) |
o Merge with Linux 2.1.100.
o Cleanup the machine dependencies of floppy and rtc. The driver for
the Dallas thingy in the Indy is still missing.
o Handle allocation of zero'd pages correct for R4000SC / R4400SC.
o Page colouring shit to match the virtual and physical colour of all
mapped pages. This tends to produce extreme fragmentation problems,
so it's deactivated for now. Users of R4000SC / R4400SC may re-enable
the code in arch/mips/mm/init.c by removing the definition of
CONF_GIVE_A_SHIT_ABOUT_COLOURS. Should get them somewhat further -
but don't shake to hard ...
o Fixed ptrace(2)-ing of syscalls, strace is now working again.
o Fix the interrupt forwarding from the keyboard driver to the psaux
driver, PS/2 mice are now working on the Indy. The fix is somewhat
broken as it prevents generic kernels for Indy and machines which handle
things different.
o Things I can't remember.
Diffstat (limited to 'fs/coda')
-rw-r--r-- | fs/coda/Makefile | 2 | ||||
-rw-r--r-- | fs/coda/cache.c | 41 | ||||
-rw-r--r-- | fs/coda/coda_linux.c | 1 | ||||
-rw-r--r-- | fs/coda/dir.c | 18 | ||||
-rw-r--r-- | fs/coda/file.c | 10 | ||||
-rw-r--r-- | fs/coda/psdev.c | 135 | ||||
-rw-r--r-- | fs/coda/stats.c | 416 | ||||
-rw-r--r-- | fs/coda/symlink.c | 7 | ||||
-rw-r--r-- | fs/coda/sysctl.c | 10 | ||||
-rw-r--r-- | fs/coda/upcall.c | 38 |
10 files changed, 610 insertions, 68 deletions
diff --git a/fs/coda/Makefile b/fs/coda/Makefile index 1f2d0a94c..4e6c40dce 100644 --- a/fs/coda/Makefile +++ b/fs/coda/Makefile @@ -4,7 +4,7 @@ O_TARGET := coda.o O_OBJS := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o coda_linux.o\ - symlink.o pioctl.o sysctl.o + symlink.o pioctl.o sysctl.o stats.o M_OBJS := $(O_TARGET) # If you want debugging output, please uncomment the following line diff --git a/fs/coda/cache.c b/fs/coda/cache.c index cdf586507..1285ac757 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c @@ -32,9 +32,6 @@ static void coda_cache_create(struct inode *inode, int mask); static struct coda_cache * coda_cache_find(struct inode *inode); -/* Keep various stats */ -struct cfsnc_statistics cfsnc_stat; - /* insert a acl-cache entry in sb list */ static void coda_ccinsert(struct coda_cache *el, struct super_block *sb) { @@ -295,41 +292,3 @@ void coda_flag_inode(struct inode *inode, int flag) -int -cfsnc_nc_info(char *buffer, char **start, off_t offset, int length, int dummy) -{ - int len=0; - off_t begin; - - /* cfsnc_gather_stats(); */ - - /* this works as long as we are below 1024 characters! */ - len += sprintf(buffer,"Coda minicache statistics\n\n"); - len += sprintf(buffer+len, "cfsnc_hits : %d\n", cfsnc_stat.hits); - len += sprintf(buffer+len, "cfsnc_misses : %d\n", cfsnc_stat.misses); - len += sprintf(buffer+len, "cfsnc_enters : %d\n", cfsnc_stat.enters); - len += sprintf(buffer+len, "cfsnc_dbl_enters : %d\n", cfsnc_stat.dbl_enters); - len += sprintf(buffer+len, "cfsnc_long_name_enters : %d\n", cfsnc_stat.long_name_enters); - len += sprintf(buffer+len, "cfsnc_long_name_lookups : %d\n", cfsnc_stat.long_name_lookups); - len += sprintf(buffer+len, "cfsnc_long_remove : %d\n", cfsnc_stat.long_remove); - len += sprintf(buffer+len, "cfsnc_lru_rm : %d\n", cfsnc_stat.lru_rm); - len += sprintf(buffer+len, "cfsnc_zapPfids : %d\n", cfsnc_stat.zapPfids); - len += sprintf(buffer+len, "cfsnc_zapFids : %d\n", cfsnc_stat.zapFids); - len += sprintf(buffer+len, "cfsnc_zapFile : %d\n", cfsnc_stat.zapFile); - len += sprintf(buffer+len, "cfsnc_zapUsers : %d\n", cfsnc_stat.zapUsers); - len += sprintf(buffer+len, "cfsnc_Flushes : %d\n", cfsnc_stat.Flushes); - len += sprintf(buffer+len, "cfsnc_SumLen : %d\n", cfsnc_stat.Sum_bucket_len); - len += sprintf(buffer+len, "cfsnc_Sum2Len : %d\n", cfsnc_stat.Sum2_bucket_len); - len += sprintf(buffer+len, "cfsnc_# 0 len : %d\n", cfsnc_stat.Num_zero_len); - len += sprintf(buffer+len, "cfsnc_MaxLen : %d\n", cfsnc_stat.Max_bucket_len); - len += sprintf(buffer+len, "cfsnc_SearchLen : %d\n", cfsnc_stat.Search_len); - begin = offset; - *start = buffer + begin; - len -= begin; - - if(len>length) - len = length; - if (len< 0) - len = 0; - return len; -} diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c index 4fe096df9..322b764a9 100644 --- a/fs/coda/coda_linux.c +++ b/fs/coda/coda_linux.c @@ -7,6 +7,7 @@ * the Coda project. Contact Peter Braam (coda@cs.cmu.edu). */ +#include <linux/version.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 8fed69242..ba0ec6e2f 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -23,6 +23,7 @@ #include <linux/coda_psdev.h> #include <linux/coda_fs_i.h> #include <linux/coda_cache.h> +#include <linux/coda_proc.h> /* dir inode-ops */ static int coda_create(struct inode *dir, struct dentry *new, int mode); @@ -179,6 +180,8 @@ int coda_permission(struct inode *inode, int mask) int error; ENTRY; + coda_vfs_stat.permission++; + coda_permission_stat.count++; if ( mask == 0 ) { EXIT; @@ -187,6 +190,7 @@ int coda_permission(struct inode *inode, int mask) if ( coda_access_cache == 1 ) { if ( coda_cache_check(inode, mask) ) { + coda_permission_stat.hit_count++; return 0; } } @@ -221,6 +225,8 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode) struct ViceFid newfid; struct coda_vattr attrs; + coda_vfs_stat.create++; + CDEBUG(D_INODE, "name: %s, length %d, mode %o\n",name, length, mode); if (!dir || !S_ISDIR(dir->i_mode)) { @@ -274,6 +280,8 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) struct ViceFid newfid; + coda_vfs_stat.mkdir++; + if (!dir || !S_ISDIR(dir->i_mode)) { printk("coda_mkdir: inode is NULL or not a directory\n"); return -ENOENT; @@ -329,6 +337,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, int error; ENTRY; + coda_vfs_stat.link++; if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) return -EPERM; @@ -373,6 +382,7 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de, int error=0; ENTRY; + coda_vfs_stat.symlink++; if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) return -EPERM; @@ -414,6 +424,7 @@ int coda_unlink(struct inode *dir, struct dentry *de) int len = de->d_name.len; ENTRY; + coda_vfs_stat.unlink++; dircnp = ITOC(dir); CHECK_CNODE(dircnp); @@ -446,6 +457,8 @@ int coda_rmdir(struct inode *dir, struct dentry *de) int len = de->d_name.len; int error, rehash = 0; + coda_vfs_stat.rmdir++; + if (!dir || !S_ISDIR(dir->i_mode)) { printk("coda_rmdir: inode is NULL or not a directory\n"); return -ENOENT; @@ -502,6 +515,8 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, struct coda_inode_info *new_cnp, *old_cnp; int error, rehash = 0, update = 1; ENTRY; + coda_vfs_stat.rename++; + old_cnp = ITOC(old_dir); CHECK_CNODE(old_cnp); new_cnp = ITOC(new_dir); @@ -565,6 +580,7 @@ int coda_readdir(struct file *file, void *dirent, filldir_t filldir) struct inode *inode=file->f_dentry->d_inode; ENTRY; + coda_vfs_stat.readdir++; if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) { printk("coda_readdir: inode is NULL or not a directory\n"); @@ -606,6 +622,7 @@ int coda_open(struct inode *i, struct file *f) unsigned short coda_flags = coda_flags_to_cflags(flags); ENTRY; + coda_vfs_stat.open++; CDEBUG(D_SPECIAL, "OPEN inode number: %ld, flags %o.\n", f->f_dentry->d_inode->i_ino, flags); @@ -659,6 +676,7 @@ int coda_release(struct inode *i, struct file *f) unsigned short cflags = coda_flags_to_cflags(flags); ENTRY; + coda_vfs_stat.release++; cnp =ITOC(i); CHECK_CNODE(cnp); diff --git a/fs/coda/file.c b/fs/coda/file.c index ae1dd9776..c92aeeb27 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -23,6 +23,7 @@ #include <linux/coda_fs_i.h> #include <linux/coda_psdev.h> #include <linux/coda_cache.h> +#include <linux/coda_proc.h> /* file operations */ static int coda_readpage(struct file *file, struct page * page); @@ -83,6 +84,7 @@ static int coda_readpage(struct file * coda_file, struct page * page) struct coda_inode_info *cii; ENTRY; + coda_vfs_stat.readpage++; cii = ITOC(coda_inode); @@ -108,6 +110,8 @@ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma) struct coda_inode_info *cii; int res; + coda_vfs_stat.file_mmap++; + ENTRY; cii = ITOC(file->f_dentry->d_inode); cii->c_mmcount++; @@ -126,7 +130,9 @@ static ssize_t coda_file_read(struct file *coda_file, char *buff, struct file cont_file; struct dentry cont_dentry; int result = 0; - ENTRY; + + ENTRY; + coda_vfs_stat.file_read++; cnp = ITOC(coda_inode); CHECK_CNODE(cnp); @@ -167,6 +173,7 @@ static ssize_t coda_file_write(struct file *coda_file, const char *buff, int result = 0; ENTRY; + coda_vfs_stat.file_write++; cnp = ITOC(coda_inode); CHECK_CNODE(cnp); @@ -205,6 +212,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry) struct dentry cont_dentry; int result = 0; ENTRY; + coda_vfs_stat.fsync++; if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) || S_ISLNK(coda_inode->i_mode))) diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 119d14f51..e3ce5b39f 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -44,7 +44,7 @@ #include <linux/coda_fs_i.h> #include <linux/coda_psdev.h> #include <linux/coda_cache.h> -#include <linux/coda_sysctl.h> +#include <linux/coda_proc.h> /* @@ -401,19 +401,106 @@ static struct file_operations coda_psdev_fops = { #ifdef CONFIG_PROC_FS -struct proc_dir_entry proc_coda = { +struct proc_dir_entry proc_sys_root = { + PROC_SYS, 3, "sys", /* inode, name */ + S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, /* mode, nlink, uid, gid */ + 0, &proc_dir_inode_operations, /* size, ops */ + NULL, NULL, /* get_info, fill_inode */ + NULL, /* next */ + NULL, NULL /* parent, subdir */ +}; + +struct proc_dir_entry proc_fs_coda = { + PROC_FS_CODA, 4, "coda", + S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, + 0, &proc_dir_inode_operations, + NULL, NULL, + NULL, + NULL, NULL +}; + +struct proc_dir_entry proc_sys_coda = { 0, 4, "coda", - S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR, 2, 0, 0, - 0, &proc_net_inode_operations, + S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, + 0, &proc_dir_inode_operations, + NULL, NULL, + NULL, + NULL, NULL +}; +struct proc_dir_entry proc_fs = { + PROC_FS, 2, "fs", + S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, + 0, &proc_dir_inode_operations, + NULL, NULL, + NULL, + NULL, NULL }; +#if 0 struct proc_dir_entry proc_coda_ncstats = { 0 , 12, "coda-ncstats", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, cfsnc_nc_info }; +#endif + +struct proc_dir_entry proc_coda_vfs = { + PROC_VFS_STATS , 9, "vfs_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_vfs_stats_get_info + }; + +struct proc_dir_entry proc_coda_vfs_control = { + 0 , 9, "vfs_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_vfs_stats_get_info + }; + +struct proc_dir_entry proc_coda_upcall = { + PROC_UPCALL_STATS , 12, "upcall_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_upcall_stats_get_info + }; + +struct proc_dir_entry proc_coda_upcall_control = { + 0 , 12, "upcall_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_upcall_stats_get_info + }; + +struct proc_dir_entry proc_coda_permission = { + PROC_PERMISSION_STATS , 16, "permission_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_permission_stats_get_info + }; + +struct proc_dir_entry proc_coda_permission_control = { + 0 , 16, "permission_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_permission_stats_get_info + }; + +struct proc_dir_entry proc_coda_cache_inv = { + PROC_CACHE_INV_STATS , 15, "cache_inv_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_cache_inv_stats_get_info + }; + +struct proc_dir_entry proc_coda_cache_inv_control = { + 0 , 15, "cache_inv_stats", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + coda_cache_inv_stats_get_info + }; #endif @@ -429,9 +516,27 @@ int init_coda_psdev(void) memset(coda_super_info, 0, sizeof(coda_super_info)); 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_register(&proc_root,&proc_coda); - proc_register(&proc_coda, &proc_coda_ncstats); + proc_register(&proc_root,&proc_fs); + proc_register(&proc_fs,&proc_fs_coda); + proc_register(&proc_fs_coda,&proc_coda_vfs); + proc_register(&proc_fs_coda,&proc_coda_upcall); + proc_register(&proc_fs_coda,&proc_coda_permission); + proc_register(&proc_fs_coda,&proc_coda_cache_inv); +#if 0 + proc_register(&proc_fs_coda, &proc_coda_ncstats); +#endif + proc_register(&proc_sys_root,&proc_sys_coda); + proc_register(&proc_sys_coda,&proc_coda_vfs_control); + proc_register(&proc_sys_coda,&proc_coda_upcall_control); + proc_register(&proc_sys_coda,&proc_coda_permission_control); + proc_register(&proc_sys_coda,&proc_coda_cache_inv_control); + coda_sysctl_init(); #endif return 0; @@ -476,8 +581,22 @@ void cleanup_module(void) #if CONFIG_PROC_FS coda_sysctl_clean(); - proc_unregister(&proc_coda, proc_coda_ncstats.low_ino); - proc_unregister(&proc_root, proc_coda.low_ino); + + proc_unregister(&proc_sys_coda, proc_coda_cache_inv_control.low_ino); + proc_unregister(&proc_sys_coda, proc_coda_permission_control.low_ino); + proc_unregister(&proc_sys_coda, proc_coda_upcall_control.low_ino); + proc_unregister(&proc_sys_coda,proc_coda_vfs_control.low_ino); + proc_unregister(&proc_sys_root, proc_sys_coda.low_ino); + +#if 0 + proc_unregister(&proc_fs_coda, proc_coda_ncstats.low_ino); +#endif + proc_unregister(&proc_fs_coda, proc_coda_cache_inv.low_ino); + proc_unregister(&proc_fs_coda, proc_coda_permission.low_ino); + proc_unregister(&proc_fs_coda, proc_coda_upcall.low_ino); + proc_unregister(&proc_fs_coda, proc_coda_vfs.low_ino); + proc_unregister(&proc_fs, proc_fs_coda.low_ino); + proc_unregister(&proc_root, proc_fs.low_ino); #endif } diff --git a/fs/coda/stats.c b/fs/coda/stats.c new file mode 100644 index 000000000..1b55b8ea7 --- /dev/null +++ b/fs/coda/stats.c @@ -0,0 +1,416 @@ +/* + * stats.c + * + * CODA operation statistics + * + * (c) March, 1998 Zhanyong Wan <zhanyong.wan@yale.edu> + * + */ + +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/sysctl.h> +#include <linux/swapctl.h> +#include <linux/proc_fs.h> +#include <linux/malloc.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> + +#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> + +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[CFS_NCALLS]; + +/* keep this in sync with coda.h! */ +char *coda_upcall_names[] = { + "totals ", /* 0 */ + "noop ", /* 1 */ + "root ", /* 2 */ + "sync ", /* 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 */ + "inactive ", /* 21 */ + "vget ", /* 22 */ + "signal ", /* 23 */ + "replace ", /* 24 */ + "flush ", /* 25 */ + "purgeuser ", /* 26 */ + "zapfile ", /* 27 */ + "zapdir ", /* 28 */ + "zapvnode ", /* 28 */ + "purgefid ", /* 30 */ + "open_by_path" /* 31 */ +}; + + + + +void reset_coda_vfs_stats( void ) +{ + memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) ); +} + +#if 0 +static void reset_upcall_entry( struct coda_upcall_stats_entry * pentry ) +{ + pentry->count = 0; + pentry->time_sum = pentry->time_squared_sum = 0; +} +#endif + +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 * 1000 /HZ; /* time in ms */ + 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 > CFS_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(); + } + + *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 ) { + reset_coda_upcall_stats(); + } + + *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(); + } + + *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(); + } + + *lenp = 0; + return 0; +} + +int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, + int length, int dummy ) +{ + 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" + "\tfile_read\t%9d\n" + "\tfile_write\t%9d\n" + "\tfile_mmap\t%9d\n" + "\topen\t\t%9d\n" + "\trelase\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" + "\treadpage\t%9d\n", + + /* file operations */ + ps->file_read, + ps->file_write, + ps->file_mmap, + ps->open, + 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, + ps->readpage ); + + 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 dummy ) +{ + int len=0; + int i; + off_t begin; + off_t pos = 0; + char tmpbuf[80]; + int tmplen = 0; + + ENTRY; + /* 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\t\t count\tavg time(ms)\tstd deviation(ms)"); + if ( offset < 320) + len += sprintf( buffer + len,"%-79s\n", "------\t\t -----\t------------\t-----------------"); + pos = 320; + for ( i = 0 ; i < CFS_NCALLS ; i++ ) { + tmplen += sprintf(tmpbuf,"%s\t%9d\t%10ld\t%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; + EXIT; + return len; +} + +int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset, + int length, int dummy ) +{ + 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 dummy ) +{ + 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; +} + diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c index c6d770a20..eb2fe150d 100644 --- a/fs/coda/symlink.c +++ b/fs/coda/symlink.c @@ -23,6 +23,7 @@ #include <linux/coda_psdev.h> #include <linux/coda_fs_i.h> #include <linux/coda_cache.h> +#include <linux/coda_proc.h> static int coda_readlink(struct dentry *de, char *buffer, int length); static struct dentry *coda_follow_link(struct dentry *, struct dentry *); @@ -60,7 +61,7 @@ static int coda_readlink(struct dentry *de, char *buffer, int length) ENTRY; cp = ITOC(inode); - CHECK_CNODE(cp); + coda_vfs_stat.readlink++; /* the maximum length we receive is len */ if ( length > CFS_MAXPATHLEN ) @@ -93,11 +94,11 @@ static struct dentry *coda_follow_link(struct dentry *de, unsigned int len; char mem[CFS_MAXPATHLEN]; char *path; -ENTRY; + ENTRY; CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino); cnp = ITOC(inode); - CHECK_CNODE(cnp); + coda_vfs_stat.follow_link++; len = CFS_MAXPATHLEN; error = venus_readlink(inode->i_sb, &(cnp->c_fid), mem, &len); diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index c21016030..36e327dce 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -26,7 +26,7 @@ #include <linux/coda_fs_i.h> #include <linux/coda_psdev.h> #include <linux/coda_cache.h> -#include <linux/coda_sysctl.h> +#include <linux/coda_proc.h> extern int coda_debug; /* extern int cfsnc_use; */ extern int coda_print_entry; @@ -47,6 +47,10 @@ struct ctl_table_header *fs_table_header, *coda_table_header; #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 */ @@ -56,6 +60,10 @@ static ctl_table coda_table[] = { {CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &coda_dointvec}, {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &coda_dointvec}, {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &coda_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}, { 0 } }; diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 13d3127c6..0e3ba95d1 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -37,6 +37,11 @@ #include <linux/coda_psdev.h> #include <linux/coda_fs_i.h> #include <linux/coda_cache.h> +#include <linux/coda_proc.h> + + +static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, + union inputArgs *buffer); #define UPARG(op)\ do {\ @@ -68,10 +73,11 @@ int venus_rootfid(struct super_block *sb, ViceFid *fidp) union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; -ENTRY; + ENTRY; insize = SIZE(root); UPARG(CFS_ROOT); + error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); if (error) { @@ -92,7 +98,7 @@ int venus_getattr(struct super_block *sb, struct ViceFid *fid, { union inputArgs *inp; union outputArgs *outp; - int insize, outsize, error; + int insize, outsize, error; ENTRY; insize = SIZE(getattr); UPARG(CFS_GETATTR); @@ -458,8 +464,8 @@ int venus_symlink(struct super_block *sb, struct ViceFid *fid, int venus_fsync(struct super_block *sb, struct ViceFid *fid) { union inputArgs *inp; - union outputArgs *outp; - int insize, outsize, error; + union outputArgs *outp; + int insize, outsize, error; insize=SIZE(fsync); UPARG(CFS_FSYNC); @@ -476,8 +482,8 @@ int venus_fsync(struct super_block *sb, struct ViceFid *fid) int venus_access(struct super_block *sb, struct ViceFid *fid, int mask) { union inputArgs *inp; - union outputArgs *outp; - int insize, outsize, error; + union outputArgs *outp; + int insize, outsize, error; insize = SIZE(access); UPARG(CFS_ACCESS); @@ -497,8 +503,8 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid, unsigned int cmd, struct PioctlData *data) { union inputArgs *inp; - union outputArgs *outp; - int insize, outsize, error; + union outputArgs *outp; + int insize, outsize, error; int iocsize; insize = VC_MAXMSGSIZE; @@ -583,11 +589,13 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid, * reply and return Venus' error, also POSITIVE. * */ -static inline void coda_waitfor_upcall(struct vmsg *vmp) +static inline unsigned long coda_waitfor_upcall(struct vmsg *vmp) { struct wait_queue wait = { current, NULL }; + unsigned long posttime; vmp->vm_posttime = jiffies; + posttime = jiffies; add_wait_queue(&vmp->vm_sleep, &wait); for (;;) { @@ -616,13 +624,17 @@ static inline void coda_waitfor_upcall(struct vmsg *vmp) remove_wait_queue(&vmp->vm_sleep, &wait); current->state = TASK_RUNNING; - return; + CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n", posttime, jiffies-posttime); + return (jiffies - posttime); + } -int coda_upcall(struct coda_sb_info *sbi, int inSize, int *outSize, +static int coda_upcall(struct coda_sb_info *sbi, + int inSize, int *outSize, union inputArgs *buffer) { + unsigned long runtime; struct vcomm *vcommp; union outputArgs *out; struct vmsg *vmp; @@ -635,7 +647,6 @@ ENTRY; } vcommp = sbi->sbi_vcomm; - clstats(((union inputArgs *)buffer)->ih.opcode); if (!vcomm_open(vcommp)) return(ENODEV); @@ -670,7 +681,8 @@ ENTRY; * ENODEV. */ /* Go to sleep. Wake up on signals only after the timeout. */ - coda_waitfor_upcall(vmp); + runtime = coda_waitfor_upcall(vmp); + coda_upcall_stats(((union inputArgs *)buffer)->ih.opcode, runtime); CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n", vmp->vm_opcode, jiffies - vmp->vm_posttime, |