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: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I780819fd7f3c44e4cf5d71c188c642536d3cc320
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/479851
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
Tomasz Zawadzki 2020-01-21 07:27:24 -05:00
parent 2bccb7c9b4
commit d1f863ca57

View File

@ -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,