
From: Chris Mason <mason@suse.com>

Fix a bug in reiserfs search_by_key call, where it might not properly
detect a change in tree height during a schedule.  Originally from
vs@namesys.com


---

 25-akpm/fs/reiserfs/stree.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff -puN fs/reiserfs/stree.c~reiserfs-search-restart fs/reiserfs/stree.c
--- 25/fs/reiserfs/stree.c~reiserfs-search-restart	2004-03-12 18:25:22.078300968 -0800
+++ 25-akpm/fs/reiserfs/stree.c	2004-03-12 18:25:22.083300208 -0800
@@ -678,7 +678,7 @@ int search_by_key (struct super_block * 
        current node, and calculate the next current node(next path element)
        for the next iteration of this loop.. */
     n_block_number = SB_ROOT_BLOCK (p_s_sb);
-    expected_level = SB_TREE_HEIGHT (p_s_sb);
+    expected_level = -1;
     while ( 1 ) {
 
 #ifdef CONFIG_REISERFS_CHECK
@@ -692,7 +692,6 @@ int search_by_key (struct super_block * 
 	/* prep path to have another element added to it. */
 	p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length);
 	fs_gen = get_generation (p_s_sb);
-	expected_level --;
 
 #ifdef SEARCH_BY_KEY_READA
 	/* schedule read of right neighbor */
@@ -707,21 +706,26 @@ int search_by_key (struct super_block * 
 	    pathrelse(p_s_search_path);
 	    return IO_ERROR;
 	}
+	if (expected_level == -1)
+		expected_level = SB_TREE_HEIGHT (p_s_sb);
+	expected_level --;
 
 	/* 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)) ) {
+	    (!B_IS_IN_TREE (p_s_bh) ||
+	     B_LEVEL(p_s_bh) != expected_level ||
+	     !key_in_buffer(p_s_search_path, p_s_key, p_s_sb))) {
 	    PROC_INFO_INC( p_s_sb, search_by_key_fs_changed );
- 	    PROC_INFO_INC( p_s_sb, search_by_key_restarted );
+	    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
-               starting from the root. */
+	       starting from the root. */
 	    n_block_number = SB_ROOT_BLOCK (p_s_sb);
-	    expected_level = SB_TREE_HEIGHT (p_s_sb);
+	    expected_level = -1;
 	    right_neighbor_of_leaf_node = 0;
 	    
 	    /* repeat search from the root */

_
