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:
parent
b70e698465
commit
9e2eb8cb51
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user