static u64 compute_subtree_max_end(struct memtype *data) { u64 max_end = data->end, child_max_end; child_max_end = get_subtree_max_end(data->rb.rb_right); if (child_max_end > max_end) max_end = child_max_end; child_max_end = get_subtree_max_end(data->rb.rb_left); if (child_max_end > max_end) max_end = child_max_end; return max_end; }
/* Update 'subtree_max_end' for a node, based on node and its children */ static void memtype_rb_augment_cb(struct rb_node *node, void *__unused) { struct memtype *data; u64 max_end, child_max_end; if (!node) return; data = container_of(node, struct memtype, rb); max_end = data->end; child_max_end = get_subtree_max_end(node->rb_right); if (child_max_end > max_end) max_end = child_max_end; child_max_end = get_subtree_max_end(node->rb_left); if (child_max_end > max_end) max_end = child_max_end; data->subtree_max_end = max_end; }
/* Update 'subtree_max_end' for a node, based on node and its children */ static void update_node_max_end(struct rb_node *node) { struct memtype *data; u64 max_end, child_max_end; if (!node) return; data = container_of(node, struct memtype, rb); max_end = data->end; child_max_end = get_subtree_max_end(node->rb_right); if (child_max_end > max_end) max_end = child_max_end; child_max_end = get_subtree_max_end(node->rb_left); if (child_max_end > max_end) max_end = child_max_end; data->subtree_max_end = max_end; }
/* Find the first (lowest start addr) overlapping range from rb tree */ static struct memtype *memtype_rb_lowest_match(struct rb_root *root, u64 start, u64 end) { struct rb_node *node = root->rb_node; struct memtype *last_lower = NULL; while (node) { struct memtype *data = container_of(node, struct memtype, rb); if (get_subtree_max_end(node->rb_left) > start) { /* Lowest overlap if any must be on left side */ node = node->rb_left; } else if (is_node_overlap(data, start, end)) { last_lower = data; break; } else if (start >= data->start) { /* Lowest overlap if any must be on right side */ node = node->rb_right; } else { break; } } return last_lower; /* Returns NULL if there is no overlap */ }