Commit 13ecee44 authored by Cunyin Chang's avatar Cunyin Chang Committed by Jim Harris
Browse files

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: default avatarCunyin Chang <cunyin.chang@intel.com>
Reviewed-on: https://review.gerrithub.io/377901


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 2d18887f
Loading
Loading
Loading
Loading
+41 −1
Original line number Diff line number Diff line
@@ -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);
+52 −1
Original line number Diff line number Diff line
@@ -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();