X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=libfrog%2Fbitmap.c;h=5af5ab8dd6b3bb853d2ff3e8bdfadff4fb8a850f;hb=93d69bc79314f7c3f1404123355056f9ed2068a2;hp=be95965fcbe4b8d82240549018c273a5acbdb45f;hpb=233fabee02b632b783aed9ad981908a2fab14cfa;p=thirdparty%2Fxfsprogs-dev.git diff --git a/libfrog/bitmap.c b/libfrog/bitmap.c index be95965fc..5af5ab8dd 100644 --- a/libfrog/bitmap.c +++ b/libfrog/bitmap.c @@ -72,21 +72,30 @@ bitmap_alloc( 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. */ @@ -140,12 +149,12 @@ __bitmap_insert( 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; @@ -226,7 +235,7 @@ bitmap_set( #if 0 /* Unused, provided for completeness. */ /* Clear a region of bits. */ -bool +int bitmap_clear( struct bitmap *bmap, uint64_t start, @@ -250,7 +259,7 @@ bitmap_clear( /* Nothing, we're done. */ if (firstn == NULL && lastn == NULL) { pthread_mutex_unlock(&bmap->bt_lock); - return true; + return 0; } assert(firstn != NULL && lastn != NULL); @@ -288,24 +297,26 @@ bitmap_clear( 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( @@ -328,7 +339,43 @@ 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