diff -rup linux/Documentation/Configure.help linux.patched/Documentation/Configure.help
--- linux/Documentation/Configure.help	Sun Sep 23 20:52:38 2001
+++ linux.patched/Documentation/Configure.help	Thu Oct 11 14:42:15 2001
@@ -11846,6 +11846,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/fs/Config.in linux.patched/fs/Config.in
--- linux/fs/Config.in	Tue Jul  3 01:03:04 2001
+++ linux.patched/fs/Config.in	Thu Oct 11 14:42:15 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/fs/reiserfs/Makefile linux.patched/fs/reiserfs/Makefile
--- linux/fs/reiserfs/Makefile	Mon Jan 15 23:42:32 2001
+++ linux.patched/fs/reiserfs/Makefile	Thu Oct 11 14:42:15 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/fs/reiserfs/bitmap.c linux.patched/fs/reiserfs/bitmap.c
--- linux/fs/reiserfs/bitmap.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/bitmap.c	Thu Oct 11 14:42:15 2001
@@ -117,6 +117,8 @@ void reiserfs_free_block (struct reiserf
 	reiserfs_panic (s, "vs-4070: reiserfs_free_block: can not free such block");
 #endif
 
+  PROC_INFO_INC( s, free_block );
+
   rs = SB_DISK_SUPER_BLOCK (s);
   sbh = SB_BUFFER_WITH_SB (s);
   apbh = SB_AP_BITMAP (s);
@@ -158,10 +160,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:
@@ -196,17 +202,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/fs/reiserfs/buffer2.c linux.patched/fs/reiserfs/buffer2.c
--- linux/fs/reiserfs/buffer2.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/buffer2.c	Thu Oct 11 14:42:15 2001
@@ -16,6 +16,7 @@
 #include <linux/locks.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
 
 /*
  *  wait_buffer_until_released
@@ -63,9 +64,16 @@ void wait_buffer_until_released (struct 
    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/fs/reiserfs/do_balan.c linux.patched/fs/reiserfs/do_balan.c
--- linux/fs/reiserfs/do_balan.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/do_balan.c	Thu Oct 11 14:42:15 2001
@@ -366,6 +366,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/fs/reiserfs/fix_node.c linux.patched/fs/reiserfs/fix_node.c
--- linux/fs/reiserfs/fix_node.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/fix_node.c	Thu Oct 11 14:42:15 2001
@@ -625,6 +625,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 );
 }
 
 
@@ -721,6 +726,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;
@@ -1274,6 +1280,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;
 }
 
@@ -2027,8 +2034,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);
 	
 #ifdef CONFIG_REISERFS_CHECK
@@ -2038,11 +2048,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;
 	}
 	
@@ -2063,6 +2074,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);
 	
 #ifdef CONFIG_REISERFS_CHECK
@@ -2072,11 +2084,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]);
@@ -2426,6 +2439,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/fs/reiserfs/ibalance.c linux.patched/fs/reiserfs/ibalance.c
--- linux/fs/reiserfs/ibalance.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/ibalance.c	Thu Oct 11 14:42:15 2001
@@ -815,6 +815,8 @@ int balance_internal (struct tree_balanc
 	reiserfs_panic (tb->tb_sb, "balance_internal", "h (%d) can not be < 1 on internal level", h);
 #endif /* CONFIG_REISERFS_CHECK */
 
+    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/fs/reiserfs/journal.c linux.patched/fs/reiserfs/journal.c
--- linux/fs/reiserfs/journal.c	Sun Sep 23 20:49:45 2001
+++ linux.patched/fs/reiserfs/journal.c	Thu Oct 11 14:42:15 2001
@@ -520,12 +520,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)) {
@@ -548,6 +550,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 ;
 }
@@ -568,7 +571,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) ;
@@ -2015,6 +2020,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) ;
@@ -2022,6 +2028,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 ;
   }
 
@@ -2060,6 +2067,7 @@ relock:
 	sleep_on(&(SB_JOURNAL(p_s_sb)->j_join_wait)) ;
       }
     }
+    PROC_INFO_INC( p_s_sb, journal.journal_relock_wcount );
     goto relock ;
   }
 
@@ -2106,6 +2114,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 ;
@@ -2120,6 +2129,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 ;
   }
 
@@ -2149,6 +2159,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) ;
   }
 
@@ -2609,6 +2620,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;
 
@@ -2630,6 +2642,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;
 
@@ -2649,6 +2662,7 @@ void reiserfs_prepare_for_journal(struct
 #endif
       wait_on_buffer(bh) ;
     }
+    PROC_INFO_INC( p_s_sb, journal.prepare_retry );
     retry_count++ ;
   }
 }
diff -rup linux/fs/reiserfs/namei.c linux.patched/fs/reiserfs/namei.c
--- linux/fs/reiserfs/namei.c	Sat Sep 15 01:16:08 2001
+++ linux.patched/fs/reiserfs/namei.c	Thu Oct 11 14:42:15 2001
@@ -485,6 +485,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/fs/reiserfs/objectid.c linux.patched/fs/reiserfs/objectid.c
--- linux/fs/reiserfs/objectid.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/objectid.c	Thu Oct 11 14:42:15 2001
@@ -149,9 +149,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/fs/reiserfs/prints.c linux.patched/fs/reiserfs/prints.c
--- linux/fs/reiserfs/prints.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/prints.c	Thu Oct 11 14:42:15 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.  */
Only in linux.patched/fs/reiserfs: procfs.c
diff -rup linux/fs/reiserfs/stree.c linux.patched/fs/reiserfs/stree.c
--- linux/fs/reiserfs/stree.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/stree.c	Thu Oct 11 14:42:15 2001
@@ -671,7 +671,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;
@@ -684,7 +683,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. */
@@ -719,17 +720,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
@@ -764,6 +772,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 );
 
 #ifdef CONFIG_REISERFS_CHECK
 
diff -rup linux/fs/reiserfs/super.c linux.patched/fs/reiserfs/super.c
--- linux/fs/reiserfs/super.c	Sat Sep  8 23:05:32 2001
+++ linux.patched/fs/reiserfs/super.c	Thu Oct 11 14:44:03 2001
@@ -110,10 +110,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;
 }
 
@@ -296,11 +304,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;
@@ -323,7 +331,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;
   }
@@ -596,7 +604,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
@@ -749,6 +756,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()) ;
@@ -798,21 +813,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/include/linux/reiserfs_fs.h linux.patched/include/linux/reiserfs_fs.h
--- linux/include/linux/reiserfs_fs.h	Sat Sep  8 23:05:32 2001
+++ linux.patched/include/linux/reiserfs_fs.h	Thu Oct 11 14:42:15 2001
@@ -17,6 +17,7 @@
 #ifdef __KERNEL__
 #include <linux/slab.h>
 #include <linux/tqueue.h>
+#include <linux/proc_fs.h>
 #endif
 
 /*
@@ -1817,6 +1818,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;
@@ -1838,7 +1900,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 (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 */
diff -rup linux/include/linux/reiserfs_fs_sb.h linux.patched/include/linux/reiserfs_fs_sb.h
--- linux/include/linux/reiserfs_fs_sb.h	Sun Sep 23 21:31:02 2001
+++ linux.patched/include/linux/reiserfs_fs_sb.h	Thu Oct 11 14:42:15 2001
@@ -264,6 +264,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
 {
@@ -302,6 +370,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;
 };
 
 
