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 <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 (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 [email protected] for PGC */
+
+/* $Id: procfs.c,v 1.1.8.2 2001/07/15 17:08:42 god Exp $ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <linux/reiserfs_fs.h>
+#include <linux/smp_lock.h>
+#include <linux/locks.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+
+#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 <linux/slab.h>
#include <linux/tqueue.h>
#include <asm/hardirq.h>
+#include <linux/proc_fs.h>
#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;
};