linux/mm
Nick Piggin 27d20fddc8 radix-tree: fix RCU bug
Salman Qazi describes the following radix-tree bug:

In the following case, we get can get a deadlock:

0.  The radix tree contains two items, one has the index 0.
1.  The reader (in this case find_get_pages) takes the rcu_read_lock.
2.  The reader acquires slot(s) for item(s) including the index 0 item.
3.  The non-zero index item is deleted, and as a consequence the other item is
    moved to the root of the tree. The place where it used to be is queued for
    deletion after the readers finish.
3b. The zero item is deleted, removing it from the direct slot, it remains in
    the rcu-delayed indirect node.
4.  The reader looks at the index 0 slot, and finds that the page has 0 ref
    count
5.  The reader looks at it again, hoping that the item will either be freed or
    the ref count will increase. This never happens, as the slot it is looking
    at will never be updated. Also, this slot can never be reclaimed because
    the reader is holding rcu_read_lock and is in an infinite loop.

The fix is to re-use the same "indirect" pointer case that requires a slot
lookup retry into a general "retry the lookup" bit.

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Reported-by: Salman Qazi <sqazi@google.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-11-12 07:55:32 -08:00
..
backing-dev.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6 2010-10-26 17:58:44 -07:00
bootmem.c x86, memblock: Replace e820_/_early string with memblock_ 2010-08-27 11:13:47 -07:00
bounce.c bounce: call flush_dcache_page() after bounce_copy_vec() 2010-09-09 18:57:25 -07:00
compaction.c mm: compaction: handle active and inactive fairly in too_many_isolated 2010-09-09 18:57:24 -07:00
debug-pagealloc.c
dmapool.c mm: add a might_sleep_if() to dma_pool_alloc() 2010-10-26 16:52:08 -07:00
fadvise.c
failslab.c
filemap.c radix-tree: fix RCU bug 2010-11-12 07:55:32 -08:00
filemap_xip.c
fremap.c Avoid pgoff overflow in remap_file_pages 2010-09-25 09:34:58 -07:00
highmem.c mm,x86: fix kmap_atomic_push vs ioremap_32.c 2010-10-27 18:03:05 -07:00
hugetlb.c mm/hugetlb.c: add missing spin_lock() to hugetlb_cow() 2010-10-26 16:52:11 -07:00
hwpoison-inject.c HWPOISON, hugetlb: support hwpoison injection for hugepage 2010-08-11 09:23:11 +02:00
init-mm.c mm: provide init_mm mm_context initializer 2010-08-09 20:44:54 -07:00
internal.h mm: fix is_mem_section_removable() page_order BUG_ON check 2010-10-26 16:52:11 -07:00
Kconfig Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu 2010-10-22 17:31:36 -07:00
Kconfig.debug
kmemcheck.c
kmemleak-test.c
kmemleak.c kmemleak: Fix typo in the comment 2010-08-08 21:57:23 +01:00
ksm.c ksm: fix bad user data when swapping 2010-10-04 11:09:53 -07:00
maccess.c MN10300: Save frame pointer in thread_info struct rather than global var 2010-10-27 17:29:01 +01:00
madvise.c
Makefile percpu: use percpu allocator on UP too 2010-10-02 10:26:05 +03:00
memblock.c memblock: Annotate memblock functions with __init_memblock 2010-10-11 16:00:52 -07:00
memcontrol.c memcg: null dereference on allocation failure 2010-11-12 07:55:31 -08:00
memory-failure.c mm: compaction: fix COMPACTPAGEFAILED counting 2010-10-26 16:52:06 -07:00
memory.c use clear_page()/copy_page() in favor of memset()/memcpy() on whole pages 2010-10-26 16:52:13 -07:00
memory_hotplug.c mm: do_migrate_range: reduce list_empty() check 2010-10-26 16:52:11 -07:00
mempolicy.c numa: fix slab_node(MPOL_BIND) 2010-10-28 10:04:30 -07:00
mempool.c
migrate.c mm: fix error reporting in move_pages() syscall 2010-10-26 16:52:11 -07:00
mincore.c
mlock.c mm: Move vma_stack_continue into mm.h 2010-09-09 09:05:06 -07:00
mm_init.c
mmap.c audit mmap 2010-10-30 08:45:43 -04:00
mmu_context.c
mmu_notifier.c
mmzone.c mm: page allocator: calculate a better estimate of NR_FREE_PAGES when memory is low and kswapd is awake 2010-09-09 18:57:25 -07:00
mprotect.c perf_events: Fix perf_counter_mmap() hook in mprotect() 2010-11-09 10:19:38 -08:00
mremap.c mm: remove pte_*map_nested() 2010-10-26 16:52:08 -07:00
msync.c
nommu.c audit mmap 2010-10-30 08:45:43 -04:00
oom_kill.c oom: kill all threads sharing oom killed task's mm 2010-10-26 16:52:05 -07:00
page-writeback.c writeback: remove the internal 5% low bound on dirty_ratio 2010-10-26 16:52:08 -07:00
page_alloc.c mm: add casts to/from gfp_t in gfp_to_alloc_flags() 2010-10-26 16:52:09 -07:00
page_cgroup.c
page_io.c block: unify flags for struct bio and struct request 2010-08-07 18:20:39 +02:00
page_isolation.c mm: page_isolation: codeclean fix comment and rm unneeded val init 2010-10-26 16:52:11 -07:00
pagewalk.c
percpu-km.c percpu: clear memory allocated with the km allocator 2010-10-02 10:28:42 +03:00
percpu-vm.c
percpu.c Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2010-10-24 13:41:39 -07:00
prio_tree.c
quicklist.c
readahead.c
rmap.c rmap: make anon_vma_chain_free() static 2010-10-26 16:52:10 -07:00
shmem.c convert get_sb_nodev() users 2010-10-29 04:16:31 -04:00
slab.c replace nested max/min macros with {max,min}3 macro 2010-10-26 16:52:12 -07:00
slob.c slob: fix gfp flags for order-0 page allocations 2010-10-02 10:24:28 +03:00
slub.c SLUB: Fix memory hotplug with !NUMA 2010-10-06 21:16:42 +03:00
sparse-vmemmap.c x86: Use memblock to replace early_res 2010-08-27 11:12:29 -07:00
sparse.c
swap.c fuse: use release_pages() 2010-10-27 18:03:17 -07:00
swap_state.c
swapfile.c /proc/swaps: support polling 2010-10-26 16:52:11 -07:00
thrash.c
truncate.c check ATTR_SIZE contraints in inode_change_ok 2010-08-09 16:47:39 -04:00
util.c export __get_user_pages_fast() function 2010-10-24 10:51:24 +02:00
vmalloc.c mm: add vzalloc() and vzalloc_node() helpers 2010-10-26 16:52:10 -07:00
vmscan.c vmscan: avoid setting zone congested if no page dirty 2010-11-12 07:55:31 -08:00
vmstat.c vmstat: fix offset calculation on void* 2010-11-03 14:39:58 -04:00