diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 38694e1aa..3989b7d4f 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -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,