interval_tree.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /*
  2. * mm/interval_tree.c - interval tree for mapping->i_mmap
  3. *
  4. * Copyright (C) 2012, Michel Lespinasse <walken@google.com>
  5. *
  6. * This file is released under the GPL v2.
  7. */
  8. #include <linux/mm.h>
  9. #include <linux/fs.h>
  10. #include <linux/interval_tree_generic.h>
  11. static inline unsigned long vma_start_pgoff(struct vm_area_struct *v)
  12. {
  13. return v->vm_pgoff;
  14. }
  15. static inline unsigned long vma_last_pgoff(struct vm_area_struct *v)
  16. {
  17. return v->vm_pgoff + ((v->vm_end - v->vm_start) >> PAGE_SHIFT) - 1;
  18. }
  19. INTERVAL_TREE_DEFINE(struct vm_area_struct, shared.linear.rb,
  20. unsigned long, shared.linear.rb_subtree_last,
  21. vma_start_pgoff, vma_last_pgoff,, vma_interval_tree)
  22. /* Insert node immediately after prev in the interval tree */
  23. void vma_interval_tree_insert_after(struct vm_area_struct *node,
  24. struct vm_area_struct *prev,
  25. struct rb_root *root)
  26. {
  27. struct rb_node **link;
  28. struct vm_area_struct *parent;
  29. unsigned long last = vma_last_pgoff(node);
  30. VM_BUG_ON(vma_start_pgoff(node) != vma_start_pgoff(prev));
  31. if (!prev->shared.linear.rb.rb_right) {
  32. parent = prev;
  33. link = &prev->shared.linear.rb.rb_right;
  34. } else {
  35. parent = rb_entry(prev->shared.linear.rb.rb_right,
  36. struct vm_area_struct, shared.linear.rb);
  37. if (parent->shared.linear.rb_subtree_last < last)
  38. parent->shared.linear.rb_subtree_last = last;
  39. while (parent->shared.linear.rb.rb_left) {
  40. parent = rb_entry(parent->shared.linear.rb.rb_left,
  41. struct vm_area_struct, shared.linear.rb);
  42. if (parent->shared.linear.rb_subtree_last < last)
  43. parent->shared.linear.rb_subtree_last = last;
  44. }
  45. link = &parent->shared.linear.rb.rb_left;
  46. }
  47. node->shared.linear.rb_subtree_last = last;
  48. rb_link_node(&node->shared.linear.rb, &parent->shared.linear.rb, link);
  49. rb_insert_augmented(&node->shared.linear.rb, root,
  50. &vma_interval_tree_augment);
  51. }