1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#include "../include/lustre_dlm.h"
42#include "../include/obd_support.h"
43#include "../include/interval_tree.h"
44
45enum {
46 INTERVAL_RED = 0,
47 INTERVAL_BLACK = 1
48};
49
50static inline int node_is_left_child(struct interval_node *node)
51{
52 return node == node->in_parent->in_left;
53}
54
55static inline int node_is_right_child(struct interval_node *node)
56{
57 return node == node->in_parent->in_right;
58}
59
60static inline int node_is_red(struct interval_node *node)
61{
62 return node->in_color == INTERVAL_RED;
63}
64
65static inline int node_is_black(struct interval_node *node)
66{
67 return node->in_color == INTERVAL_BLACK;
68}
69
70static inline int extent_compare(struct interval_node_extent *e1,
71 struct interval_node_extent *e2)
72{
73 int rc;
74
75 if (e1->start == e2->start) {
76 if (e1->end < e2->end)
77 rc = -1;
78 else if (e1->end > e2->end)
79 rc = 1;
80 else
81 rc = 0;
82 } else {
83 if (e1->start < e2->start)
84 rc = -1;
85 else
86 rc = 1;
87 }
88 return rc;
89}
90
91static inline int extent_equal(struct interval_node_extent *e1,
92 struct interval_node_extent *e2)
93{
94 return (e1->start == e2->start) && (e1->end == e2->end);
95}
96
97static inline __u64 max_u64(__u64 x, __u64 y)
98{
99 return x > y ? x : y;
100}
101
102static struct interval_node *interval_first(struct interval_node *node)
103{
104 if (!node)
105 return NULL;
106 while (node->in_left)
107 node = node->in_left;
108 return node;
109}
110
111static struct interval_node *interval_next(struct interval_node *node)
112{
113 if (!node)
114 return NULL;
115 if (node->in_right)
116 return interval_first(node->in_right);
117 while (node->in_parent && node_is_right_child(node))
118 node = node->in_parent;
119 return node->in_parent;
120}
121
122static void __rotate_change_maxhigh(struct interval_node *node,
123 struct interval_node *rotate)
124{
125 __u64 left_max, right_max;
126
127 rotate->in_max_high = node->in_max_high;
128 left_max = node->in_left ? node->in_left->in_max_high : 0;
129 right_max = node->in_right ? node->in_right->in_max_high : 0;
130 node->in_max_high = max_u64(interval_high(node),
131 max_u64(left_max, right_max));
132}
133
134
135
136
137
138static void __rotate_left(struct interval_node *node,
139 struct interval_node **root)
140{
141 struct interval_node *right = node->in_right;
142 struct interval_node *parent = node->in_parent;
143
144 node->in_right = right->in_left;
145 if (node->in_right)
146 right->in_left->in_parent = node;
147
148 right->in_left = node;
149 right->in_parent = parent;
150 if (parent) {
151 if (node_is_left_child(node))
152 parent->in_left = right;
153 else
154 parent->in_right = right;
155 } else {
156 *root = right;
157 }
158 node->in_parent = right;
159
160
161 __rotate_change_maxhigh(node, right);
162}
163
164
165
166
167
168static void __rotate_right(struct interval_node *node,
169 struct interval_node **root)
170{
171 struct interval_node *left = node->in_left;
172 struct interval_node *parent = node->in_parent;
173
174 node->in_left = left->in_right;
175 if (node->in_left)
176 left->in_right->in_parent = node;
177 left->in_right = node;
178
179 left->in_parent = parent;
180 if (parent) {
181 if (node_is_right_child(node))
182 parent->in_right = left;
183 else
184 parent->in_left = left;
185 } else {
186 *root = left;
187 }
188 node->in_parent = left;
189
190
191 __rotate_change_maxhigh(node, left);
192}
193
194#define interval_swap(a, b) do { \
195 struct interval_node *c = a; a = b; b = c; \
196} while (0)
197
198
199
200
201
202
203
204
205static void interval_insert_color(struct interval_node *node,
206 struct interval_node **root)
207{
208 struct interval_node *parent, *gparent;
209
210 while ((parent = node->in_parent) && node_is_red(parent)) {
211 gparent = parent->in_parent;
212
213 if (node_is_left_child(parent)) {
214 struct interval_node *uncle;
215
216 uncle = gparent->in_right;
217 if (uncle && node_is_red(uncle)) {
218 uncle->in_color = INTERVAL_BLACK;
219 parent->in_color = INTERVAL_BLACK;
220 gparent->in_color = INTERVAL_RED;
221 node = gparent;
222 continue;
223 }
224
225 if (parent->in_right == node) {
226 __rotate_left(parent, root);
227 interval_swap(node, parent);
228 }
229
230 parent->in_color = INTERVAL_BLACK;
231 gparent->in_color = INTERVAL_RED;
232 __rotate_right(gparent, root);
233 } else {
234 struct interval_node *uncle;
235
236 uncle = gparent->in_left;
237 if (uncle && node_is_red(uncle)) {
238 uncle->in_color = INTERVAL_BLACK;
239 parent->in_color = INTERVAL_BLACK;
240 gparent->in_color = INTERVAL_RED;
241 node = gparent;
242 continue;
243 }
244
245 if (node_is_left_child(node)) {
246 __rotate_right(parent, root);
247 interval_swap(node, parent);
248 }
249
250 parent->in_color = INTERVAL_BLACK;
251 gparent->in_color = INTERVAL_RED;
252 __rotate_left(gparent, root);
253 }
254 }
255
256 (*root)->in_color = INTERVAL_BLACK;
257}
258
259struct interval_node *interval_insert(struct interval_node *node,
260 struct interval_node **root)
261
262{
263 struct interval_node **p, *parent = NULL;
264
265 LASSERT(!interval_is_intree(node));
266 p = root;
267 while (*p) {
268 parent = *p;
269 if (extent_equal(&parent->in_extent, &node->in_extent))
270 return parent;
271
272
273 if (parent->in_max_high < interval_high(node))
274 parent->in_max_high = interval_high(node);
275
276 if (extent_compare(&node->in_extent, &parent->in_extent) < 0)
277 p = &parent->in_left;
278 else
279 p = &parent->in_right;
280 }
281
282
283 node->in_parent = parent;
284 node->in_color = INTERVAL_RED;
285 node->in_left = NULL;
286 node->in_right = NULL;
287 *p = node;
288
289 interval_insert_color(node, root);
290 node->in_intree = 1;
291
292 return NULL;
293}
294EXPORT_SYMBOL(interval_insert);
295
296static inline int node_is_black_or_0(struct interval_node *node)
297{
298 return !node || node_is_black(node);
299}
300
301static void interval_erase_color(struct interval_node *node,
302 struct interval_node *parent,
303 struct interval_node **root)
304{
305 struct interval_node *tmp;
306
307 while (node_is_black_or_0(node) && node != *root) {
308 if (parent->in_left == node) {
309 tmp = parent->in_right;
310 if (node_is_red(tmp)) {
311 tmp->in_color = INTERVAL_BLACK;
312 parent->in_color = INTERVAL_RED;
313 __rotate_left(parent, root);
314 tmp = parent->in_right;
315 }
316 if (node_is_black_or_0(tmp->in_left) &&
317 node_is_black_or_0(tmp->in_right)) {
318 tmp->in_color = INTERVAL_RED;
319 node = parent;
320 parent = node->in_parent;
321 } else {
322 if (node_is_black_or_0(tmp->in_right)) {
323 struct interval_node *o_left;
324
325 o_left = tmp->in_left;
326 if (o_left)
327 o_left->in_color = INTERVAL_BLACK;
328 tmp->in_color = INTERVAL_RED;
329 __rotate_right(tmp, root);
330 tmp = parent->in_right;
331 }
332 tmp->in_color = parent->in_color;
333 parent->in_color = INTERVAL_BLACK;
334 if (tmp->in_right)
335 tmp->in_right->in_color = INTERVAL_BLACK;
336 __rotate_left(parent, root);
337 node = *root;
338 break;
339 }
340 } else {
341 tmp = parent->in_left;
342 if (node_is_red(tmp)) {
343 tmp->in_color = INTERVAL_BLACK;
344 parent->in_color = INTERVAL_RED;
345 __rotate_right(parent, root);
346 tmp = parent->in_left;
347 }
348 if (node_is_black_or_0(tmp->in_left) &&
349 node_is_black_or_0(tmp->in_right)) {
350 tmp->in_color = INTERVAL_RED;
351 node = parent;
352 parent = node->in_parent;
353 } else {
354 if (node_is_black_or_0(tmp->in_left)) {
355 struct interval_node *o_right;
356
357 o_right = tmp->in_right;
358 if (o_right)
359 o_right->in_color = INTERVAL_BLACK;
360 tmp->in_color = INTERVAL_RED;
361 __rotate_left(tmp, root);
362 tmp = parent->in_left;
363 }
364 tmp->in_color = parent->in_color;
365 parent->in_color = INTERVAL_BLACK;
366 if (tmp->in_left)
367 tmp->in_left->in_color = INTERVAL_BLACK;
368 __rotate_right(parent, root);
369 node = *root;
370 break;
371 }
372 }
373 }
374 if (node)
375 node->in_color = INTERVAL_BLACK;
376}
377
378
379
380
381
382static void update_maxhigh(struct interval_node *node,
383 __u64 old_maxhigh)
384{
385 __u64 left_max, right_max;
386
387 while (node) {
388 left_max = node->in_left ? node->in_left->in_max_high : 0;
389 right_max = node->in_right ? node->in_right->in_max_high : 0;
390 node->in_max_high = max_u64(interval_high(node),
391 max_u64(left_max, right_max));
392
393 if (node->in_max_high >= old_maxhigh)
394 break;
395 node = node->in_parent;
396 }
397}
398
399void interval_erase(struct interval_node *node,
400 struct interval_node **root)
401{
402 struct interval_node *child, *parent;
403 int color;
404
405 LASSERT(interval_is_intree(node));
406 node->in_intree = 0;
407 if (!node->in_left) {
408 child = node->in_right;
409 } else if (!node->in_right) {
410 child = node->in_left;
411 } else {
412 struct interval_node *old = node;
413
414 node = interval_next(node);
415 child = node->in_right;
416 parent = node->in_parent;
417 color = node->in_color;
418
419 if (child)
420 child->in_parent = parent;
421 if (parent == old)
422 parent->in_right = child;
423 else
424 parent->in_left = child;
425
426 node->in_color = old->in_color;
427 node->in_right = old->in_right;
428 node->in_left = old->in_left;
429 node->in_parent = old->in_parent;
430
431 if (old->in_parent) {
432 if (node_is_left_child(old))
433 old->in_parent->in_left = node;
434 else
435 old->in_parent->in_right = node;
436 } else {
437 *root = node;
438 }
439
440 old->in_left->in_parent = node;
441 if (old->in_right)
442 old->in_right->in_parent = node;
443 update_maxhigh(child ? : parent, node->in_max_high);
444 update_maxhigh(node, old->in_max_high);
445 if (parent == old)
446 parent = node;
447 goto color;
448 }
449 parent = node->in_parent;
450 color = node->in_color;
451
452 if (child)
453 child->in_parent = parent;
454 if (parent) {
455 if (node_is_left_child(node))
456 parent->in_left = child;
457 else
458 parent->in_right = child;
459 } else {
460 *root = child;
461 }
462
463 update_maxhigh(child ? : parent, node->in_max_high);
464
465color:
466 if (color == INTERVAL_BLACK)
467 interval_erase_color(child, parent, root);
468}
469EXPORT_SYMBOL(interval_erase);
470