1 /* -*- linux-c -*- */ 2 3 /* fs/reiserfs/procfs.c */ 4 5 /* 6 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 7 */ 8 9 /* proc info support a la one created by Sizif@Botik.RU for PGC */ 10 11 /* $Id: procfs.c,v 1.1.8.2 2001/07/15 17:08:42 god Exp $ */ 12 13 #include <linux/config.h> 14 #include <linux/module.h> 15 #include <linux/time.h> 16 #include <linux/seq_file.h> 17 #include <asm/uaccess.h> 18 #include <linux/reiserfs_fs.h> 19 #include <linux/reiserfs_fs_sb.h> 20 #include <linux/smp_lock.h> 21 #include <linux/init.h> 22 #include <linux/proc_fs.h> 23 24 #if defined( REISERFS_PROC_INFO ) 25 26 /* 27 * LOCKING: 28 * 29 * We rely on new Alexander Viro's super-block locking. 30 * 31 */ 32 33 static int show_version(struct seq_file *m, struct super_block *sb) 34 { 35 char *format; 36 37 if ( REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6) ) { 38 format = "3.6"; 39 } else if ( REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_5) ) { 40 format = "3.5"; 41 } else { 42 format = "unknown"; 43 } 44 45 seq_printf(m, "%s format\twith checks %s\n", 46 format, 47 #if defined( CONFIG_REISERFS_CHECK ) 48 "on" 49 #else 50 "off" 51 #endif 52 ); 53 return 0; 54 } 55 56 int reiserfs_global_version_in_proc( char *buffer, char **start, off_t offset, 57 int count, int *eof, void *data ) 58 { 59 *start = buffer; 60 *eof = 1; 61 return 0; 62 } 63 64 #define SF( x ) ( r -> x ) 65 #define SFP( x ) SF( s_proc_info_data.x ) 66 #define SFPL( x ) SFP( x[ level ] ) 67 #define SFPF( x ) SFP( scan_bitmap.x ) 68 #define SFPJ( x ) SFP( journal.x ) 69 70 #define D2C( x ) le16_to_cpu( x ) 71 #define D4C( x ) le32_to_cpu( x ) 72 #define DF( x ) D2C( rs -> s_v1.x ) 73 #define DFL( x ) D4C( rs -> s_v1.x ) 74 75 #define objectid_map( s, rs ) (old_format_only (s) ? \ 76 (__u32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \ 77 (__u32 *)(rs + 1)) 78 #define MAP( i ) D4C( objectid_map( sb, rs )[ i ] ) 79 80 #define DJF( x ) le32_to_cpu( rs -> x ) 81 #define DJV( x ) le32_to_cpu( s_v1 -> x ) 82 #define DJP( x ) le32_to_cpu( jp -> x ) 83 #define JF( x ) ( r -> s_journal -> x ) 84 85 static int show_super(struct seq_file *m, struct super_block *sb) 86 { 87 struct reiserfs_sb_info *r = REISERFS_SB(sb); 88 89 seq_printf(m, "state: \t%s\n" 90 "mount options: \t%s%s%s%s%s%s%s%s%s%s%s\n" 91 "gen. counter: \t%i\n" 92 "s_kmallocs: \t%i\n" 93 "s_disk_reads: \t%i\n" 94 "s_disk_writes: \t%i\n" 95 "s_fix_nodes: \t%i\n" 96 "s_do_balance: \t%i\n" 97 "s_unneeded_left_neighbor: \t%i\n" 98 "s_good_search_by_key_reada: \t%i\n" 99 "s_bmaps: \t%i\n" 100 "s_bmaps_without_search: \t%i\n" 101 "s_direct2indirect: \t%i\n" 102 "s_indirect2direct: \t%i\n" 103 "\n" 104 "max_hash_collisions: \t%i\n" 105 106 "breads: \t%lu\n" 107 "bread_misses: \t%lu\n" 108 109 "search_by_key: \t%lu\n" 110 "search_by_key_fs_changed: \t%lu\n" 111 "search_by_key_restarted: \t%lu\n" 112 113 "insert_item_restarted: \t%lu\n" 114 "paste_into_item_restarted: \t%lu\n" 115 "cut_from_item_restarted: \t%lu\n" 116 "delete_solid_item_restarted: \t%lu\n" 117 "delete_item_restarted: \t%lu\n" 118 119 "leaked_oid: \t%lu\n" 120 "leaves_removable: \t%lu\n", 121 122 SF( s_mount_state ) == REISERFS_VALID_FS ? 123 "REISERFS_VALID_FS" : "REISERFS_ERROR_FS", 124 reiserfs_r5_hash( sb ) ? "FORCE_R5 " : "", 125 reiserfs_rupasov_hash( sb ) ? "FORCE_RUPASOV " : "", 126 reiserfs_tea_hash( sb ) ? "FORCE_TEA " : "", 127 reiserfs_hash_detect( sb ) ? "DETECT_HASH " : "", 128 reiserfs_no_border( sb ) ? "NO_BORDER " : "BORDER ", 129 reiserfs_no_unhashed_relocation( sb ) ? "NO_UNHASHED_RELOCATION " : "", 130 reiserfs_hashed_relocation( sb ) ? "UNHASHED_RELOCATION " : "", 131 reiserfs_test4( sb ) ? "TEST4 " : "", 132 have_large_tails( sb ) ? "TAILS " : have_small_tails(sb)?"SMALL_TAILS ":"NO_TAILS ", 133 replay_only( sb ) ? "REPLAY_ONLY " : "", 134 convert_reiserfs( sb ) ? "CONV " : "", 135 136 atomic_read( &r -> s_generation_counter ), 137 SF( s_kmallocs ), 138 SF( s_disk_reads ), 139 SF( s_disk_writes ), 140 SF( s_fix_nodes ), 141 SF( s_do_balance ), 142 SF( s_unneeded_left_neighbor ), 143 SF( s_good_search_by_key_reada ), 144 SF( s_bmaps ), 145 SF( s_bmaps_without_search ), 146 SF( s_direct2indirect ), 147 SF( s_indirect2direct ), 148 SFP( max_hash_collisions ), 149 SFP( breads ), 150 SFP( bread_miss ), 151 SFP( search_by_key ), 152 SFP( search_by_key_fs_changed ), 153 SFP( search_by_key_restarted ), 154 155 SFP( insert_item_restarted ), 156 SFP( paste_into_item_restarted ), 157 SFP( cut_from_item_restarted ), 158 SFP( delete_solid_item_restarted ), 159 SFP( delete_item_restarted ), 160 161 SFP( leaked_oid ), 162 SFP( leaves_removable ) ); 163 164 return 0; 165 } 166 167 static int show_per_level(struct seq_file *m, struct super_block *sb) 168 { 169 struct reiserfs_sb_info *r = REISERFS_SB(sb); 170 int level; 171 172 seq_printf(m, "level\t" 173 " balances" 174 " [sbk: reads" 175 " fs_changed" 176 " restarted]" 177 " free space" 178 " items" 179 " can_remove" 180 " lnum" 181 " rnum" 182 " lbytes" 183 " rbytes" 184 " get_neig" 185 " get_neig_res" 186 " need_l_neig" 187 " need_r_neig" 188 "\n" 189 190 ); 191 192 for( level = 0 ; level < MAX_HEIGHT ; ++ level ) { 193 seq_printf(m, "%i\t" 194 " %12lu" 195 " %12lu" 196 " %12lu" 197 " %12lu" 198 " %12lu" 199 " %12lu" 200 " %12lu" 201 " %12li" 202 " %12li" 203 " %12li" 204 " %12li" 205 " %12lu" 206 " %12lu" 207 " %12lu" 208 " %12lu" 209 "\n", 210 level, 211 SFPL( balance_at ), 212 SFPL( sbk_read_at ), 213 SFPL( sbk_fs_changed ), 214 SFPL( sbk_restarted ), 215 SFPL( free_at ), 216 SFPL( items_at ), 217 SFPL( can_node_be_removed ), 218 SFPL( lnum ), 219 SFPL( rnum ), 220 SFPL( lbytes ), 221 SFPL( rbytes ), 222 SFPL( get_neighbors ), 223 SFPL( get_neighbors_restart ), 224 SFPL( need_l_neighbor ), 225 SFPL( need_r_neighbor ) 226 ); 227 } 228 return 0; 229 } 230 231 static int show_bitmap(struct seq_file *m, struct super_block *sb) 232 { 233 struct reiserfs_sb_info *r = REISERFS_SB(sb); 234 235 seq_printf(m, "free_block: %lu\n" 236 " scan_bitmap:" 237 " wait" 238 " bmap" 239 " retry" 240 " stolen" 241 " journal_hint" 242 "journal_nohint" 243 "\n" 244 " %14lu" 245 " %14lu" 246 " %14lu" 247 " %14lu" 248 " %14lu" 249 " %14lu" 250 " %14lu" 251 "\n", 252 SFP( free_block ), 253 SFPF( call ), 254 SFPF( wait ), 255 SFPF( bmap ), 256 SFPF( retry ), 257 SFPF( stolen ), 258 SFPF( in_journal_hint ), 259 SFPF( in_journal_nohint ) ); 260 261 return 0; 262 } 263 264 static int show_on_disk_super(struct seq_file *m, struct super_block *sb) 265 { 266 struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); 267 struct reiserfs_super_block *rs = sb_info -> s_rs; 268 int hash_code = DFL( s_hash_function_code ); 269 __u32 flags = DJF( s_flags ); 270 271 seq_printf(m, "block_count: \t%i\n" 272 "free_blocks: \t%i\n" 273 "root_block: \t%i\n" 274 "blocksize: \t%i\n" 275 "oid_maxsize: \t%i\n" 276 "oid_cursize: \t%i\n" 277 "umount_state: \t%i\n" 278 "magic: \t%10.10s\n" 279 "fs_state: \t%i\n" 280 "hash: \t%s\n" 281 "tree_height: \t%i\n" 282 "bmap_nr: \t%i\n" 283 "version: \t%i\n" 284 "flags: \t%x[%s]\n" 285 "reserved_for_journal: \t%i\n", 286 287 DFL( s_block_count ), 288 DFL( s_free_blocks ), 289 DFL( s_root_block ), 290 DF( s_blocksize ), 291 DF( s_oid_maxsize ), 292 DF( s_oid_cursize ), 293 DF( s_umount_state ), 294 rs -> s_v1.s_magic, 295 DF( s_fs_state ), 296 hash_code == TEA_HASH ? "tea" : 297 ( hash_code == YURA_HASH ) ? "rupasov" : 298 ( hash_code == R5_HASH ) ? "r5" : 299 ( hash_code == UNSET_HASH ) ? "unset" : "unknown", 300 DF( s_tree_height ), 301 DF( s_bmap_nr ), 302 DF( s_version ), 303 flags, 304 ( flags & reiserfs_attrs_cleared ) 305 ? "attrs_cleared" : "", 306 DF (s_reserved_for_journal)); 307 308 return 0; 309 } 310 311 static int show_oidmap(struct seq_file *m, struct super_block *sb) 312 { 313 struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); 314 struct reiserfs_super_block *rs = sb_info -> s_rs; 315 unsigned int mapsize = le16_to_cpu( rs -> s_v1.s_oid_cursize ); 316 unsigned long total_used = 0; 317 int i; 318 319 for( i = 0 ; i < mapsize ; ++i ) { 320 __u32 right; 321 322 right = ( i == mapsize - 1 ) ? MAX_KEY_OBJECTID : MAP( i + 1 ); 323 seq_printf(m, "%s: [ %x .. %x )\n", 324 ( i & 1 ) ? "free" : "used", MAP( i ), right ); 325 if( ! ( i & 1 ) ) { 326 total_used += right - MAP( i ); 327 } 328 } 329 #if defined( REISERFS_USE_OIDMAPF ) 330 if( sb_info -> oidmap.use_file && ( sb_info -> oidmap.mapf != NULL ) ) { 331 loff_t size = sb_info->oidmap.mapf->f_dentry->d_inode->i_size; 332 total_used += size / sizeof( reiserfs_oidinterval_d_t ); 333 } 334 #endif 335 seq_printf(m, "total: \t%i [%i/%i] used: %lu [exact]\n", 336 mapsize, 337 mapsize, le16_to_cpu( rs -> s_v1.s_oid_maxsize ), 338 total_used); 339 return 0; 340 } 341 342 static int show_journal(struct seq_file *m, struct super_block *sb) 343 { 344 struct reiserfs_sb_info *r = REISERFS_SB(sb); 345 struct reiserfs_super_block *rs = r -> s_rs; 346 struct journal_params *jp = &rs->s_v1.s_journal; 347 char b[BDEVNAME_SIZE]; 348 349 350 seq_printf(m, /* on-disk fields */ 351 "jp_journal_1st_block: \t%i\n" 352 "jp_journal_dev: \t%s[%x]\n" 353 "jp_journal_size: \t%i\n" 354 "jp_journal_trans_max: \t%i\n" 355 "jp_journal_magic: \t%i\n" 356 "jp_journal_max_batch: \t%i\n" 357 "jp_journal_max_commit_age: \t%i\n" 358 "jp_journal_max_trans_age: \t%i\n" 359 /* incore fields */ 360 "j_1st_reserved_block: \t%i\n" 361 "j_state: \t%li\n" 362 "j_trans_id: \t%lu\n" 363 "j_mount_id: \t%lu\n" 364 "j_start: \t%lu\n" 365 "j_len: \t%lu\n" 366 "j_len_alloc: \t%lu\n" 367 "j_wcount: \t%i\n" 368 "j_bcount: \t%lu\n" 369 "j_first_unflushed_offset: \t%lu\n" 370 "j_last_flush_trans_id: \t%lu\n" 371 "j_trans_start_time: \t%li\n" 372 "j_list_bitmap_index: \t%i\n" 373 "j_must_wait: \t%i\n" 374 "j_next_full_flush: \t%i\n" 375 "j_next_async_flush: \t%i\n" 376 "j_cnode_used: \t%i\n" 377 "j_cnode_free: \t%i\n" 378 "\n" 379 /* reiserfs_proc_info_data_t.journal fields */ 380 "in_journal: \t%12lu\n" 381 "in_journal_bitmap: \t%12lu\n" 382 "in_journal_reusable: \t%12lu\n" 383 "lock_journal: \t%12lu\n" 384 "lock_journal_wait: \t%12lu\n" 385 "journal_begin: \t%12lu\n" 386 "journal_relock_writers: \t%12lu\n" 387 "journal_relock_wcount: \t%12lu\n" 388 "mark_dirty: \t%12lu\n" 389 "mark_dirty_already: \t%12lu\n" 390 "mark_dirty_notjournal: \t%12lu\n" 391 "restore_prepared: \t%12lu\n" 392 "prepare: \t%12lu\n" 393 "prepare_retry: \t%12lu\n", 394 395 DJP( jp_journal_1st_block ), 396 bdevname(SB_JOURNAL(sb)->j_dev_bd, b), 397 DJP( jp_journal_dev ), 398 DJP( jp_journal_size ), 399 DJP( jp_journal_trans_max ), 400 DJP( jp_journal_magic ), 401 DJP( jp_journal_max_batch ), 402 SB_JOURNAL(sb)->j_max_commit_age, 403 DJP( jp_journal_max_trans_age ), 404 405 JF( j_1st_reserved_block ), 406 JF( j_state ), 407 JF( j_trans_id ), 408 JF( j_mount_id ), 409 JF( j_start ), 410 JF( j_len ), 411 JF( j_len_alloc ), 412 atomic_read( & r -> s_journal -> j_wcount ), 413 JF( j_bcount ), 414 JF( j_first_unflushed_offset ), 415 JF( j_last_flush_trans_id ), 416 JF( j_trans_start_time ), 417 JF( j_list_bitmap_index ), 418 JF( j_must_wait ), 419 JF( j_next_full_flush ), 420 JF( j_next_async_flush ), 421 JF( j_cnode_used ), 422 JF( j_cnode_free ), 423 424 SFPJ( in_journal ), 425 SFPJ( in_journal_bitmap ), 426 SFPJ( in_journal_reusable ), 427 SFPJ( lock_journal ), 428 SFPJ( lock_journal_wait ), 429 SFPJ( journal_being ), 430 SFPJ( journal_relock_writers ), 431 SFPJ( journal_relock_wcount ), 432 SFPJ( mark_dirty ), 433 SFPJ( mark_dirty_already ), 434 SFPJ( mark_dirty_notjournal ), 435 SFPJ( restore_prepared ), 436 SFPJ( prepare ), 437 SFPJ( prepare_retry ) 438 ); 439 return 0; 440 } 441 442 /* iterator */ 443 static int test_sb(struct super_block *sb, void *data) 444 { 445 return data == sb; 446 } 447 448 static int set_sb(struct super_block *sb, void *data) 449 { 450 return -ENOENT; 451 } 452 453 static void *r_start(struct seq_file *m, loff_t *pos) 454 { 455 struct proc_dir_entry *de = m->private; 456 struct super_block *s = de->parent->data; 457 loff_t l = *pos; 458 459 if (l) 460 return NULL; 461 462 if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, s))) 463 return NULL; 464 465 up_write(&s->s_umount); 466 467 if (de->deleted) { 468 deactivate_super(s); 469 return NULL; 470 } 471 472 return s; 473 } 474 475 static void *r_next(struct seq_file *m, void *v, loff_t *pos) 476 { 477 ++*pos; 478 if (v) 479 deactivate_super(v); 480 return NULL; 481 } 482 483 static void r_stop(struct seq_file *m, void *v) 484 { 485 if (v) 486 deactivate_super(v); 487 } 488 489 static int r_show(struct seq_file *m, void *v) 490 { 491 struct proc_dir_entry *de = m->private; 492 int (*show)(struct seq_file *, struct super_block *) = de->data; 493 return show(m, v); 494 } 495 496 static struct seq_operations r_ops = { 497 .start = r_start, 498 .next = r_next, 499 .stop = r_stop, 500 .show = r_show, 501 }; 502 503 static int r_open(struct inode *inode, struct file *file) 504 { 505 int ret = seq_open(file, &r_ops); 506 507 if (!ret) { 508 struct seq_file *m = file->private_data; 509 m->private = PDE(inode); 510 } 511 return ret; 512 } 513 514 static struct file_operations r_file_operations = { 515 .open = r_open, 516 .read = seq_read, 517 .llseek = seq_lseek, 518 .release = seq_release, 519 }; 520 521 static struct proc_dir_entry *proc_info_root = NULL; 522 static const char proc_info_root_name[] = "fs/reiserfs"; 523 524 static void add_file(struct super_block *sb, char *name, 525 int (*func)(struct seq_file *, struct super_block *)) 526 { 527 struct proc_dir_entry *de; 528 de = create_proc_entry(name, 0, REISERFS_SB(sb)->procdir); 529 if (de) { 530 de->data = func; 531 de->proc_fops = &r_file_operations; 532 } 533 } 534 535 int reiserfs_proc_info_init( struct super_block *sb ) 536 { 537 spin_lock_init( & __PINFO( sb ).lock ); 538 REISERFS_SB(sb)->procdir = proc_mkdir(reiserfs_bdevname (sb), proc_info_root); 539 if( REISERFS_SB(sb)->procdir ) { 540 REISERFS_SB(sb)->procdir->owner = THIS_MODULE; 541 REISERFS_SB(sb)->procdir->data = sb; 542 add_file(sb, "version", show_version); 543 add_file(sb, "super", show_super); 544 add_file(sb, "per-level", show_per_level); 545 add_file(sb, "bitmap", show_bitmap); 546 add_file(sb, "on-disk-super", show_on_disk_super); 547 add_file(sb, "oidmap", show_oidmap); 548 add_file(sb, "journal", show_journal); 549 return 0; 550 } 551 reiserfs_warning(sb, "reiserfs: cannot create /proc/%s/%s", 552 proc_info_root_name, reiserfs_bdevname (sb) ); 553 return 1; 554 } 555 556 int reiserfs_proc_info_done( struct super_block *sb ) 557 { 558 struct proc_dir_entry *de = REISERFS_SB(sb)->procdir; 559 if (de) { 560 remove_proc_entry("journal", de); 561 remove_proc_entry("oidmap", de); 562 remove_proc_entry("on-disk-super", de); 563 remove_proc_entry("bitmap", de); 564 remove_proc_entry("per-level", de); 565 remove_proc_entry("super", de); 566 remove_proc_entry("version", de); 567 } 568 spin_lock( & __PINFO( sb ).lock ); 569 __PINFO( sb ).exiting = 1; 570 spin_unlock( & __PINFO( sb ).lock ); 571 if ( proc_info_root ) { 572 remove_proc_entry( reiserfs_bdevname (sb), proc_info_root ); 573 REISERFS_SB(sb)->procdir = NULL; 574 } 575 return 0; 576 } 577 578 struct proc_dir_entry *reiserfs_proc_register_global( char *name, 579 read_proc_t *func ) 580 { 581 return ( proc_info_root ) ? create_proc_read_entry( name, 0, 582 proc_info_root, 583 func, NULL ) : NULL; 584 } 585 586 void reiserfs_proc_unregister_global( const char *name ) 587 { 588 remove_proc_entry( name, proc_info_root ); 589 } 590 591 int reiserfs_proc_info_global_init( void ) 592 { 593 if( proc_info_root == NULL ) { 594 proc_info_root = proc_mkdir(proc_info_root_name, NULL); 595 if( proc_info_root ) { 596 proc_info_root -> owner = THIS_MODULE; 597 } else { 598 reiserfs_warning (NULL, 599 "reiserfs: cannot create /proc/%s", 600 proc_info_root_name ); 601 return 1; 602 } 603 } 604 return 0; 605 } 606 607 int reiserfs_proc_info_global_done( void ) 608 { 609 if ( proc_info_root != NULL ) { 610 proc_info_root = NULL; 611 remove_proc_entry(proc_info_root_name, NULL); 612 } 613 return 0; 614 } 615 616 /* REISERFS_PROC_INFO */ 617 #else 618 619 int reiserfs_proc_info_init( struct super_block *sb ) { return 0; } 620 int reiserfs_proc_info_done( struct super_block *sb ) { return 0; } 621 622 struct proc_dir_entry *reiserfs_proc_register_global( char *name, 623 read_proc_t *func ) 624 { return NULL; } 625 626 void reiserfs_proc_unregister_global( const char *name ) {;} 627 628 int reiserfs_proc_info_global_init( void ) { return 0; } 629 int reiserfs_proc_info_global_done( void ) { return 0; } 630 631 int reiserfs_global_version_in_proc( char *buffer, char **start, 632 off_t offset, 633 int count, int *eof, void *data ) 634 { return 0; } 635 636 /* REISERFS_PROC_INFO */ 637 #endif 638 639 /* 640 * $Log: procfs.c,v $ 641 * Revision 1.1.8.2 2001/07/15 17:08:42 god 642 * . use get_super() in procfs.c 643 * . remove remove_save_link() from reiserfs_do_truncate() 644 * 645 * I accept terms and conditions stated in the Legal Agreement 646 * (available at http://www.namesys.com/legalese.html) 647 * 648 * Revision 1.1.8.1 2001/07/11 16:48:50 god 649 * proc info support 650 * 651 * I accept terms and conditions stated in the Legal Agreement 652 * (available at http://www.namesys.com/legalese.html) 653 * 654 */ 655 656 /* 657 * Make Linus happy. 658 * Local variables: 659 * c-indentation-style: "K&R" 660 * mode-name: "LC" 661 * c-basic-offset: 8 662 * tab-width: 8 663 * End: 664 */ 665