Commit d1f863ca authored by Tomasz Zawadzki's avatar Tomasz Zawadzki
Browse files

lib/blob: write out extent pages before persisting metadata



Add new serialization of changed extent pages before persisting md.

Iterate over active extent pages (not array !). When they are
allocated but not yet present on disk - write them out.
All extent pages in clean mutable data are assumed to be written out
already.

So there are two cases here:
1) Active mutable array is larger than clean
	All allocated extent pages should be written out.
2) Cluster allocation created new extent page
	Blob has to be thin provisioned and persist was called
	as part of cluster allocation. New extent page needs to be
	written out and EXTENT_TABLE allocated.

Iteration is done over num_extent_pages instead of extent_pages_array_size,
to prevent writting out too many extent pages when size of blob was
made smaller. The two values come back in sync at the end of persist
either way.

Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I780819fd7f3c44e4cf5d71c188c642536d3cc320
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/479851


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
parent 2bccb7c9
Loading
Loading
Loading
Loading
+66 −1
Original line number Diff line number Diff line
@@ -1395,6 +1395,8 @@ struct spdk_blob_persist_ctx {
	struct spdk_bs_super_block	*super;

	struct spdk_blob_md_page	*pages;
	uint32_t			next_extent_page;
	struct spdk_blob_md_page	*extent_page;

	spdk_bs_sequence_t		*seq;
	spdk_bs_sequence_cpl		cb_fn;
@@ -1827,6 +1829,68 @@ _spdk_blob_persist_generate_new_md(struct spdk_blob_persist_ctx *ctx)
	_spdk_blob_persist_write_page_chain(seq, ctx, 0);
}

static void _spdk_blob_persist_write_extent_pages(spdk_bs_sequence_t *seq, void *cb_arg,
		int bserrno);

static void
_spdk_blob_persist_write_extent_page(uint32_t extent, uint64_t cluster_num,
				     struct spdk_blob_persist_ctx *ctx)
{
	spdk_bs_sequence_t		*seq = ctx->seq;
	uint32_t                        page_count = 0;
	struct spdk_blob		*blob = ctx->blob;
	int				rc;

	rc = _spdk_blob_serialize_add_page(blob, &ctx->extent_page, &page_count, &ctx->extent_page);
	if (rc < 0) {
		assert(false);
		return;
	}

	_spdk_blob_serialize_extent_page(blob, cluster_num, ctx->extent_page);

	ctx->extent_page->crc = _spdk_blob_md_page_calc_crc(ctx->extent_page);

	spdk_bs_sequence_write_dev(seq, ctx->extent_page, _spdk_bs_md_page_to_lba(blob->bs, extent),
				   _spdk_bs_byte_to_lba(blob->bs, SPDK_BS_PAGE_SIZE),
				   _spdk_blob_persist_write_extent_pages, ctx);
}

static void
_spdk_blob_persist_write_extent_pages(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
{
	struct spdk_blob_persist_ctx	*ctx = cb_arg;
	struct spdk_blob		*blob = ctx->blob;
	size_t				i;
	uint32_t			extent_page_id;

	if (ctx->extent_page != NULL) {
		spdk_free(ctx->extent_page);
		ctx->extent_page = NULL;
	}

	/* Only write out changed extent pages */
	for (i = ctx->next_extent_page; i < blob->active.num_extent_pages; i++) {
		extent_page_id = blob->active.extent_pages[i];
		if (extent_page_id == 0) {
			/* No Extent Page to persist */
			assert(spdk_blob_is_thin_provisioned(blob));
			continue;
		}
		/* Writing out new extent page for the first time. Either active extent pages is larger
		 * than clean extent pages or there was no extent page assigned due to thin provisioning. */
		if (i >= blob->clean.extent_pages_array_size || blob->clean.extent_pages[i] == 0) {
			assert(spdk_bit_array_get(blob->bs->used_md_pages, extent_page_id));
			ctx->next_extent_page = i + 1;
			_spdk_blob_persist_write_extent_page(extent_page_id, i * SPDK_EXTENTS_PER_EP, ctx);
			return;
		}
		assert(blob->clean.extent_pages[i] != 0);
	}

	_spdk_blob_persist_generate_new_md(ctx);
}

static void
_spdk_blob_persist_start(struct spdk_blob_persist_ctx *ctx)
{
@@ -1843,7 +1907,7 @@ _spdk_blob_persist_start(struct spdk_blob_persist_ctx *ctx)

	}

	_spdk_blob_persist_generate_new_md(ctx);
	_spdk_blob_persist_write_extent_pages(seq, ctx, 0);
}

static void
@@ -1900,6 +1964,7 @@ _spdk_blob_persist(spdk_bs_sequence_t *seq, struct spdk_blob *blob,
	ctx->seq = seq;
	ctx->cb_fn = cb_fn;
	ctx->cb_arg = cb_arg;
	ctx->next_extent_page = 0;

	if (blob->bs->clean) {
		ctx->super = spdk_zmalloc(sizeof(*ctx->super), 0x1000, NULL,