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