struct bitmap **bmapp)
{
struct bitmap *bmap;
+ int ret;
bmap = calloc(1, sizeof(struct bitmap));
if (!bmap)
- return errno;
+ return -errno;
bmap->bt_tree = malloc(sizeof(struct avl64tree_desc));
if (!bmap->bt_tree) {
- free(bmap);
- return errno;
+ ret = -errno;
+ goto out;
}
- pthread_mutex_init(&bmap->bt_lock, NULL);
+ ret = -pthread_mutex_init(&bmap->bt_lock, NULL);
+ if (ret)
+ goto out_tree;
+
avl64_init_tree(bmap->bt_tree, &bitmap_ops);
*bmapp = bmap;
return 0;
+out_tree:
+ free(bmap->bt_tree);
+out:
+ free(bmap);
+ return ret;
}
/* Free a bitmap. */
ext = bitmap_node_init(start, length);
if (!ext)
- return errno;
+ return -errno;
node = avl64_insert(bmap->bt_tree, &ext->btn_node);
if (node == NULL) {
free(ext);
- return EEXIST;
+ return -EEXIST;
}
return 0;
#if 0 /* Unused, provided for completeness. */
/* Clear a region of bits. */
-bool
+int
bitmap_clear(
struct bitmap *bmap,
uint64_t start,
/* Nothing, we're done. */
if (firstn == NULL && lastn == NULL) {
pthread_mutex_unlock(&bmap->bt_lock);
- return true;
+ return 0;
}
assert(firstn != NULL && lastn != NULL);
new_start;
ext = bitmap_node_init(new_start, new_length);
- if (!ext)
- return false;
+ if (!ext) {
+ ret = -errno;
+ goto out;
+ }
node = avl64_insert(bmap->bt_tree, &ext->btn_node);
if (node == NULL) {
- errno = EEXIST;
- return false;
+ ret = -EEXIST;
+ goto out;
}
break;
}
}
+out:
pthread_mutex_unlock(&bmap->bt_lock);
- return true;
+ return ret;
}
#endif
-#ifdef DEBUG
/* Iterate the set regions of this bitmap. */
int
bitmap_iterate(
return error;
}
-#endif
+
+/* Iterate the set regions of part of this bitmap. */
+int
+bitmap_iterate_range(
+ struct bitmap *bmap,
+ uint64_t start,
+ uint64_t length,
+ int (*fn)(uint64_t, uint64_t, void *),
+ void *arg)
+{
+ struct avl64node *firstn;
+ struct avl64node *lastn;
+ struct avl64node *pos;
+ struct avl64node *n;
+ struct avl64node *l;
+ struct bitmap_node *ext;
+ int ret = 0;
+
+ pthread_mutex_lock(&bmap->bt_lock);
+
+ avl64_findranges(bmap->bt_tree, start, start + length, &firstn,
+ &lastn);
+
+ if (firstn == NULL && lastn == NULL)
+ goto out;
+
+ avl_for_each_range_safe(pos, n, l, firstn, lastn) {
+ ext = container_of(pos, struct bitmap_node, btn_node);
+ ret = fn(ext->btn_start, ext->btn_length, arg);
+ if (ret)
+ break;
+ }
+
+out:
+ pthread_mutex_unlock(&bmap->bt_lock);
+ return ret;
+}
/* Do any bitmap extents overlap the given one? (locked) */
static bool