diff --git a/include/spdk/bit_array.h b/include/spdk/bit_array.h index a69047ff7c..37279dfc5f 100644 --- a/include/spdk/bit_array.h +++ b/include/spdk/bit_array.h @@ -151,9 +151,7 @@ uint32_t spdk_bit_array_find_first_set(const struct spdk_bit_array *ba, uint32_t * \param start_bit_index The bit index from which to start searching (0 to start * from the beginning of the array). * - * \return the index of the first cleared bit. Bits beyond the current size of - * the array are implicitly cleared, so if all bits within the current size are - * set, this function will return the current number of bits + 1. + * \return the index of the first cleared bit. If no bits are cleared, returns UINT32_MAX. */ uint32_t spdk_bit_array_find_first_clear(const struct spdk_bit_array *ba, uint32_t start_bit_index); diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 1c45b88ac5..3b29418026 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -109,7 +109,7 @@ _spdk_bs_allocate_cluster(struct spdk_blob *blob, uint32_t cluster_num, pthread_mutex_lock(&blob->bs->used_clusters_mutex); *lowest_free_cluster = spdk_bit_array_find_first_clear(blob->bs->used_clusters, *lowest_free_cluster); - if (*lowest_free_cluster >= blob->bs->total_clusters) { + if (*lowest_free_cluster == UINT32_MAX) { /* No more free clusters. Cannot satisfy the request */ pthread_mutex_unlock(&blob->bs->used_clusters_mutex); return -ENOSPC; @@ -1338,7 +1338,7 @@ _spdk_blob_resize(struct spdk_blob *blob, uint64_t sz) lfc = 0; for (i = num_clusters; i < sz; i++) { lfc = spdk_bit_array_find_first_clear(bs->used_clusters, lfc); - if (lfc >= bs->total_clusters) { + if (lfc == UINT32_MAX) { /* No more free clusters. Cannot satisfy the request */ return -ENOSPC; } @@ -1421,7 +1421,7 @@ _spdk_blob_persist_start(struct spdk_blob_persist_ctx *ctx) /* Note that this loop starts at one. The first page location is fixed by the blobid. */ for (i = 1; i < blob->active.num_pages; i++) { page_num = spdk_bit_array_find_first_clear(bs->used_md_pages, page_num); - if (page_num >= spdk_bit_array_capacity(bs->used_md_pages)) { + if (page_num == UINT32_MAX) { _spdk_blob_persist_complete(seq, ctx, -ENOMEM); return; } @@ -4106,7 +4106,7 @@ _spdk_bs_create_blob(struct spdk_blob_store *bs, assert(spdk_get_thread() == bs->md_thread); page_idx = spdk_bit_array_find_first_clear(bs->used_md_pages, 0); - if (page_idx >= spdk_bit_array_capacity(bs->used_md_pages)) { + if (page_idx == UINT32_MAX) { cb_fn(cb_arg, 0, -ENOMEM); return; } @@ -4780,7 +4780,7 @@ _spdk_bs_inflate_blob_open_cpl(void *cb_arg, struct spdk_blob *_blob, int bserrn for (i = 0; i < _blob->active.num_clusters; i++) { if (_spdk_bs_cluster_needs_allocation(_blob, i, ctx->allocate_all)) { lfc = spdk_bit_array_find_first_clear(_blob->bs->used_clusters, lfc); - if (lfc >= _blob->bs->total_clusters) { + if (lfc == UINT32_MAX) { /* No more free clusters. Cannot satisfy the request */ _spdk_bs_clone_snapshot_origblob_cleanup(ctx, -ENOSPC); return; diff --git a/lib/util/bit_array.c b/lib/util/bit_array.c index 394b84bbb0..d6c112f79e 100644 --- a/lib/util/bit_array.c +++ b/lib/util/bit_array.c @@ -97,7 +97,11 @@ spdk_bit_array_resize(struct spdk_bit_array **bap, uint32_t num_bits) uint32_t old_word_count, new_word_count; size_t new_size; - if (!bap) { + /* + * Max number of bits allowed is UINT32_MAX - 1, because we use UINT32_MAX to denote + * when a set or cleared bit cannot be found. + */ + if (!bap || num_bits == UINT32_MAX) { return -EINVAL; } @@ -269,7 +273,19 @@ spdk_bit_array_find_first_set(const struct spdk_bit_array *ba, uint32_t start_bi uint32_t spdk_bit_array_find_first_clear(const struct spdk_bit_array *ba, uint32_t start_bit_index) { - return _spdk_bit_array_find_first(ba, start_bit_index, SPDK_BIT_ARRAY_WORD_C(-1)); + uint32_t bit_index; + + bit_index = _spdk_bit_array_find_first(ba, start_bit_index, SPDK_BIT_ARRAY_WORD_C(-1)); + + /* + * If we ran off the end of the array and found the 0 bit in the extra word, + * return UINT32_MAX to indicate no actual 0 bits were found. + */ + if (bit_index >= ba->bit_count) { + bit_index = UINT32_MAX; + } + + return bit_index; } uint32_t diff --git a/test/unit/lib/util/bit_array.c/bit_array_ut.c b/test/unit/lib/util/bit_array.c/bit_array_ut.c index 682ce37498..18d84b948b 100644 --- a/test/unit/lib/util/bit_array.c/bit_array_ut.c +++ b/test/unit/lib/util/bit_array.c/bit_array_ut.c @@ -133,10 +133,10 @@ test_find(void) /* Verify that find_first_set and find_first_clear work for each starting position */ for (i = 0; i < 256; i++) { CU_ASSERT(spdk_bit_array_find_first_set(ba, i) == i); - CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == 256); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == UINT32_MAX); } CU_ASSERT(spdk_bit_array_find_first_set(ba, 256) == UINT32_MAX); - CU_ASSERT(spdk_bit_array_find_first_clear(ba, 256) == 256); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, 256) == UINT32_MAX); /* Clear bits 0 through 31 */ for (i = 0; i < 32; i++) { @@ -150,7 +150,7 @@ test_find(void) for (i = 32; i < 256; i++) { CU_ASSERT(spdk_bit_array_find_first_set(ba, i) == i); - CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == 256); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == UINT32_MAX); } /* Clear bit 255 */ @@ -166,7 +166,7 @@ test_find(void) CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == 255); } - CU_ASSERT(spdk_bit_array_find_first_clear(ba, 256) == 256); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, 256) == UINT32_MAX); spdk_bit_array_free(&ba); }