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 <cunyin.chang@intel.com>
Reviewed-on: https://review.gerrithub.io/377901
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Cunyin Chang 2017-09-11 16:52:49 +08:00 committed by Jim Harris
parent 2d18887fbd
commit 13ecee44a4
2 changed files with 93 additions and 2 deletions

View File

@ -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);

View File

@ -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();