summaryrefslogtreecommitdiffstats
path: root/fs/coda
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
commit3917ac5846dd0f9ad1238166f90caab9912052e6 (patch)
tree1c298935def4f29edb39192365a65d73de999155 /fs/coda
parentaf2f803c8b2d469fe38e4a7ce952658dfcb6681a (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/Makefile2
-rw-r--r--fs/coda/cache.c41
-rw-r--r--fs/coda/coda_linux.c1
-rw-r--r--fs/coda/dir.c18
-rw-r--r--fs/coda/file.c10
-rw-r--r--fs/coda/psdev.c135
-rw-r--r--fs/coda/stats.c416
-rw-r--r--fs/coda/symlink.c7
-rw-r--r--fs/coda/sysctl.c10
-rw-r--r--fs/coda/upcall.c38
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,