}
if (unlikely(ma_is_leaf(type))) {
+ mas->offset = offset;
mas->min = min;
mas->max = min + gap - 1;
return true;
{
enum maple_type type = mte_node_type(mas->node);
unsigned long pivot, min, gap = 0;
- unsigned char count, offset = 0;
+ unsigned char count, offset;
unsigned long *gaps = NULL, *pivots = ma_pivots(mas_mn(mas), type);
void **slots = ma_slots(mas_mn(mas), type);
bool found = false;
return true;
}
- if (!ma_is_leaf(type)) {
- offset = mas->offset;
+ if (!ma_is_leaf(type))
gaps = ma_gaps(mte_to_node(mas->node), type);
- }
+ offset = mas->offset;
count = mt_slots[type];
min = mas_safe_min(mas, pivots, offset);
for (; offset < count; offset++) {
do {
if (mte_is_root(mas->node)) {
slot = mas->offset;
- if (!slot) {
- mas_set_err(mas, -EBUSY);
+ if (!slot)
return false;
- }
} else {
slot = mte_parent_slot(mas->node);
mas_ascend(mas);
return true;
}
-/*
- * mas_rev_awalk() - Reverse allocation walk for a given size.
- * @mas: The maple state
- * @size: The size of the gap
- *
- * Reverse search from @mas->last to @mas->index for a gap of @size.
- *
- * Return: true if found, false otherwise.
- */
-static bool mas_rev_awalk(struct ma_state *mas, unsigned long size)
-{
- struct maple_enode *last = NULL;
-
- mas->offset = mas_data_end(mas);
-
- /* There are 4 options:
- * go to child (descend)
- * go back to parent (ascend)
- * no gap found. (return, slot == MAPLE_NODE_SLOTS)
- * found the gap. (return, slot != MAPLE_NODE_SLOTS)
- */
- while (!_mas_rev_awalk(mas, size)) {
- if (last == mas->node) {
- if (!mas_rewind_node(mas))
- return false;
- } else {
- last = mas->node;
- }
- }
- return true;
-}
-
/*
* mas_skip_node() - Internal function. Skip over a node.
* @mas: The maple state.
{
struct maple_enode *last = NULL;
- mas_start(mas);
- if (mas_is_none(mas))
- return;
-
- if (mas_is_ptr(mas))
- return;
-
/* There are 4 options:
* go to child (descend)
* go back to parent (ascend)
unsigned char offset;
unsigned long *pivots;
enum maple_type mt;
- mas_start(mas);
+
+ if (mas_is_start(mas)) {
+ mas_start(mas);
+ } else if (mas->offset >= 2) {
+ mas->offset -= 2;
+ } else if (!mas_skip_node(mas)) {
+ return -EBUSY;
+ }
// Empty set.
if (mas_is_none(mas) || mas_is_ptr(mas)) {
int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
unsigned long max, unsigned long size)
{
- mas_start(mas);
+ struct maple_enode *last = mas->node;
+
+ if (mas_is_start(mas)) {
+ mas_start(mas);
+ mas->offset = mas_data_end(mas);
+ } else if (mas->offset >= 2) {
+ mas->offset -= 2;
+ } else if (!mas_rewind_node(mas)) {
+ return -EBUSY;
+ }
// Empty set.
if (mas_is_none(mas) || mas_is_ptr(mas)) {
// The start of the window can only be within these values.
mas->index = min;
mas->last = max;
- if (unlikely(!mas_rev_awalk(mas, size)))
- return xa_err(mas->node);
+
+ while (!_mas_rev_awalk(mas, size)) {
+ if (last == mas->node) {
+ if (!mas_rewind_node(mas))
+ return -EBUSY;
+ } else {
+ last = mas->node;
+ }
+ }
if (unlikely(mas->offset == MAPLE_NODE_SLOTS))
return -EBUSY;