aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mmap.c
diff options
context:
space:
mode:
authorMichel Lespinasse <walken@google.com>2012-12-11 19:01:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 20:22:25 -0500
commit5a0768f641a5bad844860e67250baf0d1aa5e03c (patch)
tree3bb26ec05c4aede8ff37474dc27b5af49892c95e /mm/mmap.c
parentd37371870ceb1d2165397dc36114725b6dca946c (diff)
mm: check rb_subtree_gap correctness
When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is correctly set for every vma and that mm->highest_vm_end is also correct. Also add an explicit 'bug' variable to track if browse_rb() detected any invalid condition. [akpm@linux-foundation.org: repair innovative coding-style inventions] Signed-off-by: Michel Lespinasse <walken@google.com> Reviewed-by: Rik van Riel <riel@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Paul Mundt <lethal@linux-sh.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Chris Metcalf <cmetcalf@tilera.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/mmap.c')
-rw-r--r--mm/mmap.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index bdcea6310fff..ff93f6c8436c 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -322,31 +322,45 @@ static long vma_compute_subtree_gap(struct vm_area_struct *vma)
322#ifdef CONFIG_DEBUG_VM_RB 322#ifdef CONFIG_DEBUG_VM_RB
323static int browse_rb(struct rb_root *root) 323static int browse_rb(struct rb_root *root)
324{ 324{
325 int i = 0, j; 325 int i = 0, j, bug = 0;
326 struct rb_node *nd, *pn = NULL; 326 struct rb_node *nd, *pn = NULL;
327 unsigned long prev = 0, pend = 0; 327 unsigned long prev = 0, pend = 0;
328 328
329 for (nd = rb_first(root); nd; nd = rb_next(nd)) { 329 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
330 struct vm_area_struct *vma; 330 struct vm_area_struct *vma;
331 vma = rb_entry(nd, struct vm_area_struct, vm_rb); 331 vma = rb_entry(nd, struct vm_area_struct, vm_rb);
332 if (vma->vm_start < prev) 332 if (vma->vm_start < prev) {
333 printk("vm_start %lx prev %lx\n", vma->vm_start, prev), i = -1; 333 printk("vm_start %lx prev %lx\n", vma->vm_start, prev);
334 if (vma->vm_start < pend) 334 bug = 1;
335 }
336 if (vma->vm_start < pend) {
335 printk("vm_start %lx pend %lx\n", vma->vm_start, pend); 337 printk("vm_start %lx pend %lx\n", vma->vm_start, pend);
336 if (vma->vm_start > vma->vm_end) 338 bug = 1;
337 printk("vm_end %lx < vm_start %lx\n", vma->vm_end, vma->vm_start); 339 }
340 if (vma->vm_start > vma->vm_end) {
341 printk("vm_end %lx < vm_start %lx\n",
342 vma->vm_end, vma->vm_start);
343 bug = 1;
344 }
345 if (vma->rb_subtree_gap != vma_compute_subtree_gap(vma)) {
346 printk("free gap %lx, correct %lx\n",
347 vma->rb_subtree_gap,
348 vma_compute_subtree_gap(vma));
349 bug = 1;
350 }
338 i++; 351 i++;
339 pn = nd; 352 pn = nd;
340 prev = vma->vm_start; 353 prev = vma->vm_start;
341 pend = vma->vm_end; 354 pend = vma->vm_end;
342 } 355 }
343 j = 0; 356 j = 0;
344 for (nd = pn; nd; nd = rb_prev(nd)) { 357 for (nd = pn; nd; nd = rb_prev(nd))
345 j++; 358 j++;
359 if (i != j) {
360 printk("backwards %d, forwards %d\n", j, i);
361 bug = 1;
346 } 362 }
347 if (i != j) 363 return bug ? -1 : i;
348 printk("backwards %d, forwards %d\n", j, i), i = 0;
349 return i;
350} 364}
351 365
352static void validate_mm_rb(struct rb_root *root, struct vm_area_struct *ignore) 366static void validate_mm_rb(struct rb_root *root, struct vm_area_struct *ignore)
@@ -365,6 +379,7 @@ void validate_mm(struct mm_struct *mm)
365{ 379{
366 int bug = 0; 380 int bug = 0;
367 int i = 0; 381 int i = 0;
382 unsigned long highest_address = 0;
368 struct vm_area_struct *vma = mm->mmap; 383 struct vm_area_struct *vma = mm->mmap;
369 while (vma) { 384 while (vma) {
370 struct anon_vma_chain *avc; 385 struct anon_vma_chain *avc;
@@ -372,14 +387,24 @@ void validate_mm(struct mm_struct *mm)
372 list_for_each_entry(avc, &vma->anon_vma_chain, same_vma) 387 list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
373 anon_vma_interval_tree_verify(avc); 388 anon_vma_interval_tree_verify(avc);
374 vma_unlock_anon_vma(vma); 389 vma_unlock_anon_vma(vma);
390 highest_address = vma->vm_end;
375 vma = vma->vm_next; 391 vma = vma->vm_next;
376 i++; 392 i++;
377 } 393 }
378 if (i != mm->map_count) 394 if (i != mm->map_count) {
379 printk("map_count %d vm_next %d\n", mm->map_count, i), bug = 1; 395 printk("map_count %d vm_next %d\n", mm->map_count, i);
396 bug = 1;
397 }
398 if (highest_address != mm->highest_vm_end) {
399 printk("mm->highest_vm_end %lx, found %lx\n",
400 mm->highest_vm_end, highest_address);
401 bug = 1;
402 }
380 i = browse_rb(&mm->mm_rb); 403 i = browse_rb(&mm->mm_rb);
381 if (i != mm->map_count) 404 if (i != mm->map_count) {
382 printk("map_count %d rb %d\n", mm->map_count, i), bug = 1; 405 printk("map_count %d rb %d\n", mm->map_count, i);
406 bug = 1;
407 }
383 BUG_ON(bug); 408 BUG_ON(bug);
384} 409}
385#else 410#else