diff -Nru linux/fs/reiserfs/fix_node.c linux.old/fs/reiserfs/fix_node.c
--- linux/fs/reiserfs/fix_node.c        Fri Apr 20 11:43:58 2001
+++ linux.old/fs/reiserfs/fix_node.c    Fri Apr 20 11:43:58 2001
@@ -2087,6 +2087,7 @@
    unsigned long              n_son_number;
    struct super_block  *      p_s_sb = p_s_tb->tb_sb;
    struct buffer_head  * p_s_bh;
+    int was_read;


    if ( p_s_tb->lnum[n_h] ) {
@@ -2100,7 +2101,7 @@

       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_read_node (p_s_sb, n_son_number, &was_read);
       if (!p_s_bh)
           return IO_ERROR;
       if ( FILESYSTEM_CHANGED_TB (p_s_tb) ) {
@@ -2108,6 +2109,15 @@
           return REPEAT_SEARCH;
       }

+       if (
+#ifndef CONFIG_REISERFS_CHECK
+       was_read &&
+#endif
+       reiserfs_check_node(p_s_bh, n_h + 1)) {
+           brelse (p_s_bh);
+           return IO_ERROR;
+       }
+
#ifdef CONFIG_REISERFS_CHECK
       if ( ! B_IS_IN_TREE(p_s_tb->FL[n_h]) || n_child_position > B_NR_ITEMS(p_s_tb->FL[n_h]) ||
            B_N_CHILD_NUM(p_s_tb->FL[n_h], n_child_position) != p_s_bh->b_blocknr )
@@ -2134,13 +2144,23 @@

       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_read_node(p_s_sb, n_son_number, &was_read);
       if (!p_s_bh)
           return IO_ERROR;
       if ( FILESYSTEM_CHANGED_TB (p_s_tb) ) {
           decrement_bcount(p_s_bh);
           return REPEAT_SEARCH;
       }
+
+       if (
+#ifndef CONFIG_REISERFS_CHECK
+       was_read &&
+#endif
+       reiserfs_check_node(p_s_bh, n_h + 1)) {
+           brelse (p_s_bh);
+           return IO_ERROR;
+       }
+
       decrement_bcount(p_s_tb->R[n_h]);
       p_s_tb->R[n_h] = p_s_bh;

diff -Nru linux/fs/reiserfs/item_ops.c linux.old/fs/reiserfs/item_ops.c
--- linux/fs/reiserfs/item_ops.c        Fri Apr 20 11:43:58 2001
+++ linux.old/fs/reiserfs/item_ops.c    Fri Apr 20 11:43:58 2001
@@ -20,6 +20,8 @@
/* and where are the comments? how about saying where we can find an
   explanation of each item handler method? -Hans */

+#define check_key_version(ih, key) (ih_version(ih) == le_key_version(key))
+
//////////////////////////////////////////////////////////////////////////////
// stat data functions
//
@@ -74,9 +76,12 @@
    }
}

-static void sd_check_item (struct item_head * ih, char * item)
+static int sd_check_item (struct item_head * ih, char * item)
{
-    // FIXME: type something here!
+    if (ih_version(ih) == ITEM_VERSION_1) {
+       return (ih_item_len(ih) == SD_V1_SIZE);
+    }
+    return (ih_item_len(ih) == SD_SIZE);
}


@@ -178,9 +183,9 @@
}


-static void direct_check_item (struct item_head * ih, char * item)
+static int direct_check_item (struct item_head * ih, char * item)
{
-    // FIXME: type something here!
+    return check_key_version(ih, &(ih)->ih_key);
}


@@ -329,9 +334,9 @@
    printk ("]\n");
}

-static void indirect_check_item (struct item_head * ih, char * item)
+static int indirect_check_item (struct item_head * ih, char * item)
{
-    // FIXME: type something here!
+    return check_key_version(ih, &(ih)->ih_key);
}


@@ -464,7 +469,7 @@
}


-static void direntry_check_item (struct item_head * ih, char * item)
+static int direntry_check_item (struct item_head * ih, char * item)
{
    int i;
    struct reiserfs_de_head * deh;
@@ -474,6 +479,13 @@
    for (i = 0; i < I_ENTRY_COUNT (ih); i ++, deh ++) {
       ;
    }
+    if (ih_version(ih) != ITEM_VERSION_1 ||
+       le_key_version(&ih->ih_key)) {
+       reiserfs_warning ("direntry_check_item: item or item key version "
+                         "is not suitable here.\n");
+       return 0;
+    }
+    return 1;
}


diff -Nru linux/fs/reiserfs/stree.c linux.old/fs/reiserfs/stree.c
--- linux/fs/reiserfs/stree.c   Fri Apr 20 11:43:58 2001
+++ linux.old/fs/reiserfs/stree.c       Fri Apr 20 11:43:58 2001
@@ -568,6 +568,12 @@
           reiserfs_warning ("is_leaf: item location seems wrong (second one): %h\n", ih);
           return 0;
       }
+
+       if (!op_check_item(ih, B_I_PITEM(bh,ih))) {
+           reiserfs_warning ("is_leaf: item (%h) has not passed internal check\n", ih);
+           return 0;
+       }
+
       prev_location = ih_location (ih);
    }

@@ -608,20 +614,26 @@
    return 1;
}

-
-// make sure that bh contains formatted node of reiserfs tree of
-// 'level'-th level
-static int is_tree_node (struct buffer_head * bh, int level)
+int reiserfs_check_node (struct buffer_head *bh, int level)
{
    if (B_LEVEL (bh) != level) {
-       printk ("is_tree_node: node level %d does not match to the expected one %d\n",
+       printk (__FUNCTION__ ": node level %d does not match to the expected one %d\n",
               B_LEVEL (bh), level);
+       goto error;
+    }
+
+    if (level == DISK_LEAF_NODE_LEVEL) {
+       if (is_leaf (bh->b_data, bh->b_size, bh))
+           return 0;           /* OK */
+    } else if (is_internal (bh->b_data, bh->b_size, bh)) {
       return 0;
    }
-    if (level == DISK_LEAF_NODE_LEVEL)
-       return is_leaf (bh->b_data, bh->b_size, bh);

-    return is_internal (bh->b_data, bh->b_size, bh);
+ error:
+    mark_buffer_uptodate(bh, 0);
+    reiserfs_warning("zam-5100: " __FUNCTION__ ": "
+                    "reiserfs format violation in block %lu\n", bh->b_blocknr);
+    return IO_ERROR;
}


@@ -646,6 +658,28 @@

#endif

+struct buffer_head * reiserfs_read_node (struct super_block *sb,
+                                        int block,
+                                        int * was_read)
+{
+    struct buffer_head *bh;
+
+    bh = getblk(sb->s_dev, block, sb->s_blocksize);
+    if (buffer_uptodate(bh)) {
+       *was_read = 0;
+       return bh;
+    } else {
+       *was_read = 1;
+       ll_rw_block(READ, 1, &bh);
+       wait_on_buffer(bh);
+       if (buffer_uptodate(bh))
+           return bh;
+    }
+
+    brelse(bh);
+    return NULL;
+}
+
/**************************************************************************
 * Algorithm   SearchByKey                                                *
 *             look for item in the Disk S+Tree by its key                *
@@ -680,15 +714,14 @@
                                       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;
+    int  n_block_number = SB_ROOT_BLOCK (p_s_sb);
+    int expected_level = SB_TREE_HEIGHT (p_s_sb);
    struct buffer_head  *       p_s_bh;
    struct path_element *       p_s_last_element;
    int                                n_node_level, n_retval;
    int                        right_neighbor_of_leaf_node;
    int                                fs_gen;
+    int                         was_read;

#ifdef CONFIG_REISERFS_CHECK
    int n_repeat_counter = 0;
@@ -727,8 +760,10 @@

       /* 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)) ) {
+       p_s_bh = p_s_last_element->pe_buffer =
+           reiserfs_read_node(p_s_sb, n_block_number, &was_read);
+
+       if (!p_s_bh) {
           p_s_search_path->path_length --;
           pathrelse(p_s_search_path);
           return IO_ERROR;
@@ -764,7 +799,11 @@

       // make sure, that the node contents look like a node of
       // certain level
-       if (!is_tree_node (p_s_bh, expected_level)) {
+        if (
+#ifndef CONFIG_REISERFS_CHECK
+           was_read &&
+#endif
+           reiserfs_check_node (p_s_bh, expected_level)) {
           reiserfs_warning ("vs-5150: search_by_key: "
                             "invalid format found in block %d. Fsck?\n", p_s_bh->b_blocknr);
           pathrelse (p_s_search_path);
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h       Fri Apr 20 11:43:58 2001
+++ b/include/linux/reiserfs_fs.h       Fri Apr 20 11:43:58 2001
@@ -1398,7 +1398,7 @@
    void (*decrement_key) (struct cpu_key *);
    int (*is_left_mergeable) (struct key * ih, unsigned long bsize);
    void (*print_item) (struct item_head *, char * item);
-    void (*check_item) (struct item_head *, char * item);
+    int (*check_item) (struct item_head *, char * item);

    int (*create_vi) (struct virtual_node * vn, struct virtual_item * vi,
                     int is_affected, int insert_size);
@@ -1714,6 +1714,8 @@
int comp_items (struct item_head  * p_s_ih, struct path * p_s_path);
struct key * get_rkey (struct path * p_s_chk_path, struct super_block  * p_s_sb);
inline int bin_search (void * p_v_key, void * p_v_base, int p_n_num, int p_n_width, int * p_n_pos);
+struct buffer_head * reiserfs_read_node (struct super_block*, int, int*);
+int reiserfs_check_node (struct buffer_head*, int);
int search_by_key (struct super_block *, struct cpu_key *, struct path *, int);
#define search_item(s,key,path) search_by_key (s, key, path, DISK_LEAF_NODE_LEVEL)
int search_for_position_by_key (struct super_block * p_s_sb, struct cpu_key * p_s_cpu_key, struct path * p_s_search_path);