Whamcloud - gitweb
Land b1_8_gate onto b1_8 (20081218_1708)
[fs/lustre-release.git] / lustre / ldlm / interval_tree.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/ldlm/interval_tree.c
37  *
38  * Interval tree library used by ldlm extent lock code
39  *
40  * Author: Huang Wei <huangwei@clusterfs.com>
41  * Author: Jay Xiong <jinshan.xiong@sun.com>
42  */
43 #ifdef __KERNEL__
44 # include <lustre_dlm.h>
45 #else
46 # include <liblustre.h>
47 # include <libcfs/kp30.h>
48 #endif
49 #include <obd_support.h>
50 #include <interval_tree.h>
51
52 enum {
53         INTERVAL_RED = 0,
54         INTERVAL_BLACK = 1
55 };
56
57 static inline int node_is_left_child(struct interval_node *node)
58 {
59         LASSERT(node->in_parent != NULL);
60         return node == node->in_parent->in_left;
61 }
62
63 static inline int node_is_right_child(struct interval_node *node)
64 {
65         LASSERT(node->in_parent != NULL);
66         return node == node->in_parent->in_right;
67 }
68
69 static inline int node_is_red(struct interval_node *node)
70 {
71         return node->in_color == INTERVAL_RED;
72 }
73
74 static inline int node_is_black(struct interval_node *node)
75 {
76         return node->in_color == INTERVAL_BLACK;
77 }
78
79 static inline int extent_compare(struct interval_node_extent *e1,
80                                  struct interval_node_extent *e2)
81 {
82         int rc;
83         if (e1->start == e2->start) {
84                 if (e1->end < e2->end)
85                         rc = -1;
86                 else if (e1->end > e2->end)
87                         rc = 1;
88                 else
89                         rc = 0;
90         } else {
91                 if (e1->start < e2->start)
92                         rc = -1;
93                 else
94                         rc = 1;
95         }
96         return rc;
97 }
98
99 static inline int extent_equal(struct interval_node_extent *e1,
100                                struct interval_node_extent *e2)
101 {
102         return (e1->start == e2->start) && (e1->end == e2->end);
103 }
104
105 static inline int extent_overlapped(struct interval_node_extent *e1, 
106                                     struct interval_node_extent *e2)
107 {
108         return (e1->start <= e2->end) && (e2->start <= e1->end);
109 }
110
111 static inline int node_compare(struct interval_node *n1,
112                                struct interval_node *n2)
113 {
114         return extent_compare(&n1->in_extent, &n2->in_extent);
115 }
116
117 static inline int node_equal(struct interval_node *n1,
118                              struct interval_node *n2)
119 {
120         return extent_equal(&n1->in_extent, &n2->in_extent);
121 }
122
123 static inline __u64 max_u64(__u64 x, __u64 y)
124 {
125         return x > y ? x : y;
126 }
127
128 static inline __u64 min_u64(__u64 x, __u64 y)
129 {
130         return x < y ? x : y;
131 }
132
133 #define interval_for_each(node, root)                   \
134 for (node = interval_first(root); node != NULL;         \
135      node = interval_next(node))
136
137 #define interval_for_each_reverse(node, root)           \
138 for (node = interval_last(root); node != NULL;          \
139      node = interval_prev(node))
140
141 static struct interval_node *interval_first(struct interval_node *node)
142 {
143         ENTRY;
144
145         if (!node)
146                 RETURN(NULL);
147         while (node->in_left)
148                 node = node->in_left;
149         RETURN(node);
150 }
151
152 static struct interval_node *interval_last(struct interval_node *node)
153 {
154         ENTRY;
155
156         if (!node)
157                 RETURN(NULL);
158         while (node->in_right)
159                 node = node->in_right;
160         RETURN(node);
161 }
162
163 static struct interval_node *interval_next(struct interval_node *node)
164 {
165         ENTRY;
166
167         if (!node)
168                 RETURN(NULL);
169         if (node->in_right)
170                 RETURN(interval_first(node->in_right));
171         while (node->in_parent && node_is_right_child(node))
172                 node = node->in_parent;
173         RETURN(node->in_parent);
174 }
175
176 static struct interval_node *interval_prev(struct interval_node *node)
177 {
178         ENTRY;
179
180         if (!node)
181                 RETURN(NULL);
182
183         if (node->in_left)
184                 RETURN(interval_last(node->in_left));
185
186         while (node->in_parent && node_is_left_child(node))
187                 node = node->in_parent;
188
189         RETURN(node->in_parent);
190 }
191
192 enum interval_iter interval_iterate(struct interval_node *root,
193                                     interval_callback_t func,
194                                     void *data)
195 {
196         struct interval_node *node;
197         enum interval_iter rc = INTERVAL_ITER_CONT;
198         ENTRY;
199         
200         interval_for_each(node, root) {
201                 rc = func(node, data);
202                 if (rc == INTERVAL_ITER_STOP)
203                         break;
204         }
205
206         RETURN(rc);
207 }
208 EXPORT_SYMBOL(interval_iterate);
209
210 enum interval_iter interval_iterate_reverse(struct interval_node *root,
211                                             interval_callback_t func,
212                                             void *data)
213 {
214         struct interval_node *node;
215         enum interval_iter rc = INTERVAL_ITER_CONT;
216         ENTRY;
217         
218         interval_for_each_reverse(node, root) {
219                 rc = func(node, data);
220                 if (rc == INTERVAL_ITER_STOP)
221                         break;
222         }
223
224         RETURN(rc);
225 }
226 EXPORT_SYMBOL(interval_iterate_reverse);
227
228 /* try to find a node with same interval in the tree,
229  * if found, return the pointer to the node, otherwise return NULL*/
230 struct interval_node *interval_find(struct interval_node *root,
231                                     struct interval_node_extent *ex)
232 {
233         struct interval_node *walk = root;
234         int rc;
235         ENTRY;
236
237         while (walk) {
238                 rc = extent_compare(ex, &walk->in_extent);
239                 if (rc == 0)
240                         break;
241                 else if (rc < 0)
242                         walk = walk->in_left;
243                 else
244                         walk = walk->in_right;
245         }
246
247         RETURN(walk);
248 }
249 EXPORT_SYMBOL(interval_find);
250
251 static void __rotate_change_maxhigh(struct interval_node *node,
252                                     struct interval_node *rotate)
253 {
254         __u64 left_max, right_max;
255
256         rotate->in_max_high = node->in_max_high;
257         left_max = node->in_left ? node->in_left->in_max_high : 0;
258         right_max = node->in_right ? node->in_right->in_max_high : 0;
259         node->in_max_high  = max_u64(interval_high(node),
260                                      max_u64(left_max,right_max));
261 }
262
263 /* The left rotation "pivots" around the link from node to node->right, and
264  * - node will be linked to node->right's left child, and
265  * - node->right's left child will be linked to node's right child.  */
266 static void __rotate_left(struct interval_node *node,
267                           struct interval_node **root)
268 {
269         struct interval_node *right = node->in_right;
270         struct interval_node *parent = node->in_parent;
271
272         node->in_right = right->in_left;
273         if (node->in_right)
274                 right->in_left->in_parent = node;
275
276         right->in_left = node;
277         right->in_parent = parent;
278         if (parent) {
279                 if (node_is_left_child(node))
280                         parent->in_left = right;
281                 else
282                         parent->in_right = right;
283         } else {
284                 *root = right;
285         }
286         node->in_parent = right;
287
288         /* update max_high for node and right */
289         __rotate_change_maxhigh(node, right);
290 }
291
292 /* The right rotation "pivots" around the link from node to node->left, and
293  * - node will be linked to node->left's right child, and
294  * - node->left's right child will be linked to node's left child.  */
295 static void __rotate_right(struct interval_node *node,
296                            struct interval_node **root)
297 {
298         struct interval_node *left = node->in_left;
299         struct interval_node *parent = node->in_parent;
300
301         node->in_left = left->in_right;
302         if (node->in_left)
303                 left->in_right->in_parent = node;
304         left->in_right = node;
305
306         left->in_parent = parent;
307         if (parent) {
308                 if (node_is_right_child(node))
309                         parent->in_right = left;
310                 else
311                         parent->in_left = left;
312         } else {
313                 *root = left;
314         }
315         node->in_parent = left;
316
317         /* update max_high for node and left */
318         __rotate_change_maxhigh(node, left);
319 }
320
321 #define interval_swap(a, b) do {                        \
322         struct interval_node *c = a; a = b; b = c;      \
323 } while (0)
324
325 /*
326  * Operations INSERT and DELETE, when run on a tree with n keys, 
327  * take O(logN) time.Because they modify the tree, the result 
328  * may violate the red-black properties.To restore these properties, 
329  * we must change the colors of some of the nodes in the tree 
330  * and also change the pointer structure.
331  */
332 static void interval_insert_color(struct interval_node *node,
333                                   struct interval_node **root)
334 {
335         struct interval_node *parent, *gparent;
336         ENTRY;
337
338         while ((parent = node->in_parent) && node_is_red(parent)) {
339                 gparent = parent->in_parent;
340                 /* Parent is RED, so gparent must not be NULL */
341                 if (node_is_left_child(parent)) {
342                         struct interval_node *uncle;
343                         uncle = gparent->in_right;
344                         if (uncle && node_is_red(uncle)) {
345                                 uncle->in_color = INTERVAL_BLACK;
346                                 parent->in_color = INTERVAL_BLACK;
347                                 gparent->in_color = INTERVAL_RED;
348                                 node = gparent;
349                                 continue;
350                         }
351
352                         if (parent->in_right == node) {
353                                 __rotate_left(parent, root);
354                                 interval_swap(node, parent);
355                         }
356
357                         parent->in_color = INTERVAL_BLACK;
358                         gparent->in_color = INTERVAL_RED;
359                         __rotate_right(gparent, root);
360                 } else {
361                         struct interval_node *uncle;
362                         uncle = gparent->in_left;
363                         if (uncle && node_is_red(uncle)) {
364                                 uncle->in_color = INTERVAL_BLACK;
365                                 parent->in_color = INTERVAL_BLACK;
366                                 gparent->in_color = INTERVAL_RED;
367                                 node = gparent;
368                                 continue;
369                         }
370
371                         if (node_is_left_child(node)) {
372                                 __rotate_right(parent, root);
373                                 interval_swap(node, parent);
374                         }
375
376                         parent->in_color = INTERVAL_BLACK;
377                         gparent->in_color = INTERVAL_RED;
378                         __rotate_left(gparent, root);
379                 }
380         }
381
382         (*root)->in_color = INTERVAL_BLACK;
383         EXIT;
384 }
385
386 struct interval_node *interval_insert(struct interval_node *node,
387                                       struct interval_node **root)
388                      
389 {
390         struct interval_node **p, *parent = NULL;
391         ENTRY;
392
393         LASSERT(!interval_is_intree(node));
394         p = root;
395         while (*p) {
396                 parent = *p;
397                 if (node_equal(parent, node))
398                         RETURN(parent);
399
400                 /* max_high field must be updated after each iteration */
401                 if (parent->in_max_high < interval_high(node))
402                         parent->in_max_high = interval_high(node);
403
404                 if (node_compare(node, parent) < 0)
405                         p = &parent->in_left;
406                 else 
407                         p = &parent->in_right;
408         }
409
410         /* link node into the tree */
411         node->in_parent = parent;
412         node->in_color = INTERVAL_RED;
413         node->in_left = node->in_right = NULL;
414         *p = node;
415
416         interval_insert_color(node, root);
417         node->in_intree = 1;
418
419         RETURN(NULL);
420 }
421 EXPORT_SYMBOL(interval_insert);
422
423 static inline int node_is_black_or_0(struct interval_node *node)
424 {
425         return !node || node_is_black(node);
426 }
427
428 static void interval_erase_color(struct interval_node *node,
429                                  struct interval_node *parent,
430                                  struct interval_node **root)
431 {
432         struct interval_node *tmp;
433         ENTRY;
434
435         while (node_is_black_or_0(node) && node != *root) {
436                 if (parent->in_left == node) {
437                         tmp = parent->in_right;
438                         if (node_is_red(tmp)) {
439                                 tmp->in_color = INTERVAL_BLACK;
440                                 parent->in_color = INTERVAL_RED;
441                                 __rotate_left(parent, root);
442                                 tmp = parent->in_right;
443                         }
444                         if (node_is_black_or_0(tmp->in_left) &&
445                             node_is_black_or_0(tmp->in_right)) {
446                                 tmp->in_color = INTERVAL_RED;
447                                 node = parent;
448                                 parent = node->in_parent;
449                         } else {
450                                 if (node_is_black_or_0(tmp->in_right)) {
451                                         struct interval_node *o_left;
452                                         if ((o_left = tmp->in_left))
453                                              o_left->in_color = INTERVAL_BLACK;
454                                         tmp->in_color = INTERVAL_RED;
455                                         __rotate_right(tmp, root);
456                                         tmp = parent->in_right;
457                                 }
458                                 tmp->in_color = parent->in_color;
459                                 parent->in_color = INTERVAL_BLACK;
460                                 if (tmp->in_right)
461                                     tmp->in_right->in_color = INTERVAL_BLACK;
462                                 __rotate_left(parent, root);
463                                 node = *root;
464                                 break;
465                         }
466                 } else {
467                         tmp = parent->in_left;
468                         if (node_is_red(tmp)) {
469                                 tmp->in_color = INTERVAL_BLACK;
470                                 parent->in_color = INTERVAL_RED;
471                                 __rotate_right(parent, root);
472                                 tmp = parent->in_left;
473                         }
474                         if (node_is_black_or_0(tmp->in_left) &&
475                             node_is_black_or_0(tmp->in_right)) {
476                                 tmp->in_color = INTERVAL_RED;
477                                 node = parent;
478                                 parent = node->in_parent;
479                         } else {
480                                 if (node_is_black_or_0(tmp->in_left)) {
481                                         struct interval_node *o_right;
482                                         if ((o_right = tmp->in_right))
483                                             o_right->in_color = INTERVAL_BLACK;
484                                         tmp->in_color = INTERVAL_RED;
485                                         __rotate_left(tmp, root);
486                                         tmp = parent->in_left;
487                                 }
488                                 tmp->in_color = parent->in_color;
489                                 parent->in_color = INTERVAL_BLACK;
490                                 if (tmp->in_left)
491                                         tmp->in_left->in_color = INTERVAL_BLACK;
492                                 __rotate_right(parent, root);
493                                 node = *root;
494                                 break;
495                         }
496                 }
497         }
498         if (node)
499                 node->in_color = INTERVAL_BLACK;
500         EXIT;
501 }
502
503 /* 
504  * if the @max_high value of @node is changed, this function traverse  a path 
505  * from node  up to the root to update max_high for the whole tree.
506  */
507 static void update_maxhigh(struct interval_node *node,
508                            __u64  old_maxhigh)
509 {
510         __u64 left_max, right_max;
511         ENTRY;
512
513         while (node) {
514                 left_max = node->in_left ? node->in_left->in_max_high : 0;
515                 right_max = node->in_right ? node->in_right->in_max_high : 0;
516                 node->in_max_high = max_u64(interval_high(node),
517                                             max_u64(left_max, right_max));
518
519                 if (node->in_max_high >= old_maxhigh)
520                         break;
521                 node = node->in_parent;
522         }
523         EXIT;
524 }
525
526 void interval_erase(struct interval_node *node,
527                     struct interval_node **root)
528 {
529         struct interval_node *child, *parent;
530         int color;
531         ENTRY;
532
533         LASSERT(interval_is_intree(node));
534         node->in_intree = 0;
535         if (!node->in_left) {
536                 child = node->in_right;
537         } else if (!node->in_right) {
538                 child = node->in_left;
539         } else { /* Both left and right child are not NULL */
540                 struct interval_node *old = node;
541
542                 node = interval_next(node);
543                 child = node->in_right;
544                 parent = node->in_parent;
545                 color = node->in_color;
546
547                 if (child)
548                         child->in_parent = parent;
549                 if (parent == old) {
550                         parent->in_right = child;
551                         parent = node;
552                 } else {
553                         parent->in_left = child;
554                 }
555
556                 node->in_color = old->in_color;
557                 node->in_right = old->in_right;
558                 node->in_left = old->in_left;
559                 node->in_parent = old->in_parent;
560
561                 if (old->in_parent) {
562                         if (node_is_left_child(old))
563                                 old->in_parent->in_left = node;
564                         else
565                                 old->in_parent->in_right = node;
566                 } else {
567                         *root = node;
568                 }
569
570                 old->in_left->in_parent = node;
571                 if (old->in_right)
572                         old->in_right->in_parent = node;
573                 update_maxhigh(child, node->in_max_high);
574                 update_maxhigh(node, old->in_max_high);
575                 goto color;
576         }
577         parent = node->in_parent;
578         color = node->in_color;
579
580         if (child)
581                 child->in_parent = parent;
582         if (parent) {
583                 if (node_is_left_child(node))
584                         parent->in_left = child;
585                 else
586                         parent->in_right = child;
587         } else {
588                 *root = child;
589         }
590
591         update_maxhigh(child, node->in_max_high);
592
593 color:
594         if (color == INTERVAL_BLACK)
595                 interval_erase_color(child, parent, root);
596         EXIT;
597 }
598 EXPORT_SYMBOL(interval_erase);
599
600 static inline int interval_may_overlap(struct interval_node *node,
601                                           struct interval_node_extent *ext)
602 {
603         return (ext->start <= node->in_max_high &&
604                 ext->end >= interval_low(node));
605 }
606
607 /*
608  * This function finds all intervals that overlap interval ext,
609  * and calls func to handle resulted intervals one by one.
610  * in lustre, this function will find all conflicting locks in
611  * the granted queue and add these locks to the ast work list.
612  *
613  * {
614  *       if (node == NULL)
615  *               return 0;
616  *       if (ext->end < interval_low(node)) {
617  *               interval_search(node->in_left, ext, func, data);
618  *       } else if (interval_may_overlap(node, ext)) {
619  *               if (extent_overlapped(ext, &node->in_extent))
620  *                       func(node, data);
621  *               interval_search(node->in_left, ext, func, data);
622  *               interval_search(node->in_right, ext, func, data);
623  *       }
624  *       return 0;
625  * }
626  *
627  */
628 enum interval_iter interval_search(struct interval_node *node,
629                                    struct interval_node_extent *ext,
630                                    interval_callback_t func,
631                                    void *data)
632 {
633         struct interval_node *parent;
634         enum interval_iter rc = INTERVAL_ITER_CONT;
635
636         LASSERT(ext != NULL);
637         LASSERT(func != NULL);
638
639         while (node) {
640                 if (ext->end < interval_low(node)) {
641                         if (node->in_left) {
642                                 node = node->in_left;
643                                 continue;
644                         }
645                 } else if (interval_may_overlap(node, ext)) {
646                         if (extent_overlapped(ext, &node->in_extent)) {
647                                 rc = func(node, data);
648                                 if (rc == INTERVAL_ITER_STOP)
649                                         break;
650                         }
651
652                         if (node->in_left) {
653                                 node = node->in_left;
654                                 continue;
655                         }
656                         if (node->in_right) {
657                                 node = node->in_right;
658                                 continue;
659                         }
660                 } 
661
662                 parent = node->in_parent;
663                 while (parent) {
664                         if (node_is_left_child(node) &&
665                             parent->in_right) {
666                                 /* If we ever got the left, it means that the 
667                                  * parent met ext->end<interval_low(parent), or
668                                  * may_overlap(parent). If the former is true,
669                                  * we needn't go back. So stop early and check
670                                  * may_overlap(parent) after this loop.  */
671                                 node = parent->in_right;
672                                 break;
673                         }
674                         node = parent;
675                         parent = parent->in_parent;
676                 }
677                 if (parent == NULL || !interval_may_overlap(parent, ext))
678                         break;
679         }
680
681         return rc;
682 }
683 EXPORT_SYMBOL(interval_search);
684
685 static enum interval_iter interval_overlap_cb(struct interval_node *n,
686                                               void *args)
687 {
688         *(int *)args = 1;
689         return INTERVAL_ITER_STOP;
690 }
691
692 int interval_is_overlapped(struct interval_node *root,
693                            struct interval_node_extent *ext)
694 {
695         int has = 0;
696         (void)interval_search(root, ext, interval_overlap_cb, &has);
697         return has;
698 }
699 EXPORT_SYMBOL(interval_is_overlapped);
700
701 /* Don't expand to low. Expanding downwards is expensive, and meaningless to
702  * some extents, because programs seldom do IO backward.
703  *
704  * The recursive algorithm of expanding low:
705  * expand_low {
706  *        struct interval_node *tmp;
707  *        static __u64 res = 0;
708  *
709  *        if (root == NULL)
710  *                return res;
711  *        if (root->in_max_high < low) {
712  *                res = max_u64(root->in_max_high + 1, res);
713  *                return res;
714  *        } else if (low < interval_low(root)) {
715  *                interval_expand_low(root->in_left, low);
716  *                return res;
717  *        }
718  *
719  *        if (interval_high(root) < low)
720  *                res = max_u64(interval_high(root) + 1, res);
721  *        interval_expand_low(root->in_left, low);
722  *        interval_expand_low(root->in_right, low);
723  *
724  *        return res;
725  * }
726  *
727  * It's much easy to eliminate the recursion, see interval_search for 
728  * an example. -jay
729  */
730 static inline __u64 interval_expand_low(struct interval_node *root, __u64 low)
731 {
732         /* we only concern the empty tree right now. */
733         if (root == NULL)
734                 return 0;
735         return low;
736 }
737
738 static inline __u64 interval_expand_high(struct interval_node *node, __u64 high)
739 {
740         __u64 result = ~0;
741
742         while (node != NULL) {
743                 if (node->in_max_high < high)
744                         break;
745                         
746                 if (interval_low(node) > high) {
747                         result = interval_low(node) - 1;
748                         node = node->in_left;
749                 } else {
750                         node = node->in_right;
751                 }
752         }
753
754         return result;
755 }
756
757 /* expanding the extent based on @ext. */
758 void interval_expand(struct interval_node *root,
759                      struct interval_node_extent *ext,
760                      struct interval_node_extent *limiter)
761 {
762         /* The assertion of interval_is_overlapped is expensive because we may
763          * travel many nodes to find the overlapped node. */
764         LASSERT(interval_is_overlapped(root, ext) == 0);
765         if (!limiter || limiter->start < ext->start)
766                 ext->start = interval_expand_low(root, ext->start);
767         if (!limiter || limiter->end > ext->end)
768                 ext->end = interval_expand_high(root, ext->end);
769         LASSERT(interval_is_overlapped(root, ext) == 0);
770 }
771 EXPORT_SYMBOL(interval_expand);