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 14 #include <linux/time.h> 15 #include <linux/mm.h> 16 #include <linux/sysctl.h> 17 #include <linux/proc_fs.h> 18 #include <linux/seq_file.h> 19 #include <linux/slab.h> 20 #include <linux/stat.h> 21 #include <linux/ctype.h> 22 #include <linux/bitops.h> 23 #include <asm/uaccess.h> 24 #include <linux/utsname.h> 25 #include <linux/module.h> 26 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 34 static struct ctl_table_header *fs_table_header; 35 36 #define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */ 37 #define CODA_HARD 5 /* mount type "hard" or "soft" */ 38 #define CODA_VFS 6 /* vfs statistics */ 39 #define CODA_CACHE_INV 9 /* cache invalidation statistics */ 40 #define CODA_FAKE_STATFS 10 /* don't query venus for actual cache usage */ 41 42 struct coda_vfs_stats coda_vfs_stat; 43 static struct coda_cache_inv_stats coda_cache_inv_stat; 44 45 static void reset_coda_vfs_stats( void ) 46 { 47 memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) ); 48 } 49 50 static void reset_coda_cache_inv_stats( void ) 51 { 52 memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) ); 53 } 54 55 static int do_reset_coda_vfs_stats( ctl_table * table, int write, 56 struct file * filp, void __user * buffer, 57 size_t * lenp, loff_t * ppos ) 58 { 59 if ( write ) { 60 reset_coda_vfs_stats(); 61 62 *ppos += *lenp; 63 } else { 64 *lenp = 0; 65 } 66 67 return 0; 68 } 69 70 static int do_reset_coda_cache_inv_stats( ctl_table * table, int write, 71 struct file * filp, 72 void __user * buffer, 73 size_t * lenp, loff_t * ppos ) 74 { 75 if ( write ) { 76 reset_coda_cache_inv_stats(); 77 78 *ppos += *lenp; 79 } else { 80 *lenp = 0; 81 } 82 83 return 0; 84 } 85 86 static int proc_vfs_stats_show(struct seq_file *m, void *v) 87 { 88 struct coda_vfs_stats * ps = & coda_vfs_stat; 89 90 seq_printf(m, 91 "Coda VFS statistics\n" 92 "===================\n\n" 93 "File Operations:\n" 94 "\topen\t\t%9d\n" 95 "\tflush\t\t%9d\n" 96 "\trelease\t\t%9d\n" 97 "\tfsync\t\t%9d\n\n" 98 "Dir Operations:\n" 99 "\treaddir\t\t%9d\n\n" 100 "Inode Operations\n" 101 "\tcreate\t\t%9d\n" 102 "\tlookup\t\t%9d\n" 103 "\tlink\t\t%9d\n" 104 "\tunlink\t\t%9d\n" 105 "\tsymlink\t\t%9d\n" 106 "\tmkdir\t\t%9d\n" 107 "\trmdir\t\t%9d\n" 108 "\trename\t\t%9d\n" 109 "\tpermission\t%9d\n", 110 111 /* file operations */ 112 ps->open, 113 ps->flush, 114 ps->release, 115 ps->fsync, 116 117 /* dir operations */ 118 ps->readdir, 119 120 /* inode operations */ 121 ps->create, 122 ps->lookup, 123 ps->link, 124 ps->unlink, 125 ps->symlink, 126 ps->mkdir, 127 ps->rmdir, 128 ps->rename, 129 ps->permission); 130 return 0; 131 } 132 133 static int proc_cache_inv_stats_show(struct seq_file *m, void *v) 134 { 135 struct coda_cache_inv_stats * ps = & coda_cache_inv_stat; 136 137 seq_printf(m, 138 "Coda cache invalidation statistics\n" 139 "==================================\n\n" 140 "flush\t\t%9d\n" 141 "purge user\t%9d\n" 142 "zap_dir\t\t%9d\n" 143 "zap_file\t%9d\n" 144 "zap_vnode\t%9d\n" 145 "purge_fid\t%9d\n" 146 "replace\t\t%9d\n", 147 ps->flush, 148 ps->purge_user, 149 ps->zap_dir, 150 ps->zap_file, 151 ps->zap_vnode, 152 ps->purge_fid, 153 ps->replace ); 154 return 0; 155 } 156 157 static int proc_vfs_stats_open(struct inode *inode, struct file *file) 158 { 159 return single_open(file, proc_vfs_stats_show, NULL); 160 } 161 162 static int proc_cache_inv_stats_open(struct inode *inode, struct file *file) 163 { 164 return single_open(file, proc_cache_inv_stats_show, NULL); 165 } 166 167 static const struct file_operations proc_vfs_stats_fops = { 168 .owner = THIS_MODULE, 169 .open = proc_vfs_stats_open, 170 .read = seq_read, 171 .llseek = seq_lseek, 172 .release = single_release, 173 }; 174 175 static const struct file_operations proc_cache_inv_stats_fops = { 176 .owner = THIS_MODULE, 177 .open = proc_cache_inv_stats_open, 178 .read = seq_read, 179 .llseek = seq_lseek, 180 .release = single_release, 181 }; 182 183 static ctl_table coda_table[] = { 184 { 185 .ctl_name = CTL_UNNUMBERED, 186 .procname = "timeout", 187 .data = &coda_timeout, 188 .maxlen = sizeof(int), 189 .mode = 0644, 190 .proc_handler = &proc_dointvec 191 }, 192 { 193 .ctl_name = CTL_UNNUMBERED, 194 .procname = "hard", 195 .data = &coda_hard, 196 .maxlen = sizeof(int), 197 .mode = 0644, 198 .proc_handler = &proc_dointvec 199 }, 200 { 201 .ctl_name = CTL_UNNUMBERED, 202 .procname = "vfs_stats", 203 .data = NULL, 204 .maxlen = 0, 205 .mode = 0644, 206 .proc_handler = &do_reset_coda_vfs_stats 207 }, 208 { 209 .ctl_name = CTL_UNNUMBERED, 210 .procname = "cache_inv_stats", 211 .data = NULL, 212 .maxlen = 0, 213 .mode = 0644, 214 .proc_handler = &do_reset_coda_cache_inv_stats 215 }, 216 { 217 .ctl_name = CTL_UNNUMBERED, 218 .procname = "fake_statfs", 219 .data = &coda_fake_statfs, 220 .maxlen = sizeof(int), 221 .mode = 0600, 222 .proc_handler = &proc_dointvec 223 }, 224 {} 225 }; 226 227 static ctl_table fs_table[] = { 228 { 229 .ctl_name = CTL_UNNUMBERED, 230 .procname = "coda", 231 .mode = 0555, 232 .child = coda_table 233 }, 234 {} 235 }; 236 237 238 #ifdef CONFIG_PROC_FS 239 240 /* 241 target directory structure: 242 /proc/fs (see linux/fs/proc/root.c) 243 /proc/fs/coda 244 /proc/fs/coda/{vfs_stats, 245 246 */ 247 248 static struct proc_dir_entry* proc_fs_coda; 249 250 #endif 251 252 void coda_sysctl_init(void) 253 { 254 reset_coda_vfs_stats(); 255 reset_coda_cache_inv_stats(); 256 257 #ifdef CONFIG_PROC_FS 258 proc_fs_coda = proc_mkdir("coda", proc_root_fs); 259 if (proc_fs_coda) { 260 struct proc_dir_entry *pde; 261 262 proc_fs_coda->owner = THIS_MODULE; 263 pde = create_proc_entry("vfs_stats", 0, proc_fs_coda); 264 if (pde) 265 pde->proc_fops = &proc_vfs_stats_fops; 266 pde = create_proc_entry("cache_inv_stats", 0, proc_fs_coda); 267 if (pde) 268 pde->proc_fops = &proc_cache_inv_stats_fops; 269 } 270 #endif 271 272 #ifdef CONFIG_SYSCTL 273 if ( !fs_table_header ) 274 fs_table_header = register_sysctl_table(fs_table); 275 #endif 276 } 277 278 void coda_sysctl_clean(void) 279 { 280 281 #ifdef CONFIG_SYSCTL 282 if ( fs_table_header ) { 283 unregister_sysctl_table(fs_table_header); 284 fs_table_header = NULL; 285 } 286 #endif 287 288 #ifdef CONFIG_PROC_FS 289 remove_proc_entry("cache_inv_stats", proc_fs_coda); 290 remove_proc_entry("vfs_stats", proc_fs_coda); 291 remove_proc_entry("coda", proc_root_fs); 292 #endif 293 } 294