blobstore: fix parent for snapshot of clone

When snapshot is created from a clone, clones parent is not
inherited.

This patch also updates unit tests covering this case.

Change-Id: I42eb00fe2f33504c5b5c5beded20c4ea65eaff67
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
Reviewed-on: https://review.gerrithub.io/414804
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
Tomasz Kulasek 2018-06-12 10:59:44 +02:00 committed by Jim Harris
parent 9d04d0efd5
commit 826aac635e
2 changed files with 92 additions and 19 deletions

View File

@ -4303,6 +4303,8 @@ _spdk_bs_snapshot_newblob_sync_cpl(void *cb_arg, int bserrno)
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno); _spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno);
return; return;
} }
_spdk_bs_blob_list_remove(origblob);
origblob->parent_id = newblob->id; origblob->parent_id = newblob->id;
/* Create new back_bs_dev for snapshot */ /* Create new back_bs_dev for snapshot */
@ -4331,6 +4333,7 @@ _spdk_bs_snapshot_freeze_cpl(void *cb_arg, int rc)
struct spdk_clone_snapshot_ctx *ctx = (struct spdk_clone_snapshot_ctx *)cb_arg; struct spdk_clone_snapshot_ctx *ctx = (struct spdk_clone_snapshot_ctx *)cb_arg;
struct spdk_blob *origblob = ctx->original.blob; struct spdk_blob *origblob = ctx->original.blob;
struct spdk_blob *newblob = ctx->new.blob; struct spdk_blob *newblob = ctx->new.blob;
int bserrno;
if (rc != 0) { if (rc != 0) {
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, rc); _spdk_bs_clone_snapshot_newblob_cleanup(ctx, rc);
@ -4344,6 +4347,18 @@ _spdk_bs_snapshot_freeze_cpl(void *cb_arg, int rc)
/* Set invalid flags from origblob */ /* Set invalid flags from origblob */
newblob->invalid_flags = origblob->invalid_flags; newblob->invalid_flags = origblob->invalid_flags;
/* inherit parent from original blob if set */
newblob->parent_id = origblob->parent_id;
if (origblob->parent_id != SPDK_BLOBID_INVALID) {
/* Set internal xattr for snapshot id */
bserrno = _spdk_blob_set_xattr(newblob, BLOB_SNAPSHOT,
&origblob->parent_id, sizeof(spdk_blob_id), true);
if (bserrno != 0) {
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno);
return;
}
}
/* Copy cluster map to snapshot */ /* Copy cluster map to snapshot */
memcpy(newblob->active.clusters, origblob->active.clusters, memcpy(newblob->active.clusters, origblob->active.clusters,
origblob->active.num_clusters * sizeof(origblob->active.clusters)); origblob->active.num_clusters * sizeof(origblob->active.clusters));

View File

@ -4088,13 +4088,13 @@ blob_inflate_rw(void)
/** /**
* Snapshot-clones relation test * Snapshot-clones relation test
* *
* snapshot * snapshot
* | * |
* +----+----+ * +-----+-----+
* | | * | |
* blob clone * blob(ro) snapshot2
* | * | |
* clone2 * clone2 clone
*/ */
static void static void
blob_relations(void) blob_relations(void)
@ -4103,8 +4103,8 @@ blob_relations(void)
struct spdk_bs_dev *dev; struct spdk_bs_dev *dev;
struct spdk_bs_opts bs_opts; struct spdk_bs_opts bs_opts;
struct spdk_blob_opts opts; struct spdk_blob_opts opts;
struct spdk_blob *blob, *snapshot, *clone, *clone2; struct spdk_blob *blob, *snapshot, *snapshot2, *clone, *clone2;
spdk_blob_id blobid, cloneid, snapshotid, cloneid2; spdk_blob_id blobid, cloneid, snapshotid, cloneid2, snapshotid2;
int rc; int rc;
size_t count; size_t count;
spdk_blob_id ids[10]; spdk_blob_id ids[10];
@ -4139,6 +4139,7 @@ blob_relations(void)
CU_ASSERT(!spdk_blob_is_thin_provisioned(blob)); CU_ASSERT(!spdk_blob_is_thin_provisioned(blob));
/* blob should not have underlying snapshot nor clones */ /* blob should not have underlying snapshot nor clones */
CU_ASSERT(blob->parent_id == SPDK_BLOBID_INVALID);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID); CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID);
count = SPDK_COUNTOF(ids); count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, blobid, ids, &count); rc = spdk_blob_get_clones(bs, blobid, ids, &count);
@ -4161,6 +4162,7 @@ blob_relations(void)
CU_ASSERT(spdk_blob_is_read_only(snapshot)); CU_ASSERT(spdk_blob_is_read_only(snapshot));
CU_ASSERT(spdk_blob_is_snapshot(snapshot)); CU_ASSERT(spdk_blob_is_snapshot(snapshot));
CU_ASSERT(!spdk_blob_is_clone(snapshot)); CU_ASSERT(!spdk_blob_is_clone(snapshot));
CU_ASSERT(snapshot->parent_id == SPDK_BLOBID_INVALID);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid) == SPDK_BLOBID_INVALID); CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid) == SPDK_BLOBID_INVALID);
/* Check if original blob is converted to the clone of snapshot */ /* Check if original blob is converted to the clone of snapshot */
@ -4168,7 +4170,7 @@ blob_relations(void)
CU_ASSERT(!spdk_blob_is_snapshot(blob)); CU_ASSERT(!spdk_blob_is_snapshot(blob));
CU_ASSERT(spdk_blob_is_clone(blob)); CU_ASSERT(spdk_blob_is_clone(blob));
CU_ASSERT(spdk_blob_is_thin_provisioned(blob)); CU_ASSERT(spdk_blob_is_thin_provisioned(blob));
CU_ASSERT(blob->parent_id == snapshotid);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid); CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid);
count = SPDK_COUNTOF(ids); count = SPDK_COUNTOF(ids);
@ -4194,7 +4196,7 @@ blob_relations(void)
CU_ASSERT(!spdk_blob_is_snapshot(clone)); CU_ASSERT(!spdk_blob_is_snapshot(clone));
CU_ASSERT(spdk_blob_is_clone(clone)); CU_ASSERT(spdk_blob_is_clone(clone));
CU_ASSERT(spdk_blob_is_thin_provisioned(clone)); CU_ASSERT(spdk_blob_is_thin_provisioned(clone));
CU_ASSERT(clone->parent_id == snapshotid);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid); CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid);
count = SPDK_COUNTOF(ids); count = SPDK_COUNTOF(ids);
@ -4210,7 +4212,41 @@ blob_relations(void)
CU_ASSERT(ids[0] == cloneid || ids[1] == cloneid); CU_ASSERT(ids[0] == cloneid || ids[1] == cloneid);
/* 4. Try to create clone from read only blob */ /* 4. Create snapshot of the clone */
spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL);
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
snapshotid2 = g_blobid;
spdk_bs_open_blob(bs, snapshotid2, blob_op_with_handle_complete, NULL);
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot2 = g_blob;
CU_ASSERT(spdk_blob_is_read_only(snapshot2));
CU_ASSERT(spdk_blob_is_snapshot(snapshot2));
CU_ASSERT(spdk_blob_is_clone(snapshot2));
CU_ASSERT(snapshot2->parent_id == snapshotid);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid);
/* Check if clone is converted to the clone of snapshot2 and snapshot2
* is a child of snapshot */
CU_ASSERT(!spdk_blob_is_read_only(clone));
CU_ASSERT(!spdk_blob_is_snapshot(clone));
CU_ASSERT(spdk_blob_is_clone(clone));
CU_ASSERT(spdk_blob_is_thin_provisioned(clone));
CU_ASSERT(clone->parent_id == snapshotid2);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid);
/* 5. Try to create clone from read only blob */
/* Mark blob as read only */ /* Mark blob as read only */
spdk_blob_set_read_only(blob); spdk_blob_set_read_only(blob);
@ -4262,10 +4298,16 @@ blob_relations(void)
spdk_blob_close(snapshot, blob_op_complete, NULL); spdk_blob_close(snapshot, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0); CU_ASSERT(g_bserrno == 0);
spdk_blob_close(snapshot2, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
/* Try to delete snapshot with created clones */ /* Try to delete snapshot with created clones */
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
CU_ASSERT(g_bserrno != 0); CU_ASSERT(g_bserrno != 0);
spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
CU_ASSERT(g_bserrno != 0);
spdk_bs_unload(bs, bs_op_complete, NULL); spdk_bs_unload(bs, bs_op_complete, NULL);
CU_ASSERT(g_bserrno == 0); CU_ASSERT(g_bserrno == 0);
g_bs = NULL; g_bs = NULL;
@ -4303,7 +4345,7 @@ blob_relations(void)
CU_ASSERT(rc == 0); CU_ASSERT(rc == 0);
CU_ASSERT(count == 2); CU_ASSERT(count == 2);
CU_ASSERT(ids[0] == blobid || ids[1] == blobid); CU_ASSERT(ids[0] == blobid || ids[1] == blobid);
CU_ASSERT(ids[0] == cloneid || ids[1] == cloneid); CU_ASSERT(ids[0] == snapshotid2 || ids[1] == snapshotid2);
/* blob */ /* blob */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid); CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid);
@ -4314,12 +4356,20 @@ blob_relations(void)
CU_ASSERT(ids[0] == cloneid2); CU_ASSERT(ids[0] == cloneid2);
/* clone */ /* clone */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid); CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2);
count = SPDK_COUNTOF(ids); count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, cloneid, ids, &count); rc = spdk_blob_get_clones(bs, cloneid, ids, &count);
CU_ASSERT(rc == 0); CU_ASSERT(rc == 0);
CU_ASSERT(count == 0); CU_ASSERT(count == 0);
/* snapshot2 */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid);
/* clone2 */ /* clone2 */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid); CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid);
count = SPDK_COUNTOF(ids); count = SPDK_COUNTOF(ids);
@ -4327,15 +4377,23 @@ blob_relations(void)
CU_ASSERT(rc == 0); CU_ASSERT(rc == 0);
CU_ASSERT(count == 0); CU_ASSERT(count == 0);
/* Try to delete all blobs */ /* Try to delete all blobs in the worse possible order */
spdk_bs_delete_blob(bs, cloneid, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0); spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
CU_ASSERT(g_bserrno != 0);
spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
CU_ASSERT(g_bserrno != 0);
spdk_bs_delete_blob(bs, cloneid, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
/* Try to delete snapshot with clones */
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
CU_ASSERT(g_bserrno != 0); CU_ASSERT(g_bserrno != 0);
/* Try to delete ro blob with clones */
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
CU_ASSERT(g_bserrno != 0); CU_ASSERT(g_bserrno != 0);