radix-tree: fix contiguous iterator
This patch fixes bug in macro radix_tree_for_each_contig(). If radix_tree_next_slot() sees NULL in next slot it returns NULL, but following radix_tree_next_chunk() switches iterating into next chunk. As result iterating becomes non-contiguous and breaks vfs "splice" and all its users. Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org> Reported-and-bisected-by: Hans de Bruin <jmdebruin@xmsnet.nl> Reported-and-bisected-by: Ondrej Zary <linux@rainbow-software.org> Reported-bisected-and-tested-by: Toralf Förster <toralf.foerster@gmx.de> Link: https://lkml.org/lkml/2012/6/5/64 Cc: stable <stable@vger.kernel.org> # 3.4.x Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
f9ba7179ce
commit
fffaee365f
|
@ -368,10 +368,13 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags)
|
||||||
iter->index++;
|
iter->index++;
|
||||||
if (likely(*slot))
|
if (likely(*slot))
|
||||||
return slot;
|
return slot;
|
||||||
if (flags & RADIX_TREE_ITER_CONTIG)
|
if (flags & RADIX_TREE_ITER_CONTIG) {
|
||||||
|
/* forbid switching to the next chunk */
|
||||||
|
iter->next_index = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -686,6 +686,9 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
|
||||||
* during iterating; it can be zero only at the beginning.
|
* during iterating; it can be zero only at the beginning.
|
||||||
* And we cannot overflow iter->next_index in a single step,
|
* And we cannot overflow iter->next_index in a single step,
|
||||||
* because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG.
|
* because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG.
|
||||||
|
*
|
||||||
|
* This condition also used by radix_tree_next_slot() to stop
|
||||||
|
* contiguous iterating, and forbid swithing to the next chunk.
|
||||||
*/
|
*/
|
||||||
index = iter->next_index;
|
index = iter->next_index;
|
||||||
if (!index && iter->index)
|
if (!index && iter->index)
|
||||||
|
|
Loading…
Reference in New Issue