lib/blob: update extent pages during snapshot deletion

When both clone and snapshot had already extent pages
corresponding to the same region in cluster map,
the clone extent page was replaced with one from snapshot.

This was incorrect and would result in loss of clusters
from clones extent page. It did not occur in practice
because all extent pages were rewritten anyway during
md sync. Cluster map was correct so updated extent pages
were too.

Cluster map correctness is verified in UT _blob_inflate_rw(true),
at the very end when checking data consistency of inflated blob.

This patch writes out the updated extent page explicitly.
So it would be possible to skip wirting out extent pages
during md sync later in the series.

Note 1)
At this point in series the extent page is written here,
and in blob persists. The later will be removed later in
series.

Note 2)
Errors during updating extent pages are not accounted for,
but neither does syncing them in blob persist.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I7deac3c64299f33f8df49e860af1a16295c074e6
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7438
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
This commit is contained in:
Tomasz Zawadzki 2021-04-15 07:37:20 -04:00
parent bc9da1c66c
commit a512214517

View File

@ -6346,6 +6346,7 @@ struct delete_snapshot_ctx {
spdk_blob_op_with_handle_complete cb_fn;
void *cb_arg;
int bserrno;
uint32_t next_extent_page;
};
static void
@ -6540,15 +6541,33 @@ delete_snapshot_update_extent_pages_cpl(struct delete_snapshot_ctx *ctx)
}
static void
delete_snapshot_update_extent_pages(struct delete_snapshot_ctx *ctx)
delete_snapshot_update_extent_pages(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
uint32_t *extent_page;
uint64_t i;
for (i = 0; i < ctx->snapshot->active.num_extent_pages &&
for (i = ctx->next_extent_page; i < ctx->snapshot->active.num_extent_pages &&
i < ctx->clone->active.num_extent_pages; i++) {
if (ctx->clone->active.extent_pages[i] == 0) {
ctx->clone->active.extent_pages[i] = ctx->snapshot->active.extent_pages[i];
if (ctx->snapshot->active.extent_pages[i] == 0) {
/* No extent page to use from snapshot */
continue;
}
extent_page = &ctx->clone->active.extent_pages[i];
if (*extent_page == 0) {
/* Copy extent page from snapshot when clone did not have a matching one */
*extent_page = ctx->snapshot->active.extent_pages[i];
continue;
}
/* Clone and snapshot both contain partialy filled matching extent pages.
* Update the clone extent page in place with cluster map containing the mix of both. */
ctx->next_extent_page = i + 1;
blob_write_extent_page(ctx->clone, *extent_page, i * SPDK_EXTENTS_PER_EP,
delete_snapshot_update_extent_pages, ctx);
return;
}
delete_snapshot_update_extent_pages_cpl(ctx);
}
@ -6576,7 +6595,8 @@ delete_snapshot_sync_snapshot_xattr_cpl(void *cb_arg, int bserrno)
ctx->clone->active.clusters[i] = ctx->snapshot->active.clusters[i];
}
}
delete_snapshot_update_extent_pages(ctx);
ctx->next_extent_page = 0;
delete_snapshot_update_extent_pages(ctx, 0);
}
static void