Commit df773a2c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] reiserfs: search_by_key fix

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
parent 83e830d0
...@@ -678,7 +678,7 @@ int search_by_key (struct super_block * p_s_sb, ...@@ -678,7 +678,7 @@ int search_by_key (struct super_block * p_s_sb,
current node, and calculate the next current node(next path element) current node, and calculate the next current node(next path element)
for the next iteration of this loop.. */ for the next iteration of this loop.. */
n_block_number = SB_ROOT_BLOCK (p_s_sb); n_block_number = SB_ROOT_BLOCK (p_s_sb);
expected_level = SB_TREE_HEIGHT (p_s_sb); expected_level = -1;
while ( 1 ) { while ( 1 ) {
#ifdef CONFIG_REISERFS_CHECK #ifdef CONFIG_REISERFS_CHECK
...@@ -692,7 +692,6 @@ int search_by_key (struct super_block * p_s_sb, ...@@ -692,7 +692,6 @@ int search_by_key (struct super_block * p_s_sb,
/* prep path to have another element added to it. */ /* 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); p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length);
fs_gen = get_generation (p_s_sb); fs_gen = get_generation (p_s_sb);
expected_level --;
#ifdef SEARCH_BY_KEY_READA #ifdef SEARCH_BY_KEY_READA
/* schedule read of right neighbor */ /* schedule read of right neighbor */
...@@ -707,21 +706,26 @@ int search_by_key (struct super_block * p_s_sb, ...@@ -707,21 +706,26 @@ int search_by_key (struct super_block * p_s_sb,
pathrelse(p_s_search_path); pathrelse(p_s_search_path);
return IO_ERROR; 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 /* 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 to search is still in the tree rooted from the current buffer. If
not then repeat search from the root. */ not then repeat search from the root. */
if ( fs_changed (fs_gen, p_s_sb) && 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_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 ] ); PROC_INFO_INC( p_s_sb, sbk_restarted[ expected_level - 1 ] );
decrement_counters_in_path(p_s_search_path); decrement_counters_in_path(p_s_search_path);
/* Get the root block number so that we can repeat the search /* 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); 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; right_neighbor_of_leaf_node = 0;
/* repeat search from the root */ /* repeat search from the root */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment