From 3ae0b6ec643cf25a0b1421440696d32c77d184ed Mon Sep 17 00:00:00 2001 From: Tiago Castro Date: Tue, 12 Dec 2023 19:40:21 +0000 Subject: [PATCH] blobstore: export allocated cluster bitmap for a blob Signed-off-by: Tiago Castro --- include/spdk/bit_array.h | 6 +++++- include/spdk/blob.h | 25 +++++++++++++++++++++++++ lib/blob/blobstore.c | 32 +++++++++++++++++++++++++++++++- lib/util/bit_array.c | 28 ++++++++++++++++++++++------ 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/include/spdk/bit_array.h b/include/spdk/bit_array.h index b0fed89b041..08942f50a31 100644 --- a/include/spdk/bit_array.h +++ b/include/spdk/bit_array.h @@ -16,10 +16,14 @@ extern "C" { #endif +typedef uint64_t spdk_bit_array_word; /** * Variable-length bit array. */ -struct spdk_bit_array; +struct spdk_bit_array { + uint32_t bit_count; + spdk_bit_array_word words[]; +}; /** * Return the number of bits that a bit array is currently sized to hold. diff --git a/include/spdk/blob.h b/include/spdk/blob.h index ef321131c31..af6f1ea09ea 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -35,6 +35,7 @@ #include "spdk/stdinc.h" #include "spdk/assert.h" +#include "spdk/bit_array.h" #ifdef __cplusplus extern "C" { @@ -1180,6 +1181,30 @@ bool spdk_blob_is_degraded(const struct spdk_blob *blob); */ void spdk_blob_reset_used_clusters_cache(struct spdk_blob *blob); +/** + * Blob get cluster bitmap completion callback. + * + * \param cb_arg Callback argument. + * \param bserrno 0 if it completed successfully, or negative errno if it failed. + * \param bitmap NULL if no memory available, otherwise a bitmap where each bit corresponds + * to a cluster. A set bit indicates the cluster is owned by the blob. + */ +typedef void (*spdk_blob_cluster_bitmap_complete)(void *cb_arg, int bserrno, + struct spdk_bit_array *bitmap); + +/** + * Get the allocated cluster bitmap of the given blob. + * + * \param blob Blob to retrieve allocated bitmap from. + * \param cb_fn Called when the operation is complete. + * \param cb_arg Custom cb_arg passed to function cb_fn. + * + * \return 0 if callback was called, or negative errno otherwise. + */ +int +spdk_blob_get_cluster_bitmap(struct spdk_blob *blob, spdk_blob_cluster_bitmap_complete cb_fn, + void *cb_arg); + #ifdef __cplusplus } #endif diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 46145de7bbc..127f516bbf4 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -11,7 +11,6 @@ #include "spdk/env.h" #include "spdk/queue.h" #include "spdk/thread.h" -#include "spdk/bit_array.h" #include "spdk/bit_pool.h" #include "spdk/likely.h" #include "spdk/util.h" @@ -5985,6 +5984,37 @@ spdk_blob_reset_used_clusters_cache(struct spdk_blob *blob) spdk_spin_unlock(&blob->bs->used_lock); } } + +int +spdk_blob_get_cluster_bitmap(struct spdk_blob *blob, spdk_blob_cluster_bitmap_complete cb_fn, + void *cb_arg) +{ + struct spdk_bit_array *allocated_bitmap; + uint64_t i; + + /* Only snapshots are supported at the moment. */ + if (!blob->data_ro || !blob->md_ro) { + return -EPERM; + } + + allocated_bitmap = spdk_bit_array_create(blob->active.num_clusters); + if (allocated_bitmap == NULL) { + SPDK_ERRLOG("Failed to allocate bit array memory for blob #%ld", blob->id); + return -ENOMEM; + } + + for (i = 0; i < blob->active.num_clusters; i++) { + if (blob->active.clusters[i]) { + spdk_bit_array_set(allocated_bitmap, i); + } + } + + cb_fn(cb_arg, 0, allocated_bitmap); + spdk_bit_array_free(&allocated_bitmap); + + return 0; +} + /* START spdk_bs_create_blob */ static void diff --git a/lib/util/bit_array.c b/lib/util/bit_array.c index ec182492fe2..82b287fada4 100644 --- a/lib/util/bit_array.c +++ b/lib/util/bit_array.c @@ -12,7 +12,6 @@ #include "spdk/likely.h" #include "spdk/util.h" -typedef uint64_t spdk_bit_array_word; #define SPDK_BIT_ARRAY_WORD_TZCNT(x) (__builtin_ctzll(x)) #define SPDK_BIT_ARRAY_WORD_POPCNT(x) (__builtin_popcountll(x)) #define SPDK_BIT_ARRAY_WORD_C(x) ((spdk_bit_array_word)(x)) @@ -21,11 +20,6 @@ typedef uint64_t spdk_bit_array_word; #define SPDK_BIT_ARRAY_WORD_INDEX_SHIFT spdk_u32log2(SPDK_BIT_ARRAY_WORD_BITS) #define SPDK_BIT_ARRAY_WORD_INDEX_MASK ((1u << SPDK_BIT_ARRAY_WORD_INDEX_SHIFT) - 1) -struct spdk_bit_array { - uint32_t bit_count; - spdk_bit_array_word words[]; -}; - struct spdk_bit_array * spdk_bit_array_create(uint32_t num_bits) { @@ -335,6 +329,28 @@ spdk_bit_array_clear_mask(struct spdk_bit_array *ba) } } +void +spdk_bit_array_print(struct spdk_bit_array *ba) +{ + uint32_t i; + uint32_t num_bits = spdk_bit_array_capacity(ba); + + printf("bit_count: %d\n", ba->bit_count); + printf("num_bits: %d\n", num_bits); + printf("num_bits: %d\n", num_bits % CHAR_BIT); + + printf("SPDK_BIT_ARRAY_WORD_BYTES: %ld\n", SPDK_BIT_ARRAY_WORD_BYTES); + printf("SPDK_BIT_ARRAY_WORD_BITS: %ld\n", SPDK_BIT_ARRAY_WORD_BITS); + printf("SPDK_BIT_ARRAY_WORD_INDEX_SHIFT: %d\n", SPDK_BIT_ARRAY_WORD_INDEX_SHIFT); + printf("SPDK_BIT_ARRAY_WORD_INDEX_MASK: %d\n", SPDK_BIT_ARRAY_WORD_INDEX_MASK); + + for (i = 0; i < num_bits; i++) { + if (spdk_bit_array_get(ba, i)) { + printf("i: %d, set: 1\n", i); + } + } +} + struct spdk_bit_pool { struct spdk_bit_array *array; uint32_t lowest_free_bit;