Commit 826aac63 authored by Tomasz Kulasek's avatar Tomasz Kulasek Committed by Jim Harris
Browse files

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: default avatarTomasz Kulasek <tomaszx.kulasek@intel.com>
Reviewed-on: https://review.gerrithub.io/414804


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent 9d04d0ef
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -4303,6 +4303,8 @@ _spdk_bs_snapshot_newblob_sync_cpl(void *cb_arg, int bserrno)
		_spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno);
		return;
	}

	_spdk_bs_blob_list_remove(origblob);
	origblob->parent_id = newblob->id;

	/* 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_blob *origblob = ctx->original.blob;
	struct spdk_blob *newblob = ctx->new.blob;
	int bserrno;

	if (rc != 0) {
		_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 */
	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 */
	memcpy(newblob->active.clusters, origblob->active.clusters,
	       origblob->active.num_clusters * sizeof(origblob->active.clusters));
+75 −17
Original line number Diff line number Diff line
@@ -4090,11 +4090,11 @@ blob_inflate_rw(void)
 *
 *         snapshot
 *            |
 *     +----+----+
 *      +-----+-----+
 *      |           |
 *   blob      clone
 *     |
 *  clone2
 *   blob(ro)   snapshot2
 *      |           |
 *   clone2      clone
 */
static void
blob_relations(void)
@@ -4103,8 +4103,8 @@ blob_relations(void)
	struct spdk_bs_dev *dev;
	struct spdk_bs_opts bs_opts;
	struct spdk_blob_opts opts;
	struct spdk_blob *blob, *snapshot, *clone, *clone2;
	spdk_blob_id blobid, cloneid, snapshotid, cloneid2;
	struct spdk_blob *blob, *snapshot, *snapshot2, *clone, *clone2;
	spdk_blob_id blobid, cloneid, snapshotid, cloneid2, snapshotid2;
	int rc;
	size_t count;
	spdk_blob_id ids[10];
@@ -4139,6 +4139,7 @@ blob_relations(void)
	CU_ASSERT(!spdk_blob_is_thin_provisioned(blob));

	/* 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);
	count = SPDK_COUNTOF(ids);
	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_snapshot(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);

	/* 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_clone(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);

	count = SPDK_COUNTOF(ids);
@@ -4194,7 +4196,7 @@ blob_relations(void)
	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 == snapshotid);
	CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid);

	count = SPDK_COUNTOF(ids);
@@ -4210,7 +4212,41 @@ blob_relations(void)
	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 */
	spdk_blob_set_read_only(blob);
@@ -4262,10 +4298,16 @@ blob_relations(void)
	spdk_blob_close(snapshot, blob_op_complete, NULL);
	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 */
	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_unload(bs, bs_op_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
	g_bs = NULL;
@@ -4303,7 +4345,7 @@ blob_relations(void)
	CU_ASSERT(rc == 0);
	CU_ASSERT(count == 2);
	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 */
	CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid);
@@ -4314,12 +4356,20 @@ blob_relations(void)
	CU_ASSERT(ids[0] == cloneid2);

	/* 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);
	rc = spdk_blob_get_clones(bs, cloneid, ids, &count);
	CU_ASSERT(rc == 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 */
	CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid);
	count = SPDK_COUNTOF(ids);
@@ -4327,15 +4377,23 @@ blob_relations(void)
	CU_ASSERT(rc == 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, 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);

	/* Try to delete snapshot with clones */
	spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
	CU_ASSERT(g_bserrno == 0);

	spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
	CU_ASSERT(g_bserrno != 0);

	/* Try to delete ro blob with clones */
	spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
	CU_ASSERT(g_bserrno != 0);