diff options
author | Matthew Wilcox (Oracle) <willy@infradead.org> | 2020-03-12 22:29:11 +0100 |
---|---|---|
committer | Matthew Wilcox (Oracle) <willy@infradead.org> | 2020-03-12 22:42:08 +0100 |
commit | 7e934cf5ace1dceeb804f7493fa28bb697ed3c52 (patch) | |
tree | e79bea212e334e55d606a7f184113aa724c9aa71 /tools/testing/radix-tree/test.h | |
parent | radix tree test suite: Support kmem_cache alignment (diff) | |
download | linux-7e934cf5ace1dceeb804f7493fa28bb697ed3c52.tar.xz linux-7e934cf5ace1dceeb804f7493fa28bb697ed3c52.zip |
xarray: Fix early termination of xas_for_each_marked
xas_for_each_marked() is using entry == NULL as a termination condition
of the iteration. When xas_for_each_marked() is used protected only by
RCU, this can however race with xas_store(xas, NULL) in the following
way:
TASK1 TASK2
page_cache_delete() find_get_pages_range_tag()
xas_for_each_marked()
xas_find_marked()
off = xas_find_chunk()
xas_store(&xas, NULL)
xas_init_marks(&xas);
...
rcu_assign_pointer(*slot, NULL);
entry = xa_entry(off);
And thus xas_for_each_marked() terminates prematurely possibly leading
to missed entries in the iteration (translating to missing writeback of
some pages or a similar problem).
If we find a NULL entry that has been marked, skip it (unless we're trying
to allocate an entry).
Reported-by: Jan Kara <jack@suse.cz>
CC: stable@vger.kernel.org
Fixes: ef8e5717db01 ("page cache: Convert delete_batch to XArray")
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Diffstat (limited to 'tools/testing/radix-tree/test.h')
-rw-r--r-- | tools/testing/radix-tree/test.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h index 1ee4b2c0ad10..34dab4d18744 100644 --- a/tools/testing/radix-tree/test.h +++ b/tools/testing/radix-tree/test.h @@ -34,6 +34,7 @@ void xarray_tests(void); void tag_check(void); void multiorder_checks(void); void iteration_test(unsigned order, unsigned duration); +void iteration_test2(unsigned duration); void benchmark(void); void idr_checks(void); void ida_tests(void); |