void *mas_walk(struct ma_state *mas);
void *mas_store(struct ma_state *mas, void *entry);
+int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp);
void *mas_find(struct ma_state *mas, unsigned long max);
bool mas_nomem(struct ma_state *mas, gfp_t gfp);
if (!mas_searchable(mas))
return NULL;
+
if (mas_is_start(mas)) {
mas_start(mas);
- return mas_last_entry(mas, ULONG_MAX);
+ mas_walk(mas);
}
do {
*/
void *mas_store(struct ma_state *mas, void *entry)
{
- if (mas->index <= mas->last)
- return _mas_store(mas, entry, true);
+ void *existing = NULL;
+
+ if (mas->index > mas->last)
+ goto invalid_range;
+
+ existing = _mas_store(mas, entry, true);
+ if (mas_is_err(mas))
+ return existing;
+
+ if (!mte_is_leaf(mas->node)) // gaps were updated
+ mas->node = MAS_START;
+ return existing;
+
+invalid_range:
mas_set_err(mas, -EINVAL);
return NULL;
}
+int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp)
+{
+
+ // Detect spanning store.
+ if ((mas->last == mas->max && !entry) ||
+ (mas->last > mas->max))
+ mas->node = MAS_START;
+
+retry:
+ _mas_store(mas, entry, true);
+ if (mas_nomem(mas, gfp))
+ goto retry;
+
+ if (mas_is_err(mas))
+ return xa_err(mas->node);
+
+ if (!mte_is_leaf(mas->node)) // gaps were updated
+ mas->node = MAS_START;
+
+ return 0;
+
+}
+
/*
* mas_entry_count() - Set the expected number of entries that will be inserted.
*
unsigned char end;
unsigned long range_min, range_max;
+ if (mas_is_start(mas))
+ mas_start(mas);
+
__mas_walk(mas, &range_min, &range_max);
end = mas_data_end(mas) + 1;
if (end < mt_min_slot_count(mas->node) - 1) {