From 13ecee44a43d1aae51b8299e939aaf037b5a05ba Mon Sep 17 00:00:00 2001 From: Cunyin Chang Date: Mon, 11 Sep 2017 16:52:49 +0800 Subject: [PATCH] blob: Add support for crc of metadata pages. This patch add support crc for metadata pages, we will also add crc for supper block, used md and used clusters bitmask pages in the following patches. Change-Id: Ie36fcc16b39296d06721f1f8eb5689260194c558 Signed-off-by: Cunyin Chang Reviewed-on: https://review.gerrithub.io/377901 Reviewed-by: Jim Harris Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp --- lib/blob/blobstore.c | 42 ++++++++++++++++++++++- test/unit/lib/blob/blob.c/blob_ut.c | 53 ++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 91a040322..82c997f76 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -34,6 +34,7 @@ #include "spdk/stdinc.h" #include "spdk/blob.h" +#include "spdk/crc32.h" #include "spdk/env.h" #include "spdk/queue.h" #include "spdk/io_channel.h" @@ -45,6 +46,8 @@ #include "blobstore.h" #include "request.h" +#define BLOB_CRC32C_INITIAL 0xffffffffUL + static inline size_t divide_round_up(size_t num, size_t divisor) { @@ -518,6 +521,19 @@ struct spdk_blob_load_ctx { void *cb_arg; }; +static uint32_t +_spdk_blob_md_page_calc_crc(void *page) +{ + uint32_t crc; + + crc = BLOB_CRC32C_INITIAL; + crc = spdk_crc32c_update(page, SPDK_BS_PAGE_SIZE - 4, crc); + crc ^= BLOB_CRC32C_INITIAL; + + return crc; + +} + static void _spdk_blob_load_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) { @@ -525,8 +541,18 @@ _spdk_blob_load_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) struct spdk_blob *blob = ctx->blob; struct spdk_blob_md_page *page; int rc; + uint32_t crc; page = &ctx->pages[ctx->num_pages - 1]; + crc = _spdk_blob_md_page_calc_crc(page); + if (crc != page->crc) { + SPDK_ERRLOG("Metadata page %d crc mismatch\n", ctx->num_pages); + _spdk_blob_free(blob); + ctx->cb_fn(seq, NULL, -EINVAL); + spdk_dma_free(ctx->pages); + free(ctx); + return; + } if (page->next != SPDK_INVALID_MD_PAGE) { uint32_t next_page = page->next; @@ -1000,12 +1026,14 @@ _spdk_blob_persist(spdk_bs_sequence_t *seq, struct spdk_blob *blob, for (i = 1; i < blob->active.num_pages; i++) { page_num = spdk_bit_array_find_first_clear(bs->used_md_pages, page_num); ctx->pages[i - 1].next = page_num; + /* Now that previous metadata page is complete, calculate the crc for it. */ + ctx->pages[i - 1].crc = _spdk_blob_md_page_calc_crc(&ctx->pages[i - 1]); blob->active.pages[i] = page_num; spdk_bit_array_set(bs->used_md_pages, page_num); SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "Claiming page %u for blob %lu\n", page_num, blob->id); page_num++; } - + ctx->pages[i - 1].crc = _spdk_blob_md_page_calc_crc(&ctx->pages[i - 1]); /* Start writing the metadata from last page to first */ ctx->idx = blob->active.num_pages - 1; _spdk_blob_persist_write_page_chain(seq, ctx, 0); @@ -2111,6 +2139,11 @@ _spdk_bs_md_delete_open_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) { struct spdk_blob *blob = cb_arg; + /* If the blob have crc error, we just return NULL. */ + if (blob == NULL) { + spdk_bs_sequence_finish(seq, bserrno); + return; + } blob->state = SPDK_BLOB_STATE_DIRTY; blob->active.num_pages = 0; _spdk_resize_blob(blob, 0); @@ -2164,6 +2197,13 @@ _spdk_bs_md_open_blob_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) { struct spdk_blob *blob = cb_arg; + /* If the blob have crc error, we just return NULL. */ + if (blob == NULL) { + seq->cpl.u.blob_handle.blob = NULL; + spdk_bs_sequence_finish(seq, bserrno); + return; + } + blob->open_ref++; TAILQ_INSERT_HEAD(&blob->bs->blobs, blob, link); diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 22211554b..355b7a4a5 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -1184,6 +1184,56 @@ blob_serialize(void) g_bs = NULL; } +static void +blob_crc(void) +{ + struct spdk_blob_store *bs; + struct spdk_bs_dev *dev; + struct spdk_blob *blob; + spdk_blob_id blobid; + uint32_t page_num; + int index; + struct spdk_blob_md_page *page; + + dev = init_dev(); + + spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + bs = g_bs; + + spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); + blobid = g_blobid; + + spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(g_blob != NULL); + blob = g_blob; + + spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(blob == NULL); + + page_num = _spdk_bs_blobid_to_page(blobid); + index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num); + page = (struct spdk_blob_md_page *)&g_dev_buffer[index]; + page->crc = 0; + + spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == -EINVAL); + CU_ASSERT(g_blob == NULL); + g_bserrno = 0; + + spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == -EINVAL); + + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; @@ -1217,7 +1267,8 @@ int main(int argc, char **argv) CU_add_test(suite, "bs_unload_delayed", bs_unload_delayed) == NULL || CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL || CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL || - CU_add_test(suite, "blob_serialize", blob_serialize) == NULL + CU_add_test(suite, "blob_serialize", blob_serialize) == NULL || + CU_add_test(suite, "blob_crc", blob_crc) == NULL ) { CU_cleanup_registry(); return CU_get_error();