From 63e257ed34819a4a6b87f0cf4092517c7a8e5d9d Mon Sep 17 00:00:00 2001 From: Tomasz Zawadzki Date: Fri, 2 Oct 2020 05:01:25 -0400 Subject: [PATCH] lib/blob: update pages array during blob load When loading a blob and parsing its metadata, the array of pages was not updated. Serialization was unaffected, since the current pages array is unused there. Behavior was working correctly for first page, but did not for any blob with more than one page. Unfortunetly blob_persist_zero_pages() never zeroed out the pages, neither blob_persist_zero_pages_cpl() released the md pages. Resulting in md pages being claimed even after blobs deletion. This patch now fills out the active pages array with the appropriate page numbers from metadata. Signed-off-by: Tomasz Zawadzki Change-Id: I6ff1f4fe95684119d283c2471fdbbea464da8151 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4504 Tested-by: SPDK CI Jenkins Community-CI: Mellanox Build Bot Reviewed-by: Ben Walker Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- lib/blob/blobstore.c | 15 ++++++++++++++ test/unit/lib/blob/blob.c/blob_ut.c | 32 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 0afd4919d..9c063fc1b 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -766,6 +766,7 @@ blob_parse(const struct spdk_blob_md_page *pages, uint32_t page_count, const struct spdk_blob_md_page *page; uint32_t i; int rc; + void *tmp; assert(page_count > 0); assert(pages[0].sequence_num == 0); @@ -782,6 +783,20 @@ blob_parse(const struct spdk_blob_md_page *pages, uint32_t page_count, return -ENOENT; } + tmp = realloc(blob->active.pages, page_count * sizeof(*blob->active.pages)); + if (!tmp) { + return -ENOMEM; + } + blob->active.pages = tmp; + + blob->active.pages[0] = pages[0].id; + + for (i = 1; i < page_count; i++) { + assert(spdk_bit_array_get(blob->bs->used_md_pages, pages[i - 1].next)); + blob->active.pages[i] = pages[i - 1].next; + } + blob->active.num_pages = page_count; + for (i = 0; i < page_count; i++) { page = &pages[i]; diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 21a39543c..dfcf2a3c2 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -2115,6 +2115,37 @@ blob_xattr(void) CU_ASSERT((blob->invalid_flags & SPDK_BLOB_INTERNAL_XATTR) == 0); } +static void +blob_parse_md(void) +{ + struct spdk_blob_store *bs = g_bs; + struct spdk_blob *blob; + int rc; + uint32_t used_pages; + size_t xattr_length; + char *xattr; + + used_pages = spdk_bit_array_count_set(bs->used_md_pages); + blob = ut_blob_create_and_open(bs, NULL); + + /* Create large extent to force more than 1 page of metadata. */ + xattr_length = SPDK_BS_MAX_DESC_SIZE - sizeof(struct spdk_blob_md_descriptor_xattr) - + strlen("large_xattr"); + xattr = calloc(xattr_length, sizeof(char)); + SPDK_CU_ASSERT_FATAL(xattr != NULL); + rc = spdk_blob_set_xattr(blob, "large_xattr", xattr, xattr_length); + free(xattr); + SPDK_CU_ASSERT_FATAL(rc == 0); + + spdk_blob_sync_md(blob, blob_op_complete, NULL); + poll_threads(); + + /* Delete the blob and verify that number of pages returned to before its creation. */ + SPDK_CU_ASSERT_FATAL(used_pages != spdk_bit_array_count_set(bs->used_md_pages)); + ut_blob_close_and_delete(bs, blob); + SPDK_CU_ASSERT_FATAL(used_pages == spdk_bit_array_count_set(bs->used_md_pages)); +} + static void bs_load(void) { @@ -6699,6 +6730,7 @@ int main(int argc, char **argv) CU_ADD_TEST(suite_bs, blob_unmap); CU_ADD_TEST(suite_bs, blob_iter); CU_ADD_TEST(suite_blob, blob_xattr); + CU_ADD_TEST(suite_bs, blob_parse_md); CU_ADD_TEST(suite, bs_load); CU_ADD_TEST(suite_bs, bs_load_pending_removal); CU_ADD_TEST(suite, bs_load_custom_cluster_size);