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