History

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.

Konstantin Khlebnikov committed 14 years ago

Commit fffaee31 parent f9ba7172 files · +7 −1Browse files

Unified · Split

2 files
  1. include/linux/radix-tree.h +4 −1
  2. lib/radix-tree.c +3 −0
include/linux/radix-tree.h+4−1
@@ -368,8 +368,11 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) · 367 unmodified lines
368 iter->index++;368 iter->index++;
369 if (likely(*slot))369 if (likely(*slot))
370 return slot;370 return slot;
371 if (flags & RADIX_TREE_ITER_CONTIG)371 if (flags & RADIX_TREE_ITER_CONTIG) {
372 /* forbid switching to the next chunk */
373 iter->next_index = 0;
372 break;374 break;
375 }
373 }376 }
374 }377 }
375 return NULL;378 return NULL;
lib/radix-tree.c+3−0
@@ -686,6 +686,9 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, · 685 unmodified lines
686 * during iterating; it can be zero only at the beginning.686 * during iterating; it can be zero only at the beginning.
687 * And we cannot overflow iter->next_index in a single step,687 * And we cannot overflow iter->next_index in a single step,
688 * because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG.688 * because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG.
689 *
690 * This condition also used by radix_tree_next_slot() to stop
691 * contiguous iterating, and forbid swithing to the next chunk.
689 */692 */
690 index = iter->next_index;693 index = iter->next_index;
691 if (!index && iter->index)694 if (!index && iter->index)