drbd_interval.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "drbd_interval.h"
  2. /**
  3. * interval_end - return end of @node
  4. */
  5. static inline
  6. sector_t interval_end(struct rb_node *node)
  7. {
  8. struct drbd_interval *this = rb_entry(node, struct drbd_interval, rb);
  9. return this->end;
  10. }
  11. /**
  12. * update_interval_end - recompute end of @node
  13. *
  14. * The end of an interval is the highest (start + (size >> 9)) value of this
  15. * node and of its children. Called for @node and its parents whenever the end
  16. * may have changed.
  17. */
  18. static void
  19. update_interval_end(struct rb_node *node, void *__unused)
  20. {
  21. struct drbd_interval *this = rb_entry(node, struct drbd_interval, rb);
  22. sector_t end;
  23. end = this->sector + (this->size >> 9);
  24. if (node->rb_left) {
  25. sector_t left = interval_end(node->rb_left);
  26. if (left > end)
  27. end = left;
  28. }
  29. if (node->rb_right) {
  30. sector_t right = interval_end(node->rb_right);
  31. if (right > end)
  32. end = right;
  33. }
  34. this->end = end;
  35. }
  36. /**
  37. * drbd_insert_interval - insert a new interval into a tree
  38. */
  39. bool
  40. drbd_insert_interval(struct rb_root *root, struct drbd_interval *this)
  41. {
  42. struct rb_node **new = &root->rb_node, *parent = NULL;
  43. BUG_ON(!IS_ALIGNED(this->size, 512));
  44. while (*new) {
  45. struct drbd_interval *here =
  46. rb_entry(*new, struct drbd_interval, rb);
  47. parent = *new;
  48. if (this->sector < here->sector)
  49. new = &(*new)->rb_left;
  50. else if (this->sector > here->sector)
  51. new = &(*new)->rb_right;
  52. else if (this < here)
  53. new = &(*new)->rb_left;
  54. else if (this > here)
  55. new = &(*new)->rb_right;
  56. else
  57. return false;
  58. }
  59. rb_link_node(&this->rb, parent, new);
  60. rb_insert_color(&this->rb, root);
  61. rb_augment_insert(&this->rb, update_interval_end, NULL);
  62. return true;
  63. }
  64. /**
  65. * drbd_contains_interval - check if a tree contains a given interval
  66. * @sector: start sector of @interval
  67. * @interval: may not be a valid pointer
  68. *
  69. * Returns if the tree contains the node @interval with start sector @start.
  70. * Does not dereference @interval until @interval is known to be a valid object
  71. * in @tree. Returns %false if @interval is in the tree but with a different
  72. * sector number.
  73. */
  74. bool
  75. drbd_contains_interval(struct rb_root *root, sector_t sector,
  76. struct drbd_interval *interval)
  77. {
  78. struct rb_node *node = root->rb_node;
  79. while (node) {
  80. struct drbd_interval *here =
  81. rb_entry(node, struct drbd_interval, rb);
  82. if (sector < here->sector)
  83. node = node->rb_left;
  84. else if (sector > here->sector)
  85. node = node->rb_right;
  86. else if (interval < here)
  87. node = node->rb_left;
  88. else if (interval > here)
  89. node = node->rb_right;
  90. else
  91. return true;
  92. }
  93. return false;
  94. }
  95. /**
  96. * drbd_remove_interval - remove an interval from a tree
  97. */
  98. void
  99. drbd_remove_interval(struct rb_root *root, struct drbd_interval *this)
  100. {
  101. struct rb_node *deepest;
  102. deepest = rb_augment_erase_begin(&this->rb);
  103. rb_erase(&this->rb, root);
  104. rb_augment_erase_end(deepest, update_interval_end, NULL);
  105. }
  106. /**
  107. * drbd_find_overlap - search for an interval overlapping with [sector, sector + size)
  108. * @sector: start sector
  109. * @size: size, aligned to 512 bytes
  110. *
  111. * Returns an interval overlapping with [sector, sector + size), or NULL if
  112. * there is none. When there is more than one overlapping interval in the
  113. * tree, the interval with the lowest start sector is returned, and all other
  114. * overlapping intervals will be on the right side of the tree, reachable with
  115. * rb_next().
  116. */
  117. struct drbd_interval *
  118. drbd_find_overlap(struct rb_root *root, sector_t sector, unsigned int size)
  119. {
  120. struct rb_node *node = root->rb_node;
  121. struct drbd_interval *overlap = NULL;
  122. sector_t end = sector + (size >> 9);
  123. BUG_ON(!IS_ALIGNED(size, 512));
  124. while (node) {
  125. struct drbd_interval *here =
  126. rb_entry(node, struct drbd_interval, rb);
  127. if (node->rb_left &&
  128. sector < interval_end(node->rb_left)) {
  129. /* Overlap if any must be on left side */
  130. node = node->rb_left;
  131. } else if (here->sector < end &&
  132. sector < here->sector + (here->size >> 9)) {
  133. overlap = here;
  134. break;
  135. } else if (sector >= here->sector) {
  136. /* Overlap if any must be on right side */
  137. node = node->rb_right;
  138. } else
  139. break;
  140. }
  141. return overlap;
  142. }
  143. struct drbd_interval *
  144. drbd_next_overlap(struct drbd_interval *i, sector_t sector, unsigned int size)
  145. {
  146. sector_t end = sector + (size >> 9);
  147. struct rb_node *node;
  148. for (;;) {
  149. node = rb_next(&i->rb);
  150. if (!node)
  151. return NULL;
  152. i = rb_entry(node, struct drbd_interval, rb);
  153. if (i->sector >= end)
  154. return NULL;
  155. if (sector < i->sector + (i->size >> 9))
  156. return i;
  157. }
  158. }