blobstore: Swap cluster maps on snapshot instead of copying

Previously, when creating a snapshot in blobstore the snapshot's cluster map
was copied from the "original" blob, with the original's map zeroed. These
operations are both O(num_clusters*cluster_size/page_size) while io
operations are frozen. This change replaces the linear operation with an
O(1) pointer swap at the critical moment that io is frozen, while
doing the zeroing before the freeze when preparing the snapshot to
minimize freeze time.

Change-Id: I1e468bc97623f5da161a8ddba1393c271acd3aed
Signed-off-by: Amir More <habeanf@gmail.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/451486
Reviewed-by: Maciej Szwed <maciej.szwed@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Amir More 2019-04-18 19:49:59 +03:00 committed by Jim Harris
parent b70e698465
commit 9e2eb8cb51

View File

@ -4344,13 +4344,25 @@ _spdk_bs_clone_snapshot_newblob_cleanup(void *cb_arg, int bserrno)
/* START spdk_bs_create_snapshot */
static void
_spdk_bs_snapshot_swap_cluster_maps(struct spdk_blob *blob1, struct spdk_blob *blob2)
{
uint64_t *cluster_temp;
cluster_temp = blob1->active.clusters;
blob1->active.clusters = blob2->active.clusters;
blob2->active.clusters = cluster_temp;
}
static void
_spdk_bs_snapshot_origblob_sync_cpl(void *cb_arg, int bserrno)
{
struct spdk_clone_snapshot_ctx *ctx = (struct spdk_clone_snapshot_ctx *)cb_arg;
struct spdk_blob *origblob = ctx->original.blob;
struct spdk_blob *newblob = ctx->new.blob;
if (bserrno != 0) {
_spdk_bs_snapshot_swap_cluster_maps(newblob, origblob);
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno);
return;
}
@ -4378,6 +4390,8 @@ _spdk_bs_snapshot_newblob_sync_cpl(void *cb_arg, int bserrno)
struct spdk_blob *newblob = ctx->new.blob;
if (bserrno != 0) {
/* return cluster map back to original */
_spdk_bs_snapshot_swap_cluster_maps(newblob, origblob);
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno);
return;
}
@ -4385,6 +4399,8 @@ _spdk_bs_snapshot_newblob_sync_cpl(void *cb_arg, int bserrno)
/* Set internal xattr for snapshot id */
bserrno = _spdk_blob_set_xattr(origblob, BLOB_SNAPSHOT, &newblob->id, sizeof(spdk_blob_id), true);
if (bserrno != 0) {
/* return cluster map back to original */
_spdk_bs_snapshot_swap_cluster_maps(newblob, origblob);
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno);
return;
}
@ -4395,6 +4411,8 @@ _spdk_bs_snapshot_newblob_sync_cpl(void *cb_arg, int bserrno)
/* Create new back_bs_dev for snapshot */
origblob->back_bs_dev = spdk_bs_create_blob_bs_dev(newblob);
if (origblob->back_bs_dev == NULL) {
/* return cluster map back to original */
_spdk_bs_snapshot_swap_cluster_maps(newblob, origblob);
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, -EINVAL);
return;
}
@ -4404,10 +4422,6 @@ _spdk_bs_snapshot_newblob_sync_cpl(void *cb_arg, int bserrno)
_spdk_bs_blob_list_add(newblob);
/* Zero out origblob cluster map */
memset(origblob->active.clusters, 0,
origblob->active.num_clusters * sizeof(origblob->active.clusters));
/* sync clone metadata */
spdk_blob_sync_md(origblob, _spdk_bs_snapshot_origblob_sync_cpl, ctx);
}
@ -4444,9 +4458,8 @@ _spdk_bs_snapshot_freeze_cpl(void *cb_arg, int rc)
}
}
/* Copy cluster map to snapshot */
memcpy(newblob->active.clusters, origblob->active.clusters,
origblob->active.num_clusters * sizeof(origblob->active.clusters));
/* swap cluster maps */
_spdk_bs_snapshot_swap_cluster_maps(newblob, origblob);
/* sync snapshot metadata */
spdk_blob_sync_md(newblob, _spdk_bs_snapshot_newblob_sync_cpl, ctx);
@ -4466,6 +4479,10 @@ _spdk_bs_snapshot_newblob_open_cpl(void *cb_arg, struct spdk_blob *_blob, int bs
ctx->new.blob = newblob;
/* Zero out newblob cluster map */
memset(newblob->active.clusters, 0,
newblob->active.num_clusters * sizeof(newblob->active.clusters));
_spdk_blob_freeze_io(origblob, _spdk_bs_snapshot_freeze_cpl, ctx);
}