Commit b357ad48 authored by Diwakar Sharma's avatar Diwakar Sharma Committed by Tomasz Zawadzki
Browse files

blob: Handle range check for all snapshot back_bs_dev up in the chain



When there are multiple snapshots in the backing for a blob,
we traverse all of them. During traversal, the is_range_valid
check need to be done for every one of them.

Change-Id: Ib8318a5d3cdc558e7f295e0543587a20a2c32917
Signed-off-by: default avatarDiwakar Sharma <diwakar.sharma@datacore.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/23020


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent d148fba3
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ blob_bs_is_zeroes(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
{
	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
	struct spdk_blob *blob = b->blob;
	bool is_valid_range;

	assert(lba == bs_cluster_to_lba(blob->bs, bs_lba_to_cluster(blob->bs, lba)));
	assert(lba_count == bs_dev_byte_to_lba(dev, blob->bs->cluster_sz));
@@ -183,7 +184,8 @@ blob_bs_is_zeroes(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
	}

	assert(blob->back_bs_dev != NULL);
	return blob->back_bs_dev->is_zeroes(blob->back_bs_dev,
	is_valid_range = blob->back_bs_dev->is_range_valid(blob->back_bs_dev, lba, lba_count);
	return is_valid_range && blob->back_bs_dev->is_zeroes(blob->back_bs_dev,
			bs_io_unit_to_back_dev_lba(blob, lba),
			bs_io_unit_to_back_dev_lba(blob, lba_count));
}
@@ -220,6 +222,7 @@ blob_bs_translate_lba(struct spdk_bs_dev *dev, uint64_t lba, uint64_t *base_lba)
{
	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
	struct spdk_blob *blob = b->blob;
	bool is_valid_range;

	assert(base_lba != NULL);
	if (bs_io_unit_is_allocated(blob, lba)) {
@@ -228,7 +231,12 @@ blob_bs_translate_lba(struct spdk_bs_dev *dev, uint64_t lba, uint64_t *base_lba)
	}

	assert(blob->back_bs_dev != NULL);
	return blob->back_bs_dev->translate_lba(blob->back_bs_dev,
	/* Since here we don't get lba_count directly, passing lba_count derived
	 * from cluster_sz which typically happens for other calls like is_zeroes
	 * in CoW path. */
	is_valid_range = blob->back_bs_dev->is_range_valid(blob->back_bs_dev, lba,
			 bs_dev_byte_to_lba(blob->back_bs_dev, blob->bs->cluster_sz));
	return is_valid_range && blob->back_bs_dev->translate_lba(blob->back_bs_dev,
			bs_io_unit_to_back_dev_lba(blob, lba),
			base_lba);
}
+41 −4
Original line number Diff line number Diff line
@@ -9115,8 +9115,8 @@ blob_clone_resize(void)
{
	struct spdk_blob_store *bs = g_bs;
	struct spdk_blob_opts opts;
	struct spdk_blob *blob, *clone;
	spdk_blob_id blobid, cloneid, snapshotid;
	struct spdk_blob *blob, *clone, *snap_blob, *snap_blob_rsz;
	spdk_blob_id blobid, cloneid, snapid1, snapid2;
	uint64_t pages_per_cluster;
	uint8_t payload_read[bs->dev->blocklen];
	uint8_t payload_write[bs->dev->blocklen];
@@ -9141,9 +9141,9 @@ blob_clone_resize(void)
	poll_threads();
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
	snapshotid = g_blobid;
	snapid1 = g_blobid;

	spdk_bs_create_clone(bs, snapshotid, NULL, blob_op_with_id_complete, NULL);
	spdk_bs_create_clone(bs, snapid1, NULL, blob_op_with_id_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
@@ -9162,6 +9162,35 @@ blob_clone_resize(void)
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(spdk_blob_get_num_clusters(clone) == 20);

	/* Create another snapshot after resizing the clone */
	spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
	snapid2 = g_blobid;

	/* Open the snapshot blobs */
	spdk_bs_open_blob(bs, snapid1, blob_op_with_handle_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
	SPDK_CU_ASSERT_FATAL(g_blob != NULL);
	snap_blob = g_blob;
	CU_ASSERT(snap_blob->data_ro == true);
	CU_ASSERT(snap_blob->md_ro == true);
	CU_ASSERT(spdk_blob_get_num_clusters(snap_blob) == 10);

	spdk_bs_open_blob(bs, snapid2, blob_op_with_handle_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
	SPDK_CU_ASSERT_FATAL(g_blob != NULL);
	snap_blob_rsz = g_blob;
	CU_ASSERT(snap_blob_rsz->data_ro == true);
	CU_ASSERT(snap_blob_rsz->md_ro == true);
	CU_ASSERT(spdk_blob_get_num_clusters(snap_blob_rsz) == 20);

	/* Confirm that clone is backed by snap_blob_rsz, and snap_blob_rsz is backed by snap_blob */
	SPDK_CU_ASSERT_FATAL(snap_blob->back_bs_dev == NULL);
	SPDK_CU_ASSERT_FATAL(blob->back_bs_dev != NULL);
	SPDK_CU_ASSERT_FATAL(snap_blob_rsz->back_bs_dev != NULL);

	/* Write and read from pre-resize ranges */
	g_bserrno = -1;
	memset(payload_write, 0xE5, sizeof(payload_write));
@@ -9204,6 +9233,14 @@ blob_clone_resize(void)
	poll_threads();
	CU_ASSERT(g_bserrno == 0);

	spdk_blob_close(snap_blob, blob_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);

	spdk_blob_close(snap_blob_rsz, blob_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);

	ut_blob_close_and_delete(bs, blob);

	spdk_bs_free_io_channel(channel);