E-procinfo.patch Add configuration option to create under /proc/fs/reiserfs hierarchy of files, displaying various ReiserFS statistics and internal data on the expense of making your kernel or module slightly larger (+8K). This also increases amount of kernel memory required for each mount. Only ReiserFS developers and people fine-tuning reiserfs or tracing problems should be interested in this. diff -rup linux-2.4.6/Documentation/Configure.help linux-2.4.6.cleanup/Documentation/Configure.help --- linux-2.4.6/Documentation/Configure.help Wed Jul 4 13:45:40 2001 +++ linux-2.4.6.cleanup/Documentation/Configure.help Wed Jul 11 19:58:09 2001 @@ -11669,6 +11669,15 @@ CONFIG_REISERFS_CHECK report, say yes and you might get a useful error message. Almost everyone should say no. +Publish some reiserfs-specific info under /proc/fs/reiserfs +CONFIG_REISERFS_PROC_INFO + Create under /proc/fs/reiserfs hierarchy of files, displaying + various ReiserFS statistics and internal data on the expense of + making your kernel or module slightly larger (+8K). This also increases + amount of kernel memory required for each mount. Almost everyone + but ReiserFS developers and people fine-tuning reiserfs or tracing + problems should say NO. + Second extended fs support CONFIG_EXT2_FS This is the de facto standard Linux file system (method to organize diff -rup linux-2.4.6/fs/Config.in linux-2.4.6.cleanup/fs/Config.in --- linux-2.4.6/fs/Config.in Wed Jul 4 13:45:54 2001 +++ linux-2.4.6.cleanup/fs/Config.in Wed Jul 11 19:58:09 2001 @@ -10,6 +10,7 @@ tristate 'Kernel automounter version 4 s dep_tristate 'Reiserfs support' CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL dep_mbool ' Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL +dep_mbool ' Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL dep_mbool ' ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL diff -rup linux-2.4.6/fs/reiserfs/Makefile linux-2.4.6.cleanup/fs/reiserfs/Makefile --- linux-2.4.6/fs/reiserfs/Makefile Mon Jan 15 23:42:32 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/Makefile Wed Jul 11 19:58:09 2001 @@ -9,7 +9,7 @@ O_TARGET := reiserfs.o obj-y := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o super.o prints.o objectid.o \ -lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o tail_conversion.o version.o item_ops.o ioctl.o +lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o tail_conversion.o version.o item_ops.o ioctl.o procfs.o obj-m := $(O_TARGET) diff -rup linux-2.4.6/fs/reiserfs/bitmap.c linux-2.4.6.cleanup/fs/reiserfs/bitmap.c --- linux-2.4.6/fs/reiserfs/bitmap.c Wed Jul 11 17:47:37 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/bitmap.c Wed Jul 11 19:58:09 2001 @@ -95,6 +95,8 @@ void reiserfs_free_block (struct reiserf RFALSE(!s, "vs-4060: trying to free block on nonexistent device"); RFALSE(is_reusable (s, block, 1) == 0, "vs-4070: can not free such block"); + PROC_INFO_INC( s, free_block ); + rs = SB_DISK_SUPER_BLOCK (s); sbh = SB_BUFFER_WITH_SB (s); apbh = SB_AP_BITMAP (s); @@ -136,10 +138,14 @@ static int find_forward (struct super_bl unsigned long block_to_try = 0; unsigned long next_block_to_try = 0 ; - for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++, *offset = 0) { + PROC_INFO_INC( s, find_forward.call ); + + for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++, *offset = 0, + PROC_INFO_INC( s, find_forward.bmap )) { /* get corresponding bitmap block */ bh = SB_AP_BITMAP (s)[i]; if (buffer_locked (bh)) { + PROC_INFO_INC( s, find_forward.wait ); __wait_on_buffer (bh); } retry: @@ -174,17 +180,21 @@ retry: int new_i ; get_bit_address (s, next_block_to_try, &new_i, offset); + PROC_INFO_INC( s, find_forward.in_journal_hint ); + /* block is not in this bitmap. reset i and continue ** we only reset i if new_i is in a later bitmap. */ if (new_i > i) { i = (new_i - 1 ); /* i gets incremented by the for loop */ + PROC_INFO_INC( s, find_forward.in_journal_out ); continue ; } } else { /* no suggestion was made, just try the next block */ *offset = j+1 ; } + PROC_INFO_INC( s, find_forward.retry ); goto retry ; } } diff -rup linux-2.4.6/fs/reiserfs/buffer2.c linux-2.4.6.cleanup/fs/reiserfs/buffer2.c --- linux-2.4.6/fs/reiserfs/buffer2.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/buffer2.c Wed Jul 11 19:58:09 2001 @@ -16,6 +16,7 @@ #include #include #include +#include /* * wait_buffer_until_released @@ -63,9 +64,16 @@ void wait_buffer_until_released (const s block. */ /* The function is NOT SCHEDULE-SAFE! */ -struct buffer_head * reiserfs_bread (kdev_t n_dev, int n_block, int n_size) +struct buffer_head * reiserfs_bread (struct super_block *super, int n_block, int n_size) { - return bread (n_dev, n_block, n_size); + struct buffer_head *result; + PROC_EXP( unsigned int ctx_switches = kstat.context_swtch ); + + result = bread (super -> s_dev, n_block, n_size); + PROC_INFO_INC( super, breads ); + PROC_EXP( if( kstat.context_swtch != ctx_switches ) + PROC_INFO_INC( super, bread_miss ) ); + return result; } /* This function looks for a buffer which contains a given block. If diff -rup linux-2.4.6/fs/reiserfs/do_balan.c linux-2.4.6.cleanup/fs/reiserfs/do_balan.c --- linux-2.4.6/fs/reiserfs/do_balan.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/do_balan.c Wed Jul 11 19:58:09 2001 @@ -338,6 +338,9 @@ static int balance_leaf (struct tree_bal tb->insert_size [0]); } #endif + + PROC_INFO_INC( tb -> tb_sb, balance_at[ 0 ] ); + /* Make balance in case insert_size[0] < 0 */ if ( tb->insert_size[0] < 0 ) return balance_leaf_when_delete (tb, flag); diff -rup linux-2.4.6/fs/reiserfs/fix_node.c linux-2.4.6.cleanup/fs/reiserfs/fix_node.c --- linux-2.4.6/fs/reiserfs/fix_node.c Wed Jul 11 17:47:37 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/fix_node.c Wed Jul 11 19:58:09 2001 @@ -575,6 +575,11 @@ static void set_parameters (struct tree_ tb->lbytes = lb; tb->rbytes = rb; } + PROC_INFO_ADD( tb -> tb_sb, lnum[ h ], lnum ); + PROC_INFO_ADD( tb -> tb_sb, rnum[ h ], rnum ); + + PROC_INFO_ADD( tb -> tb_sb, lbytes[ h ], lb ); + PROC_INFO_ADD( tb -> tb_sb, rbytes[ h ], rb ); } @@ -667,6 +672,7 @@ static int are_leaves_removable (struct if (MAX_CHILD_SIZE (S0) + vn->vn_size <= rfree + lfree + ih_size) { set_parameters (tb, 0, -1, -1, -1, NULL, -1, -1); + PROC_INFO_INC( tb -> tb_sb, leaves_removable ); return 1; } return 0; @@ -1179,6 +1185,7 @@ static inline int can_node_be_removed (i return NO_BALANCING_NEEDED; } } + PROC_INFO_INC( tb -> tb_sb, can_node_be_removed[ h ] ); return !NO_BALANCING_NEEDED; } @@ -1916,8 +1923,11 @@ static int get_neighbors( struct buffer_head * p_s_bh; + PROC_INFO_INC( p_s_sb, get_neighbors[ n_h ] ); + if ( p_s_tb->lnum[n_h] ) { /* We need left neighbor to balance S[n_h]. */ + PROC_INFO_INC( p_s_sb, need_l_neighbor[ n_h ] ); p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset); RFALSE( p_s_bh == p_s_tb->FL[n_h] && @@ -1926,11 +1936,12 @@ static int get_neighbors( n_child_position = ( p_s_bh == p_s_tb->FL[n_h] ) ? p_s_tb->lkey[n_h] : B_NR_ITEMS (p_s_tb->FL[n_h]); n_son_number = B_N_CHILD_NUM(p_s_tb->FL[n_h], n_child_position); - p_s_bh = reiserfs_bread(p_s_sb->s_dev, n_son_number, p_s_sb->s_blocksize); + p_s_bh = reiserfs_bread(p_s_sb, n_son_number, p_s_sb->s_blocksize); if (!p_s_bh) return IO_ERROR; if ( FILESYSTEM_CHANGED_TB (p_s_tb) ) { decrement_bcount(p_s_bh); + PROC_INFO_INC( p_s_sb, get_neighbors_restart[ n_h ] ); return REPEAT_SEARCH; } @@ -1949,6 +1960,7 @@ static int get_neighbors( if ( p_s_tb->rnum[n_h] ) { /* We need right neighbor to balance S[n_path_offset]. */ + PROC_INFO_INC( p_s_sb, need_r_neighbor[ n_h ] ); p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset); RFALSE( p_s_bh == p_s_tb->FR[n_h] && @@ -1957,11 +1969,12 @@ static int get_neighbors( n_child_position = ( p_s_bh == p_s_tb->FR[n_h] ) ? p_s_tb->rkey[n_h] + 1 : 0; n_son_number = B_N_CHILD_NUM(p_s_tb->FR[n_h], n_child_position); - p_s_bh = reiserfs_bread(p_s_sb->s_dev, n_son_number, p_s_sb->s_blocksize); + p_s_bh = reiserfs_bread(p_s_sb, n_son_number, p_s_sb->s_blocksize); if (!p_s_bh) return IO_ERROR; if ( FILESYSTEM_CHANGED_TB (p_s_tb) ) { decrement_bcount(p_s_bh); + PROC_INFO_INC( p_s_sb, get_neighbors_restart[ n_h ] ); return REPEAT_SEARCH; } decrement_bcount(p_s_tb->R[n_h]); @@ -2302,6 +2315,8 @@ int fix_nodes (int n_op_mode, int wait_tb_buffers_run = 0 ; int windex ; struct buffer_head * p_s_tbS0 = PATH_PLAST_BUFFER(p_s_tb->tb_path); + + ++ p_s_tb -> tb_sb -> u.reiserfs_sb.s_fix_nodes; n_pos_in_item = p_s_tb->tb_path->pos_in_item; diff -rup linux-2.4.6/fs/reiserfs/ibalance.c linux-2.4.6.cleanup/fs/reiserfs/ibalance.c --- linux-2.4.6/fs/reiserfs/ibalance.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/ibalance.c Wed Jul 11 19:58:09 2001 @@ -754,6 +754,8 @@ int balance_internal (struct tree_balanc RFALSE( h < 1, "h (%d) can not be < 1 on internal level", h); + PROC_INFO_INC( tb -> tb_sb, balance_at[ h ] ); + order = ( tbSh ) ? PATH_H_POSITION (tb->tb_path, h + 1)/*tb->S[h]->b_item_order*/ : 0; /* Using insert_size[h] calculate the number insert_num of items diff -rup linux-2.4.6/fs/reiserfs/journal.c linux-2.4.6.cleanup/fs/reiserfs/journal.c --- linux-2.4.6/fs/reiserfs/journal.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/journal.c Wed Jul 11 19:59:18 2001 @@ -524,12 +524,14 @@ int reiserfs_in_journal(struct super_blo return 0 ; } + PROC_INFO_INC( p_s_sb, journal.in_journal ); /* If we aren't doing a search_all, this is a metablock, and it will be logged before use. ** if we crash before the transaction that freed it commits, this transaction won't ** have committed either, and the block will never be written */ if (search_all) { for (i = 0 ; i < JOURNAL_NUM_BITMAPS ; i++) { + PROC_INFO_INC( p_s_sb, journal.in_journal_bitmap ); jb = SB_JOURNAL(p_s_sb)->j_list_bitmap + i ; if (jb->journal_list && jb->bitmaps[bmap_nr] && test_bit(bit_nr, jb->bitmaps[bmap_nr]->data)) { @@ -552,6 +554,7 @@ int reiserfs_in_journal(struct super_blo return 1; } + PROC_INFO_INC( p_s_sb, journal.in_journal_reusable ); /* safe for reuse */ return 0 ; } @@ -572,7 +575,9 @@ inline void insert_journal_hash(struct r /* lock the current transaction */ inline static void lock_journal(struct super_block *p_s_sb) { + PROC_INFO_INC( p_s_sb, journal.lock_journal ); while(atomic_read(&(SB_JOURNAL(p_s_sb)->j_wlock)) > 0) { + PROC_INFO_INC( p_s_sb, journal.lock_journal_wait ); sleep_on(&(SB_JOURNAL(p_s_sb)->j_wait)) ; } atomic_set(&(SB_JOURNAL(p_s_sb)->j_wlock), 1) ; @@ -1995,6 +2000,7 @@ static int do_journal_begin_r(struct rei th->t_super = p_s_sb ; /* others will check this for the don't log flag */ return 0 ; } + PROC_INFO_INC( p_s_sb, journal.journal_being ); relock: lock_journal(p_s_sb) ; @@ -2002,6 +2008,7 @@ relock: if (test_bit(WRITERS_BLOCKED, &SB_JOURNAL(p_s_sb)->j_state)) { unlock_journal(p_s_sb) ; reiserfs_wait_on_write_block(p_s_sb) ; + PROC_INFO_INC( p_s_sb, journal.journal_relock_writers ); goto relock ; } @@ -2040,6 +2047,7 @@ relock: sleep_on(&(SB_JOURNAL(p_s_sb)->j_join_wait)) ; } } + PROC_INFO_INC( p_s_sb, journal.journal_relock_wcount ); goto relock ; } @@ -2086,6 +2094,7 @@ int journal_mark_dirty(struct reiserfs_t int count_already_incd = 0 ; int prepared = 0 ; + PROC_INFO_INC( p_s_sb, journal.mark_dirty ); if (reiserfs_dont_log(th->t_super)) { mark_buffer_dirty(bh) ; return 0 ; @@ -2100,6 +2109,7 @@ int journal_mark_dirty(struct reiserfs_t prepared = test_and_clear_bit(BH_JPrepared, &bh->b_state) ; /* already in this transaction, we are done */ if (buffer_journaled(bh)) { + PROC_INFO_INC( p_s_sb, journal.mark_dirty_already ); return 0 ; } @@ -2129,6 +2139,7 @@ int journal_mark_dirty(struct reiserfs_t if (buffer_journal_dirty(bh)) { count_already_incd = 1 ; + PROC_INFO_INC( p_s_sb, journal.mark_dirty_notjournal ); mark_buffer_notjournal_dirty(bh) ; } @@ -2597,6 +2608,7 @@ int journal_mark_freed(struct reiserfs_t void reiserfs_restore_prepared_buffer(struct super_block *p_s_sb, struct buffer_head *bh) { + PROC_INFO_INC( p_s_sb, journal.restore_prepared ); if (reiserfs_dont_log (p_s_sb)) return; @@ -2618,6 +2630,7 @@ void reiserfs_prepare_for_journal(struct struct buffer_head *bh, int wait) { int retry_count = 0 ; + PROC_INFO_INC( p_s_sb, journal.prepare ); if (reiserfs_dont_log (p_s_sb)) return; @@ -2633,6 +2646,7 @@ void reiserfs_prepare_for_journal(struct "waiting while do_balance was running\n") ; wait_on_buffer(bh) ; } + PROC_INFO_INC( p_s_sb, journal.prepare_retry ); retry_count++ ; } } diff -rup linux-2.4.6/fs/reiserfs/namei.c linux-2.4.6.cleanup/fs/reiserfs/namei.c --- linux-2.4.6/fs/reiserfs/namei.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/namei.c Wed Jul 11 20:00:59 2001 @@ -480,6 +480,9 @@ static int reiserfs_add_entry (struct re deh->deh_offset = cpu_to_le32 (SET_GENERATION_NUMBER (deh_offset (deh), gen_number)); set_cpu_key_k_offset (&entry_key, le32_to_cpu (deh->deh_offset)); + /* update max-hash-collisions counter in reiserfs_sb_info */ + PROC_INFO_MAX( th -> t_super, max_hash_collisions, gen_number ); + if (gen_number != 0) { /* we need to re-search for the insertion point */ if (search_by_entry_key (dir->i_sb, &entry_key, &path, &de) != NAME_NOT_FOUND) { reiserfs_warning ("vs-7032: reiserfs_add_entry: " diff -rup linux-2.4.6/fs/reiserfs/objectid.c linux-2.4.6.cleanup/fs/reiserfs/objectid.c --- linux-2.4.6/fs/reiserfs/objectid.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/objectid.c Wed Jul 11 19:58:09 2001 @@ -145,9 +145,11 @@ void reiserfs_release_objectid (struct r return; } - if (rs->s_oid_cursize == rs->s_oid_maxsize) + if (rs->s_oid_cursize == rs->s_oid_maxsize) { /* objectid map must be expanded, but there is no space */ + PROC_INFO_INC( s, leaked_oid ); return; + } /* expand the objectid map*/ memmove (map + i + 3, map + i + 1, diff -rup linux-2.4.6/fs/reiserfs/prints.c linux-2.4.6.cleanup/fs/reiserfs/prints.c --- linux-2.4.6/fs/reiserfs/prints.c Tue Jul 10 20:26:53 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/prints.c Wed Jul 11 19:58:09 2001 @@ -527,7 +527,7 @@ static int print_super_block (struct buf printk ("Filesystem state %s\n", (le16_to_cpu (rs->s_state) == REISERFS_VALID_FS) ? "VALID" : "ERROR"); printk ("Hash function \"%s\"\n", le16_to_cpu (rs->s_hash_function_code) == TEA_HASH ? "tea" : - ((le16_to_cpu (rs->s_hash_function_code) == YURA_HASH) ? "rupasov" : "unknown")); + ( le16_to_cpu (rs->s_hash_function_code) == YURA_HASH ? "rupasov" : (le16_to_cpu (rs->s_hash_function_code) == R5_HASH ? "r5" : "unknown"))); #if 0 __u32 s_journal_trans_max ; /* max number of blocks in a transaction. */ diff -rup linux-2.4.6/fs/reiserfs/procfs.c linux-2.4.6.cleanup/fs/reiserfs/procfs.c --- linux-2.4.6/fs/reiserfs/procfs.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/procfs.c Wed Jul 11 20:02:53 2001 @@ -0,0 +1,727 @@ +/* -*- linux-c -*- */ + +/* fs/reiserfs/procfs.c */ + +/* + * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README + */ + +/* proc info support a la one created by Sizif@Botik.RU for PGC */ + +/* $Id: procfs.c,v 1.1.8.2 2001/07/15 17:08:42 god Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined( REISERFS_PROC_INFO ) + +/* + * LOCKING: + * + * reiserfs_proc_info_data_t part of reiserfs super-block is protected + * by spinlock_t field .lock. Each procinfo display function acting on + * super-block, first takes this lock, then searches though list of all + * super-blocks (super_blocks), until current super-block is found. If + * it is not, or current super-block .exiting field is set, spinlock is + * released and operation aborted. Otherwise, data are stuffed into page + * and spinlock released. .exiting field is set up in + * reiserfs_proc_info_done() called from reiserfs_put_super() under + * spinlock. + * + * This all is against proc vs. umount races pointed out by Al Viro + * at fsdevel. + * + */ + +/** implements locking logic described above. */ +static struct super_block *procinfo_prologue( kdev_t dev ) +{ + struct super_block *result; + + result = NULL; + result = get_super( dev ); + if( result != NULL ) { + if( !reiserfs_is_super( result ) ) + result = NULL; + else { + spin_lock( & __PINFO( result ).lock ); + if( __PINFO( result ).exiting ) { + result = NULL; + spin_unlock( & __PINFO( result ).lock ); + } + } + } + if( result == NULL ) + printk( KERN_DEBUG "reiserfs: procfs-74: " + "race between procinfo and umount\n" ); + return result; +} + +int procinfo_epilogue( struct super_block *super ) +{ + spin_unlock( & __PINFO( super ).lock ); + return 0; +} + +int reiserfs_proc_tail( int len, char *buffer, char **start, + off_t offset, int count, int *eof ) +{ + /* this is black procfs magic */ + if( offset >= len ) { + *start = buffer; + *eof = 1; + return 0; + } + *start = buffer + offset; + if( ( len -= offset ) > count ) { + return count; + } + *eof = 1; + return len; +} + +int reiserfs_version_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + int len = 0; + struct super_block *sb; + + sb = procinfo_prologue( ( kdev_t ) ( int ) data ); + if( sb == NULL ) + return -ENOENT; + len += sprintf( &buffer[ len ], "%s format\twith checks %s\n", + old_format_only( sb ) ? "old" : "new", +#if defined( CONFIG_REISERFS_CHECK ) + "on" +#else + "off" +#endif + ); + procinfo_epilogue( sb ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + +int reiserfs_global_version_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + int len = 0; + + len += sprintf( &buffer[ len ], "%s [%s]\n", + reiserfs_get_version_string(), +#if defined( CONFIG_REISERFS_FS_MODULE ) + "as module" +#else + "built into kernel" +#endif + ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + +#define SF( x ) ( r -> x ) +#define SFP( x ) SF( s_proc_info_data.x ) +#define SFPL( x ) SFP( x[ level ] ) +#define SFPF( x ) SFP( find_forward.x ) +#define SFPJ( x ) SFP( journal.x ) + +#define D2C( x ) le16_to_cpu( x ) +#define D4C( x ) le32_to_cpu( x ) +#define DF( x ) D2C( rs -> x ) +#define DFL( x ) D4C( rs -> x ) + +#define objectid_map( s, rs ) (old_format_only (s) ? \ + (__u32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \ + (__u32 *)(rs + 1)) +#define MAP( i ) D4C( objectid_map( sb, rs )[ i ] ) + +#define DJF( x ) le32_to_cpu( rs -> x ) +#define JF( x ) ( r -> s_journal -> x ) + +int reiserfs_super_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + struct super_block *sb; + struct reiserfs_sb_info *r; + int len = 0; + + sb = procinfo_prologue( ( kdev_t ) ( int ) data ); + if( sb == NULL ) + return -ENOENT; + r = &sb->u.reiserfs_sb; + len += sprintf( &buffer[ len ], + "state: \t%s\n" + "mount options: \t%s%s%s%s%s%s%s%s%s%s%s%s\n" + "gen. counter: \t%i\n" + "s_kmallocs: \t%i\n" + "s_disk_reads: \t%i\n" + "s_disk_writes: \t%i\n" + "s_fix_nodes: \t%i\n" + "s_do_balance: \t%i\n" + "s_unneeded_left_neighbor: \t%i\n" + "s_good_search_by_key_reada: \t%i\n" + "s_bmaps: \t%i\n" + "s_bmaps_without_search: \t%i\n" + "s_direct2indirect: \t%i\n" + "s_indirect2direct: \t%i\n" + "\n" + "max_hash_collisions: \t%i\n" + + "breads: \t%lu\n" + "bread_misses: \t%lu\n" + + "search_by_key: \t%lu\n" + "search_by_key_fs_changed: \t%lu\n" + "search_by_key_restarted: \t%lu\n" + + "leaked_oid: \t%lu\n" + "leaves_removable: \t%lu\n", + + SF( s_mount_state ) == REISERFS_VALID_FS ? + "REISERFS_VALID_FS" : "REISERFS_ERROR_FS", + reiserfs_r5_hash( sb ) ? "FORCE_R5 " : "", + reiserfs_rupasov_hash( sb ) ? "FORCE_RUPASOV " : "", + reiserfs_tea_hash( sb ) ? "FORCE_TEA " : "", + reiserfs_hash_detect( sb ) ? "DETECT_HASH " : "", + reiserfs_no_border( sb ) ? "NO_BORDER " : "BORDER ", + reiserfs_no_unhashed_relocation( sb ) ? "NO_UNHASHED_RELOCATION " : "", + reiserfs_hashed_relocation( sb ) ? "UNHASHED_RELOCATION " : "", + reiserfs_test4( sb ) ? "TEST4 " : "", + dont_have_tails( sb ) ? "NO_TAILS " : "TAILS ", + replay_only( sb ) ? "REPLAY_ONLY " : "", + reiserfs_dont_log( sb ) ? "DONT_LOG " : "LOG ", + old_format_only( sb ) ? "CONV " : "", + + atomic_read( &r -> s_generation_counter ), + SF( s_kmallocs ), + SF( s_disk_reads ), + SF( s_disk_writes ), + SF( s_fix_nodes ), + SF( s_do_balance ), + SF( s_unneeded_left_neighbor ), + SF( s_good_search_by_key_reada ), + SF( s_bmaps ), + SF( s_bmaps_without_search ), + SF( s_direct2indirect ), + SF( s_indirect2direct ), + SFP( max_hash_collisions ), + SFP( breads ), + SFP( bread_miss ), + SFP( search_by_key ), + SFP( search_by_key_fs_changed ), + SFP( search_by_key_restarted ), + SFP( leaked_oid ), + SFP( leaves_removable ) ); + + procinfo_epilogue( sb ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + +int reiserfs_per_level_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + struct super_block *sb; + struct reiserfs_sb_info *r; + int len = 0; + int level; + + sb = procinfo_prologue( ( kdev_t ) ( int ) data ); + if( sb == NULL ) + return -ENOENT; + r = &sb->u.reiserfs_sb; + + len += sprintf( &buffer[ len ], + "level\t" + " balances" + " [sbk: reads" + " fs_changed" + " restarted]" + " free space" + " items" + " can_remove" + " lnum" + " rnum" + " lbytes" + " rbytes" + " get_neig" + " get_neig_res" + " need_l_neig" + " need_r_neig" + "\n" + + ); + + for( level = 0 ; level < MAX_HEIGHT ; ++ level ) { + if( len > PAGE_SIZE - 240 ) { + len += sprintf( &buffer[ len ], "... and more\n" ); + break; + } + len += sprintf( &buffer[ len ], + "%i\t" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + " %12li" + " %12li" + " %12li" + " %12li" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + "\n", + level, + SFPL( balance_at ), + SFPL( sbk_read_at ), + SFPL( sbk_fs_changed ), + SFPL( sbk_restarted ), + SFPL( free_at ), + SFPL( items_at ), + SFPL( can_node_be_removed ), + SFPL( lnum ), + SFPL( rnum ), + SFPL( lbytes ), + SFPL( rbytes ), + SFPL( get_neighbors ), + SFPL( get_neighbors_restart ), + SFPL( need_l_neighbor ), + SFPL( need_r_neighbor ) + ); + } + + procinfo_epilogue( sb ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + +int reiserfs_bitmap_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + struct super_block *sb; + struct reiserfs_sb_info *r = &sb->u.reiserfs_sb; + int len = 0; + + sb = procinfo_prologue( ( kdev_t ) ( int ) data ); + if( sb == NULL ) + return -ENOENT; + r = &sb->u.reiserfs_sb; + + len += sprintf( &buffer[ len ], "free_block: %lu\n" + "find_forward:" + " wait" + " bmap" + " retry" + " journal_hint" + " journal_out" + "\n" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + " %12lu" + "\n", + SFP( free_block ), + SFPF( call ), + SFPF( wait ), + SFPF( bmap ), + SFPF( retry ), + SFPF( in_journal_hint ), + SFPF( in_journal_out ) ); + + procinfo_epilogue( sb ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + +int reiserfs_on_disk_super_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + struct super_block *sb; + struct reiserfs_sb_info *sb_info; + struct reiserfs_super_block *rs; + int hash_code; + int len = 0; + + sb = procinfo_prologue( ( kdev_t ) ( int ) data ); + if( sb == NULL ) + return -ENOENT; + sb_info = &sb->u.reiserfs_sb; + rs = sb_info -> s_rs; + hash_code = DFL( s_hash_function_code ); + + len += sprintf( &buffer[ len ], + "block_count: \t%i\n" + "free_blocks: \t%i\n" + "root_block: \t%i\n" + "blocksize: \t%i\n" + "oid_maxsize: \t%i\n" + "oid_cursize: \t%i\n" + "state: \t%i\n" + "magic: \t%12.12s\n" + "hash: \t%s\n" + "tree_height: \t%i\n" + "bmap_nr: \t%i\n" + "version: \t%i\n", + + DFL( s_block_count ), + DFL( s_free_blocks ), + DFL( s_root_block ), + DF( s_blocksize ), + DF( s_oid_maxsize ), + DF( s_oid_cursize ), + DF( s_state ), + rs -> s_magic, + hash_code == TEA_HASH ? "tea" : + ( hash_code == YURA_HASH ) ? "rupasov" : + ( hash_code == R5_HASH ) ? "r5" : + ( hash_code == UNSET_HASH ) ? "unset" : "unknown", + DF( s_tree_height ), + DF( s_bmap_nr ), + DF( s_version ) ); + + procinfo_epilogue( sb ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + +int reiserfs_oidmap_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + struct super_block *sb; + struct reiserfs_sb_info *sb_info; + struct reiserfs_super_block *rs; + int i; + unsigned int mapsize; + unsigned long total_used; + int len = 0; + int exact; + + sb = procinfo_prologue( ( kdev_t ) ( int ) data ); + if( sb == NULL ) + return -ENOENT; + sb_info = &sb->u.reiserfs_sb; + rs = sb_info -> s_rs; + mapsize = le16_to_cpu( rs -> s_oid_cursize ); + total_used = 0; + + for( i = 0 ; i < mapsize ; ++i ) { + __u32 right; + + right = ( i == mapsize - 1 ) ? MAX_KEY_OBJECTID : MAP( i + 1 ); + len += sprintf( &buffer[ len ], "%s: [ %x .. %x )\n", + ( i & 1 ) ? "free" : "used", MAP( i ), right ); + if( ! ( i & 1 ) ) { + total_used += right - MAP( i ); + } + if( len > PAGE_SIZE - 100 ) { + len += sprintf( &buffer[ len ], "... and more\n" ); + break; + } + } +#if defined( REISERFS_USE_OIDMAPF ) + if( sb_info -> oidmap.use_file && ( sb_info -> oidmap.mapf != NULL ) ) { + loff_t size; + + size = sb_info -> oidmap.mapf -> f_dentry -> d_inode -> i_size; + total_used += size / sizeof( reiserfs_oidinterval_d_t ); + exact = 1; + } else +#endif + { + exact = ( i == mapsize ); + } + len += sprintf( &buffer[ len ], "total: \t%i [%i/%i] used: %lu [%s]\n", + i, + mapsize, le16_to_cpu( rs -> s_oid_maxsize ), + total_used, exact ? "exact" : "estimation" ); + + procinfo_epilogue( sb ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + +int reiserfs_journal_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ + struct super_block *sb; + struct reiserfs_sb_info *r; + struct reiserfs_super_block *rs; + int len = 0; + + sb = procinfo_prologue( ( kdev_t ) ( int ) data ); + if( sb == NULL ) + return -ENOENT; + r = &sb->u.reiserfs_sb; + rs = r -> s_rs; + + len += sprintf( &buffer[ len ], + /* on-disk fields */ + "s_journal_block: \t%i\n" + "s_journal_dev: \t%s[%x]\n" + "s_orig_journal_size: \t%i\n" + "s_journal_trans_max: \t%i\n" + "s_journal_block_count: \t%i\n" + "s_journal_max_batch: \t%i\n" + "s_journal_max_commit_age: \t%i\n" + "s_journal_max_trans_age: \t%i\n" + /* incore fields */ + "j_state: \t%i\n" + "j_trans_id: \t%lu\n" + "j_mount_id: \t%lu\n" + "j_start: \t%lu\n" + "j_len: \t%lu\n" + "j_len_alloc: \t%lu\n" + "j_wcount: \t%i\n" + "j_bcount: \t%lu\n" + "j_first_unflushed_offset: \t%lu\n" + "j_last_flush_trans_id: \t%lu\n" + "j_trans_start_time: \t%li\n" + "j_journal_list_index: \t%i\n" + "j_list_bitmap_index: \t%i\n" + "j_must_wait: \t%i\n" + "j_next_full_flush: \t%i\n" + "j_next_async_flush: \t%i\n" + "j_cnode_used: \t%i\n" + "j_cnode_free: \t%i\n" + "\n" + /* reiserfs_proc_info_data_t.journal fields */ + "in_journal: \t%12lu\n" + "in_journal_bitmap: \t%12lu\n" + "in_journal_reusable: \t%12lu\n" + "lock_journal: \t%12lu\n" + "lock_journal_wait: \t%12lu\n" + "journal_begin: \t%12lu\n" + "journal_relock_writers: \t%12lu\n" + "journal_relock_wcount: \t%12lu\n" + "mark_dirty: \t%12lu\n" + "mark_dirty_already: \t%12lu\n" + "mark_dirty_notjournal: \t%12lu\n" + "restore_prepared: \t%12lu\n" + "prepare: \t%12lu\n" + "prepare_retry: \t%12lu\n", + + DJF( s_journal_block ), + DJF( s_journal_dev ) == 0 ? "none" : bdevname( DJF( s_journal_dev ) ), + DJF( s_journal_dev ), + DJF( s_orig_journal_size ), + DJF( s_journal_trans_max ), + DJF( s_journal_block_count ), + DJF( s_journal_max_batch ), + DJF( s_journal_max_commit_age ), + DJF( s_journal_max_trans_age ), + + JF( j_state ), + JF( j_trans_id ), + JF( j_mount_id ), + JF( j_start ), + JF( j_len ), + JF( j_len_alloc ), + atomic_read( & r -> s_journal -> j_wcount ), + JF( j_bcount ), + JF( j_first_unflushed_offset ), + JF( j_last_flush_trans_id ), + JF( j_trans_start_time ), + JF( j_journal_list_index ), + JF( j_list_bitmap_index ), + JF( j_must_wait ), + JF( j_next_full_flush ), + JF( j_next_async_flush ), + JF( j_cnode_used ), + JF( j_cnode_free ), + + SFPJ( in_journal ), + SFPJ( in_journal_bitmap ), + SFPJ( in_journal_reusable ), + SFPJ( lock_journal ), + SFPJ( lock_journal_wait ), + SFPJ( journal_being ), + SFPJ( journal_relock_writers ), + SFPJ( journal_relock_wcount ), + SFPJ( mark_dirty ), + SFPJ( mark_dirty_already ), + SFPJ( mark_dirty_notjournal ), + SFPJ( restore_prepared ), + SFPJ( prepare ), + SFPJ( prepare_retry ) + ); + + procinfo_epilogue( sb ); + return reiserfs_proc_tail( len, buffer, start, offset, count, eof ); +} + + +static struct proc_dir_entry *proc_info_root = NULL; +static const char *proc_info_root_name = "fs/reiserfs"; + +int reiserfs_proc_info_init( struct super_block *sb ) +{ + spin_lock_init( & __PINFO( sb ).lock ); + sb->u.reiserfs_sb.procdir = proc_mkdir( bdevname( sb -> s_dev ), + proc_info_root ); + if( sb->u.reiserfs_sb.procdir ) { + sb->u.reiserfs_sb.procdir -> owner = THIS_MODULE; + return 0; + } + reiserfs_warning( "reiserfs: cannot create /proc/%s/%s\n", + proc_info_root_name, bdevname( sb -> s_dev ) ); + return 1; +} + + +int reiserfs_proc_info_done( struct super_block *sb ) +{ + spin_lock( & __PINFO( sb ).lock ); + __PINFO( sb ).exiting = 1; + spin_unlock( & __PINFO( sb ).lock ); + if ( proc_info_root ) { + remove_proc_entry( bdevname( sb -> s_dev ), proc_info_root ); + sb->u.reiserfs_sb.procdir = NULL; + } + return 0; +} + +/* Create /proc/fs/reiserfs/DEV/name and attach read procedure @func + to it. Other parts of reiserfs use this function to make their + per-device statistics available via /proc */ + +struct proc_dir_entry *reiserfs_proc_register( struct super_block *sb, + char *name, read_proc_t *func ) +{ + return ( sb->u.reiserfs_sb.procdir ) ? create_proc_read_entry + ( name, 0, sb->u.reiserfs_sb.procdir, func, + ( void * ) ( int ) sb -> s_dev ) : NULL; +} + +void reiserfs_proc_unregister( struct super_block *sb, const char *name ) +{ + remove_proc_entry( name, sb->u.reiserfs_sb.procdir ); +} + +struct proc_dir_entry *reiserfs_proc_register_global( char *name, + read_proc_t *func ) +{ + return ( proc_info_root ) ? create_proc_read_entry( name, 0, + proc_info_root, + func, NULL ) : NULL; +} + +void reiserfs_proc_unregister_global( const char *name ) +{ + remove_proc_entry( name, proc_info_root ); +} + +int reiserfs_proc_info_global_init( void ) +{ + if( proc_info_root == NULL ) { + proc_info_root = proc_mkdir( proc_info_root_name, 0 ); + if( proc_info_root ) { + proc_info_root -> owner = THIS_MODULE; + } else { + reiserfs_warning( "reiserfs: cannot create /proc/%s\n", + proc_info_root_name ); + return 1; + } + } + return 0; +} + +int reiserfs_proc_info_global_done( void ) +{ + if ( proc_info_root != NULL ) { + proc_info_root = NULL; + remove_proc_entry( proc_info_root_name, 0 ); + } + return 0; +} + +/* REISERFS_PROC_INFO */ +#else + +int reiserfs_proc_info_init( struct super_block *sb ) { return 0; } +int reiserfs_proc_info_done( struct super_block *sb ) { return 0; } + +struct proc_dir_entry *reiserfs_proc_register( struct super_block *sb, + char *name, + read_proc_t *func ) +{ return NULL; } + +void reiserfs_proc_unregister( struct super_block *sb, const char *name ) +{;} + +struct proc_dir_entry *reiserfs_proc_register_global( char *name, + read_proc_t *func ) +{ return NULL; } + +void reiserfs_proc_unregister_global( const char *name ) {;} + +int reiserfs_proc_info_global_init( void ) { return 0; } +int reiserfs_proc_info_global_done( void ) { return 0; } + +int reiserfs_global_version_in_proc( char *buffer, char **start, + off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +int reiserfs_version_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +int reiserfs_super_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +int reiserfs_per_level_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +int reiserfs_bitmap_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +int reiserfs_on_disk_super_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +int reiserfs_oidmap_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +int reiserfs_journal_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ) +{ return 0; } + +/* REISERFS_PROC_INFO */ +#endif + +/* + * $Log: procfs.c,v $ + * Revision 1.1.8.2 2001/07/15 17:08:42 god + * . use get_super() in procfs.c + * . remove remove_save_link() from reiserfs_do_truncate() + * + * I accept terms and conditions stated in the Legal Agreement + * (available at http://www.namesys.com/legalese.html) + * + * Revision 1.1.8.1 2001/07/11 16:48:50 god + * proc info support + * + * I accept terms and conditions stated in the Legal Agreement + * (available at http://www.namesys.com/legalese.html) + * + */ + +/* + * Make Linus happy. + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -rup linux-2.4.6/fs/reiserfs/stree.c linux-2.4.6.cleanup/fs/reiserfs/stree.c --- linux-2.4.6/fs/reiserfs/stree.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/stree.c Wed Jul 11 20:02:53 2001 @@ -648,7 +648,6 @@ int search_by_key (struct super_block * stop at leaf level - set to DISK_LEAF_NODE_LEVEL */ ) { - kdev_t n_dev = p_s_sb->s_dev; int n_block_number = SB_ROOT_BLOCK (p_s_sb), expected_level = SB_TREE_HEIGHT (p_s_sb), n_block_size = p_s_sb->s_blocksize; @@ -661,7 +660,9 @@ int search_by_key (struct super_block * #ifdef CONFIG_REISERFS_CHECK int n_repeat_counter = 0; #endif - + + PROC_INFO_INC( p_s_sb, search_by_key ); + /* As we add each node to a path we increase its count. This means that we must be careful to release all nodes in a path before we either discard the path struct or re-use the path struct, as we do here. */ @@ -696,17 +697,24 @@ int search_by_key (struct super_block * /* Read the next tree node, and set the last element in the path to have a pointer to it. */ if ( ! (p_s_bh = p_s_last_element->pe_buffer = - reiserfs_bread(n_dev, n_block_number, n_block_size)) ) { + reiserfs_bread(p_s_sb, n_block_number, n_block_size)) ) { p_s_search_path->path_length --; pathrelse(p_s_search_path); return IO_ERROR; } + if( fs_changed (fs_gen, p_s_sb) ) { + PROC_INFO_INC( p_s_sb, search_by_key_fs_changed ); + PROC_INFO_INC( p_s_sb, sbk_fs_changed[ expected_level - 1 ] ); + } + /* It is possible that schedule occurred. We must check whether the key to search is still in the tree rooted from the current buffer. If not then repeat search from the root. */ if ( fs_changed (fs_gen, p_s_sb) && (!B_IS_IN_TREE (p_s_bh) || !key_in_buffer(p_s_search_path, p_s_key, p_s_sb)) ) { + PROC_INFO_INC( p_s_sb, search_by_key_restarted ); + PROC_INFO_INC( p_s_sb, sbk_restarted[ expected_level - 1 ] ); decrement_counters_in_path(p_s_search_path); /* Get the root block number so that we can repeat the search @@ -740,6 +748,8 @@ int search_by_key (struct super_block * /* ok, we have acquired next formatted node in the tree */ n_node_level = B_LEVEL (p_s_bh); + + PROC_INFO_BH_STAT( p_s_sb, p_s_bh, n_node_level - 1 ); RFALSE( n_node_level < n_stop_level, "vs-5152: tree level (%d) is less than stop level (%d)", diff -rup linux-2.4.6/fs/reiserfs/super.c linux-2.4.6.cleanup/fs/reiserfs/super.c --- linux-2.4.6/fs/reiserfs/super.c Wed Jul 11 19:43:00 2001 +++ linux-2.4.6.cleanup/fs/reiserfs/super.c Wed Jul 11 19:58:09 2001 @@ -114,10 +114,18 @@ void reiserfs_put_super (struct super_bl print_statistics (s); if (s->u.reiserfs_sb.s_kmallocs != 0) { - reiserfs_warning ("vs-2004: reiserfs_put_super: aloocated memory left %d\n", + reiserfs_warning ("vs-2004: reiserfs_put_super: allocated memory left %d\n", s->u.reiserfs_sb.s_kmallocs); } + reiserfs_proc_unregister( s, "journal" ); + reiserfs_proc_unregister( s, "oidmap" ); + reiserfs_proc_unregister( s, "on-disk-super" ); + reiserfs_proc_unregister( s, "bitmap" ); + reiserfs_proc_unregister( s, "per-level" ); + reiserfs_proc_unregister( s, "super" ); + reiserfs_proc_unregister( s, "version" ); + reiserfs_proc_info_done( s ); return; } @@ -300,11 +308,11 @@ static int read_bitmaps (struct super_bl labeling scheme currently used will have enough space. Then we need one block for the super. -Hans */ bmp = (REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */ - SB_AP_BITMAP (s)[0] = reiserfs_bread (s->s_dev, bmp, s->s_blocksize); + SB_AP_BITMAP (s)[0] = reiserfs_bread (s, bmp, s->s_blocksize); if(!SB_AP_BITMAP(s)[0]) return 1; for (i = 1, bmp = dl = rs->s_blocksize * 8; i < le16_to_cpu (rs->s_bmap_nr); i ++) { - SB_AP_BITMAP (s)[i] = reiserfs_bread (s->s_dev, bmp, s->s_blocksize); + SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp, s->s_blocksize); if (!SB_AP_BITMAP (s)[i]) return 1; bmp += dl; @@ -327,7 +335,7 @@ static int read_old_bitmaps (struct supe memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr)); for (i = 0; i < le16_to_cpu (rs->s_bmap_nr); i ++) { - SB_AP_BITMAP (s)[i] = reiserfs_bread (s->s_dev, bmp1 + i, s->s_blocksize); + SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp1 + i, s->s_blocksize); if (!SB_AP_BITMAP (s)[i]) return 1; } @@ -454,7 +462,7 @@ static int read_super_block (struct supe if (s->s_blocksize != size) set_blocksize (s->s_dev, s->s_blocksize); - bh = reiserfs_bread (s->s_dev, REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize, s->s_blocksize); + bh = reiserfs_bread (s, REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize, s->s_blocksize); if (!bh) { printk("read_super_block: unable to read superblock on dev %s\n", kdevname(s->s_dev)); return 1; @@ -656,7 +664,6 @@ int function2code (hashf_t func) return 0; } - // // a portion of this function, particularly the VFS interface portion, // was derived from minix or ext2's analog and evolved as the @@ -805,6 +812,14 @@ struct super_block * reiserfs_read_super } } + reiserfs_proc_info_init( s ); + reiserfs_proc_register( s, "version", reiserfs_version_in_proc ); + reiserfs_proc_register( s, "super", reiserfs_super_in_proc ); + reiserfs_proc_register( s, "per-level", reiserfs_per_level_in_proc ); + reiserfs_proc_register( s, "bitmap", reiserfs_bitmap_in_proc ); + reiserfs_proc_register( s, "on-disk-super", reiserfs_on_disk_super_in_proc ); + reiserfs_proc_register( s, "oidmap", reiserfs_oidmap_in_proc ); + reiserfs_proc_register( s, "journal", reiserfs_journal_in_proc ); init_waitqueue_head (&(s->u.reiserfs_sb.s_wait)); printk("%s\n", reiserfs_get_version_string()) ; @@ -854,21 +869,20 @@ int reiserfs_statfs (struct super_block static DECLARE_FSTYPE_DEV(reiserfs_fs_type,"reiserfs",reiserfs_read_super); -// -// this is exactly what 2.3.99-pre9's init_ext2_fs is -// static int __init init_reiserfs_fs (void) { + reiserfs_proc_info_global_init(); + reiserfs_proc_register_global( "version", + reiserfs_global_version_in_proc ); return register_filesystem(&reiserfs_fs_type); } EXPORT_NO_SYMBOLS; -// -// this is exactly what 2.3.99-pre9's init_ext2_fs is -// static void __exit exit_reiserfs_fs(void) { + reiserfs_proc_unregister_global( "version" ); + reiserfs_proc_info_global_done(); unregister_filesystem(&reiserfs_fs_type); } diff -rup linux-2.4.6/include/linux/reiserfs_fs.h linux-2.4.6.cleanup/include/linux/reiserfs_fs.h --- linux-2.4.6/include/linux/reiserfs_fs.h Wed Jul 11 19:43:01 2001 +++ linux-2.4.6.cleanup/include/linux/reiserfs_fs.h Wed Jul 11 20:27:28 2001 @@ -18,6 +18,7 @@ #include #include #include +#include #endif /* @@ -1783,6 +1784,67 @@ int read_old_super_block (struct super_b struct super_block * reiserfs_read_super (struct super_block * s, void * data, int silent); int reiserfs_statfs (struct super_block * s, struct statfs * buf); +/* procfs.c */ + +#if defined( CONFIG_PROC_FS ) && defined( CONFIG_REISERFS_PROC_INFO ) +#define REISERFS_PROC_INFO +#else +#undef REISERFS_PROC_INFO +#endif + +int reiserfs_proc_info_init( struct super_block *sb ); +int reiserfs_proc_info_done( struct super_block *sb ); +struct proc_dir_entry *reiserfs_proc_register( struct super_block *sb, + char *name, read_proc_t *func ); +void reiserfs_proc_unregister( struct super_block *sb, const char *name ); +struct proc_dir_entry *reiserfs_proc_register_global( char *name, + read_proc_t *func ); +void reiserfs_proc_unregister_global( const char *name ); +int reiserfs_proc_info_global_init( void ); +int reiserfs_proc_info_global_done( void ); +int reiserfs_proc_tail( int len, char *buffer, char **start, + off_t offset, int count, int *eof ); +int reiserfs_global_version_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); +int reiserfs_version_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); +int reiserfs_super_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); +int reiserfs_per_level_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); +int reiserfs_bitmap_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); +int reiserfs_on_disk_super_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); +int reiserfs_oidmap_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); +int reiserfs_journal_in_proc( char *buffer, char **start, off_t offset, + int count, int *eof, void *data ); + +#if defined( REISERFS_PROC_INFO ) + +#define PROC_EXP( e ) e + +#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) +#define __PINFO( sb ) ( sb ) -> u.reiserfs_sb.s_proc_info_data +#define PROC_INFO_MAX( sb, field, value ) \ + __PINFO( sb ).field = \ + MAX( ( sb ) -> u.reiserfs_sb.s_proc_info_data.field, value ) +#define PROC_INFO_INC( sb, field ) ( ++ ( __PINFO( sb ).field ) ) +#define PROC_INFO_ADD( sb, field, val ) ( __PINFO( sb ).field += ( val ) ) +#define PROC_INFO_BH_STAT( sb, bh, level ) \ + PROC_INFO_INC( sb, sbk_read_at[ ( level ) ] ); \ + PROC_INFO_ADD( sb, free_at[ ( level ) ], B_FREE_SPACE( bh ) ); \ + PROC_INFO_ADD( sb, items_at[ ( level ) ], B_NR_ITEMS( bh ) ) +#else +#define PROC_EXP( e ) +#define VOID_V ( ( void ) 0 ) +#define PROC_INFO_MAX( sb, field, value ) VOID_V +#define PROC_INFO_INC( sb, field ) VOID_V +#define PROC_INFO_ADD( sb, field, val ) VOID_V +#define PROC_INFO_BH_STAT( p_s_sb, p_s_bh, n_node_level ) VOID_V +#endif + /* dir.c */ extern struct inode_operations reiserfs_dir_inode_operations; extern struct file_operations reiserfs_dir_operations; @@ -1804,8 +1866,8 @@ int get_new_buffer (struct reiserfs_tran /* buffer2.c */ struct buffer_head * reiserfs_getblk (kdev_t n_dev, int n_block, int n_size); void wait_buffer_until_released (const struct buffer_head * bh); -struct buffer_head * reiserfs_bread (kdev_t n_dev, int n_block, int n_size); - +struct buffer_head * reiserfs_bread (struct super_block *super, int n_block, + int n_size); /* fix_nodes.c */ void * reiserfs_kmalloc (size_t size, int flags, struct super_block * s); diff -rup linux-2.4.6/include/linux/reiserfs_fs_sb.h linux-2.4.6.cleanup/include/linux/reiserfs_fs_sb.h --- linux-2.4.6/include/linux/reiserfs_fs_sb.h Wed May 2 14:04:19 2001 +++ linux-2.4.6.cleanup/include/linux/reiserfs_fs_sb.h Wed Jul 11 20:20:49 2001 @@ -262,6 +262,74 @@ struct reiserfs_journal { typedef __u32 (*hashf_t) (const char *, int); +struct proc_dir_entry; + +#if defined( CONFIG_PROC_FS ) && defined( CONFIG_REISERFS_PROC_INFO ) +typedef unsigned long int stat_cnt_t; +typedef struct reiserfs_proc_info_data +{ + spinlock_t lock; + int exiting; + int max_hash_collisions; + + stat_cnt_t breads; + stat_cnt_t bread_miss; + stat_cnt_t search_by_key; + stat_cnt_t search_by_key_fs_changed; + stat_cnt_t search_by_key_restarted; + + stat_cnt_t leaked_oid; + stat_cnt_t leaves_removable; + + /* balances per level. Use explicit 5 as MAX_HEIGHT is not visible yet. */ + stat_cnt_t balance_at[ 5 ]; /* XXX */ + /* sbk == search_by_key */ + stat_cnt_t sbk_read_at[ 5 ]; /* XXX */ + stat_cnt_t sbk_fs_changed[ 5 ]; + stat_cnt_t sbk_restarted[ 5 ]; + stat_cnt_t items_at[ 5 ]; /* XXX */ + stat_cnt_t free_at[ 5 ]; /* XXX */ + stat_cnt_t can_node_be_removed[ 5 ]; /* XXX */ + long int lnum[ 5 ]; /* XXX */ + long int rnum[ 5 ]; /* XXX */ + long int lbytes[ 5 ]; /* XXX */ + long int rbytes[ 5 ]; /* XXX */ + stat_cnt_t get_neighbors[ 5 ]; + stat_cnt_t get_neighbors_restart[ 5 ]; + stat_cnt_t need_l_neighbor[ 5 ]; + stat_cnt_t need_r_neighbor[ 5 ]; + + stat_cnt_t free_block; + struct __find_forward_stats { + stat_cnt_t call; + stat_cnt_t wait; + stat_cnt_t bmap; + stat_cnt_t retry; + stat_cnt_t in_journal_hint; + stat_cnt_t in_journal_out; + } find_forward; + struct __journal_stats { + stat_cnt_t in_journal; + stat_cnt_t in_journal_bitmap; + stat_cnt_t in_journal_reusable; + stat_cnt_t lock_journal; + stat_cnt_t lock_journal_wait; + stat_cnt_t journal_being; + stat_cnt_t journal_relock_writers; + stat_cnt_t journal_relock_wcount; + stat_cnt_t mark_dirty; + stat_cnt_t mark_dirty_already; + stat_cnt_t mark_dirty_notjournal; + stat_cnt_t restore_prepared; + stat_cnt_t prepare; + stat_cnt_t prepare_retry; + } journal; +} reiserfs_proc_info_data_t; +#else +typedef struct reiserfs_proc_info_data +{} reiserfs_proc_info_data_t; +#endif + /* reiserfs union of in-core super block data */ struct reiserfs_sb_info { @@ -300,6 +368,8 @@ struct reiserfs_sb_info int s_bmaps_without_search; int s_direct2indirect; int s_indirect2direct; + reiserfs_proc_info_data_t s_proc_info_data; + struct proc_dir_entry *procdir; }; .