On Thu 12-08-10 14:35:47, Christoph Hellwig wrote: > I have an oops with current Linus' tree in xfstests 217 that looks > like it was caused by this patch: Thanks for report! > 217 149s ...[ 5105.342605] XFS mounting filesystem vdb6 > [ 5105.373481] Ending clean XFS mount for filesystem: vdb6 > [ 5115.405061] XFS mounting filesystem loop0 > [ 5115.548654] Ending clean XFS mount for filesystem: loop0 > [ 5115.588067] BUG: unable to handle kernel paging request at f7f14000 > [ 5115.588067] IP: [<c07224fd>] radix_tree_range_tag_if_tagged+0x15d/0x1c0 > [ 5115.588067] *pde = 00007067 *pte = 00000000 > [ 5115.588067] Oops: 0000 [#1] SMP > [ 5115.588067] last sysfs file: > /sys/devices/virtual/block/loop0/removable We seem to oops at: while (((index >> shift) & RADIX_TREE_MAP_MASK) == 0) { /* * We've fully scanned this node. Go up. Because * last_index is guaranteed to be in the tree, what * we do below cannot wander astray. */ >>>>> slot = open_slots[height]; height++; shift += RADIX_TREE_MAP_SHIFT; } > Entering kdb (current=0xf7868100, pid 15675) on processor 0 Oops: (null) due to oops @ 0xc07224fd > <d>Modules linked in: > <c> > <d>Pid: 15675, comm: mkfs.xfs Not tainted 2.6.35+ #305 /Bochs > <d>EIP: 0060:[<c07224fd>] EFLAGS: 00010002 CPU: 0 > EIP is at radix_tree_range_tag_if_tagged+0x15d/0x1c0 > <d>EAX: f7f14000 EBX: 00000000 ECX: 482bb4f8 EDX: 0c0748d4 > <d>ESI: 2031756d EDI: 00000000 EBP: c7d41d10 ESP: c7d41cb0 And from the values in registers the loop seems to have went astray because "index" was zero at the point we entered the loop... looking around... Ah, I see, you create files with 16TB size which creates radix tree of such height that radix_tree_maxindex(height) == ~0UL and if write_cache_pages() passes in ~0UL as end, we can overflow the index. Hmm, I haven't realized that is possible. OK, attached is a patch that should fix the issue. There is just still an issue that *first_indexp will overflow in this case as well and thus we could in theory loop indefinitely. I'll have to think how to best handle this overflow - checking in caller is kind of prone to errors... Honza -- Jan Kara <jack@xxxxxxx> SUSE Labs, CR
>From c2095a0047822139a7f72ba6e766e94acd4affaf Mon Sep 17 00:00:00 2001 From: Jan Kara <jack@xxxxxxx> Date: Fri, 13 Aug 2010 00:20:25 +0200 Subject: [PATCH] mm: Fix overflow in radix_tree_range_tag_if_tagged When radix_tree_maxindex() is ~0UL, it can happen that scanning overflows index and tree traversal code goes astray reading memory until it hits unreadable memory. Check for overflow and exit in that case. Signed-off-by: Jan Kara <jack@xxxxxxx> --- lib/radix-tree.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 549ce9c..6a6c81d 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -673,7 +673,8 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, next: /* Go to next item at level determined by 'shift' */ index = ((index >> shift) + 1) << shift; - if (index > last_index) + /* Overflow can happen when last_index is ~0UL... */ + if (index > last_index || !index) break; if (tagged > nr_to_tag) break; -- 1.6.4.2