From: Chris Mason 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 */ _