From: Andrew Morton Some locking was missing around radix-tree lookups. Cc: Wu Fengguang Signed-off-by: Andrew Morton --- mm/readahead.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff -puN mm/readahead.c~readahead-context-based-method-locking-fix-2 mm/readahead.c --- a/mm/readahead.c~readahead-context-based-method-locking-fix-2 +++ a/mm/readahead.c @@ -1298,14 +1298,15 @@ try_context_based_readahead(struct addre * Case 1: we have a current page. * Search forward for a nearby hole. */ + read_lock_irq(&mapping->tree_lock); if (page) { unsigned long max_scan = ra_max + ra_min; start = radix_tree_scan_hole(&mapping->page_tree, offset, max_scan); if (start != 0 && start - offset < max_scan) goto has_history_pages; - else - return -1; + read_unlock_irq(&mapping->tree_lock); + return -1; } /* Case 2: current page is missing; previous page is present. @@ -1325,7 +1326,7 @@ try_context_based_readahead(struct addre * It can be the early stage of semi-sequential reads(interleaved/nfsd), * or an ugly random one. So be conservative. */ - if (readahead_hit_rate && probe_page(mapping, offset - 1)) { + if (readahead_hit_rate && __probe_page(mapping, offset - 1)) { start = offset; if (ra_min > 2 * readahead_hit_rate) ra_min = 2 * readahead_hit_rate; @@ -1345,10 +1346,12 @@ try_context_based_readahead(struct addre goto has_history_pages; } } + read_unlock_irq(&mapping->tree_lock); return 0; has_history_pages: + read_unlock_irq(&mapping->tree_lock); ra_size = count_history_pages(mapping, ra, offset, ra_max); if (!ra_size) return 0; _