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;
};