]> git.baikalelectronics.ru Git - kernel.git/commit
radix-tree: radix_tree_range_tag_if_tagged() can set incorrect tags
authorDave Chinner <dchinner@redhat.com>
Mon, 23 Aug 2010 00:33:53 +0000 (10:33 +1000)
committerDave Chinner <david@fromorbit.com>
Mon, 23 Aug 2010 00:33:53 +0000 (10:33 +1000)
commit108a8592088e0156df053ab5cc9496d9e7e897ff
tree70b0d0bf73815fb242502a562da3a8c7667843ba
parentba5c74ff2d2653dbf456791be21b179e7a66ef81
radix-tree: radix_tree_range_tag_if_tagged() can set incorrect tags

Commit 920bcff7054a834f24d8b2fb1d0f7bef16918030 ("radix-tree:
omplement function radix_tree_range_tag_if_tagged") does not safely
set tags on on intermediate tree nodes. The code walks down the tree
setting tags before it has fully resolved the path to the leaf under
the assumption there will be a leaf slot with the tag set in the
range it is searching.

Unfortunately, this is not a valid assumption - we can abort after
setting a tag on an intermediate node if we overrun the number of
tags we are allowed to set in a batch, or stop scanning because we
we have passed the last scan index before we reach a leaf slot with
the tag we are searching for set.

As a result, we can leave the function with tags set on intemediate
nodes which can be tripped over later by tag-based lookups. The
result of these stale tags is that lookup may end prematurely or
livelock because the lookup cannot make progress.

The fix for the problem involves reocrding the traversal path we
take to the leaf nodes, and only propagating the tags back up the
tree once the tag is set in the leaf node slot. We are already
recording the path for efficient traversal, so there is no
additional overhead to do the intermediately node tag setting in
this manner.

This fixes a radix tree lookup livelock triggered by the new
writeback sync livelock avoidance code introduced in commit
b5d84a7834f8374c1feb0b86e070f9559ee37190 ("mm: implement writeback
livelock avoidance using page tagging").

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Acked-by: Jan Kara <jack@suse.cz>
lib/radix-tree.c