Commit 9e554deb authored by Jim Harris's avatar Jim Harris Committed by Konrad Sztyber
Browse files

test/unit/blob: add SZ to represent cluster size in blocks for io tests



The various test_io/test_iov helper functions are littered with
hard-coded values based on a known size of 32 blocks per cluster. We
will need to increase this size in an upcoming patch, to support
larger metadata page sizes. But instead of replacing all of the
existing hard-coded values with new hard-coded values, introduce
local SZ variables, and do various math based on that. Then increasing
the size of these clusters in the later patch will be trivial.

Signed-off-by: default avatarJim Harris <jim.harris@samsung.com>
Change-Id: Ie931b026e7b274854fbde492f8a785d5a03b5398
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/25310


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Community-CI: Community CI Samsung <spdk.community.ci.samsung@gmail.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
parent d0dfbef6
Loading
Loading
Loading
Loading
+67 −61
Original line number Diff line number Diff line
@@ -6812,6 +6812,7 @@ blob_create_snapshot_power_failure(void)
static void
test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
{
	const uint32_t SZ = 32; /* size of cluster in 512-byte blocks */
	uint8_t payload_ff[64 * 512];
	uint8_t payload_aa[64 * 512];
	uint8_t payload_00[64 * 512];
@@ -6834,7 +6835,7 @@ test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	* Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */
	/* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
	CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 31 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, (SZ - 1) * 512) == 0);

	/* Verify write with offset on first page */
	spdk_blob_io_write(blob, channel, payload_ff, 2, 1, blob_op_complete, NULL);
@@ -6846,7 +6847,7 @@ test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Verify write with offset on first page */
	spdk_blob_io_write(blob, channel, payload_ff, 4, 4, blob_op_complete, NULL);
@@ -6858,7 +6859,7 @@ test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, 24 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, (SZ - 8) * 512) == 0);

	/* Verify write with offset on second page */
	spdk_blob_io_write(blob, channel, payload_ff, 8, 4, blob_op_complete, NULL);
@@ -6870,7 +6871,7 @@ test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, (SZ - 12) * 512) == 0);

	/* Verify write across multiple pages */
	spdk_blob_io_write(blob, channel, payload_aa, 4, 8, blob_op_complete, NULL);
@@ -6882,10 +6883,10 @@ test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, (SZ - 12) * 512) == 0);

	/* Verify write across multiple clusters */
	spdk_blob_io_write(blob, channel, payload_ff, 28, 8, blob_op_complete, NULL);
	spdk_blob_io_write(blob, channel, payload_ff, SZ - 4, 8, blob_op_complete, NULL);
	poll_threads();

	SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
@@ -6898,13 +6899,13 @@ test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + (SZ - 4) * 512, payload_ff, 4 * 512) == 0);

	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Verify write to second cluster */
	spdk_blob_io_write(blob, channel, payload_ff, 32 + 12, 2, blob_op_complete, NULL);
	spdk_blob_io_write(blob, channel, payload_ff, SZ + 12, 2, blob_op_complete, NULL);
	poll_threads();

	SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
@@ -6917,17 +6918,18 @@ test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + (SZ - 4) * 512, payload_ff, 4 * 512) == 0);

	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 12 * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, 18 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, (SZ - 14) * 512) == 0);
}

static void
test_io_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
{
	const uint32_t SZ = 32; /* size of cluster in 512-byte blocks */
	uint8_t payload_read[64 * 512];
	uint8_t payload_ff[64 * 512];
	uint8_t payload_aa[64 * 512];
@@ -6946,7 +6948,7 @@ test_io_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_cha
	poll_threads();
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 31 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, (SZ - 1) * 512) == 0);

	/* Read four io_units starting from offset = 2
	 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
@@ -6962,7 +6964,7 @@ test_io_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_cha
	CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 2 * 512, payload_aa, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 3 * 512, payload_aa, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Read eight io_units across multiple pages
	 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
@@ -6974,51 +6976,51 @@ test_io_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_cha
	CU_ASSERT(g_bserrno == 0);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, (SZ - 8) * 512) == 0);

	/* Read eight io_units across multiple clusters
	 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ]
	 * cluster1: [ FFFF) 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
	 * payload_read: FFFF FFFF | 0000 0000 ... */
	memset(payload_read, 0x00, sizeof(payload_read));
	spdk_blob_io_read(blob, channel, payload_read, 28, 8, blob_op_complete, NULL);
	spdk_blob_io_read(blob, channel, payload_read, SZ - 4, 8, blob_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, (SZ - 8) * 512) == 0);

	/* Read four io_units from second cluster
	 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
	 * cluster1: [ FFFF 0000 | 00(00 FF)00 | 0000 0000 | 0000 0000 ]
	 * payload_read: 00FF 0000 | 0000 0000 ... */
	memset(payload_read, 0x00, sizeof(payload_read));
	spdk_blob_io_read(blob, channel, payload_read, 32 + 10, 4, blob_op_complete, NULL);
	spdk_blob_io_read(blob, channel, payload_read, SZ + 10, 4, blob_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_00, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Read second cluster
	 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
	 * cluster1: [ (FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ]
	 * payload_read: FFFF 0000 | 0000 FF00 ... */
	memset(payload_read, 0x00, sizeof(payload_read));
	spdk_blob_io_read(blob, channel, payload_read, 32, 32, blob_op_complete, NULL);
	spdk_blob_io_read(blob, channel, payload_read, SZ, SZ, blob_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 12 * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, 18 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, (SZ - 14) * 512) == 0);

	/* Read whole two clusters
	 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
	 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] */
	memset(payload_read, 0x00, sizeof(payload_read));
	spdk_blob_io_read(blob, channel, payload_read, 0, 64, blob_op_complete, NULL);
	spdk_blob_io_read(blob, channel, payload_read, 0, SZ * 2, blob_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);

@@ -7027,18 +7029,19 @@ test_io_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_cha
	CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 28 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ - 4) * 512, payload_ff, 4 * 512) == 0);

	CU_ASSERT(memcmp(payload_read + (32 + 0) * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (32 + 4) * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (32 + 12) * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (32 + 14) * 512, payload_00, 18 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 0) * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 4) * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 12) * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 14) * 512, payload_00, (SZ - 14) * 512) == 0);
}


static void
test_io_unmap(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
{
	const uint32_t SZ = 32; /* size of cluster in 512-byte blocks */
	uint8_t payload_ff[64 * 512];
	uint8_t payload_aa[64 * 512];
	uint8_t payload_00[64 * 512];
@@ -7052,18 +7055,19 @@ test_io_unmap(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];

	/* Unmap */
	spdk_blob_io_unmap(blob, channel, 0, 64, blob_op_complete, NULL);
	spdk_blob_io_unmap(blob, channel, 0, SZ * 2, blob_op_complete, NULL);
	poll_threads();

	CU_ASSERT(g_bserrno == 0);

	CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, 32 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, 32 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, SZ * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, SZ * 512) == 0);
}

static void
test_io_zeroes(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
{
	const uint32_t SZ = 32; /* size of cluster in 512-byte blocks */
	uint8_t payload_ff[64 * 512];
	uint8_t payload_aa[64 * 512];
	uint8_t payload_00[64 * 512];
@@ -7077,13 +7081,13 @@ test_io_zeroes(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];

	/* Write zeroes  */
	spdk_blob_io_write_zeroes(blob, channel, 0, 64, blob_op_complete, NULL);
	spdk_blob_io_write_zeroes(blob, channel, 0, SZ * 2, blob_op_complete, NULL);
	poll_threads();

	CU_ASSERT(g_bserrno == 0);

	CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, 32 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, 32 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, SZ * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, SZ * 512) == 0);
}

static inline void
@@ -7111,6 +7115,7 @@ static void
test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel,
	       bool ext_api)
{
	const uint32_t SZ = 32; /* size of cluster in 512-byte blocks */
	uint8_t payload_ff[64 * 512];
	uint8_t payload_aa[64 * 512];
	uint8_t payload_00[64 * 512];
@@ -7142,7 +7147,7 @@ test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	* Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */
	/* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
	CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 31 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, (SZ - 1) * 512) == 0);

	/* Verify write with offset on first page */
	iov[0].iov_base = payload_ff;
@@ -7156,7 +7161,7 @@ test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Verify write with offset on first page */
	iov[0].iov_base = payload_ff;
@@ -7170,7 +7175,7 @@ test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, 24 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, (SZ - 8) * 512) == 0);

	/* Verify write with offset on second page */
	iov[0].iov_base = payload_ff;
@@ -7184,7 +7189,7 @@ test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, (SZ - 12) * 512) == 0);

	/* Verify write across multiple pages */
	iov[0].iov_base = payload_aa;
@@ -7199,14 +7204,14 @@ test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, (SZ - 12) * 512) == 0);

	/* Verify write across multiple clusters */

	iov[0].iov_base = payload_ff;
	iov[0].iov_len = 8 * 512;

	test_blob_io_writev(blob, channel, iov, 1, 28, 8, blob_op_complete, NULL,
	test_blob_io_writev(blob, channel, iov, 1, (SZ - 4), 8, blob_op_complete, NULL,
			    ext_api ? &ext_opts : NULL);

	SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
@@ -7219,18 +7224,18 @@ test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 16 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, (SZ - 16) * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + (SZ - 4) * 512, payload_ff, 4 * 512) == 0);

	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Verify write to second cluster */

	iov[0].iov_base = payload_ff;
	iov[0].iov_len = 2 * 512;

	test_blob_io_writev(blob, channel, iov, 1, 32 + 12, 2, blob_op_complete, NULL,
	test_blob_io_writev(blob, channel, iov, 1, SZ + 12, 2, blob_op_complete, NULL,
			    ext_api ? &ext_opts : NULL);

	SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
@@ -7243,12 +7248,12 @@ test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_c
	CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster0 + (SZ - 4) * 512, payload_ff, 4 * 512) == 0);

	CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 12 * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, 18 * 512) == 0);
	CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, (SZ - 14) * 512) == 0);
}

static inline void
@@ -7275,6 +7280,7 @@ static void
test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel,
	      bool ext_api)
{
	const uint32_t SZ = 32; /* size of cluster in 512-byte blocks */
	uint8_t payload_read[64 * 512];
	uint8_t payload_ff[64 * 512];
	uint8_t payload_aa[64 * 512];
@@ -7302,7 +7308,7 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	test_blob_io_readv(blob, channel, iov, 1, 0, 1, blob_op_complete, NULL, ext_api ? &ext_opts : NULL);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 31 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, (SZ - 1) * 512) == 0);

	/* Read four io_units starting from offset = 2
	 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
@@ -7319,7 +7325,7 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 2 * 512, payload_aa, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 3 * 512, payload_aa, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Read eight io_units across multiple pages
	 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
@@ -7334,7 +7340,7 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	test_blob_io_readv(blob, channel, iov, 2, 4, 8, blob_op_complete, NULL, ext_api ? &ext_opts : NULL);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, (SZ - 8) * 512) == 0);

	/* Read eight io_units across multiple clusters
	 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ]
@@ -7350,11 +7356,11 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	iov[3].iov_base = payload_read + 6 * 512;
	iov[3].iov_len = 2 * 512;

	test_blob_io_readv(blob, channel, iov, 4, 28, 8, blob_op_complete, NULL,
	test_blob_io_readv(blob, channel, iov, 4, SZ - 4, 8, blob_op_complete, NULL,
			   ext_api ? &ext_opts : NULL);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, (SZ - 8) * 512) == 0);

	/* Read four io_units from second cluster
	 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
@@ -7366,12 +7372,12 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	iov[1].iov_base = payload_read + 1 * 512;
	iov[1].iov_len = 3 * 512;

	test_blob_io_readv(blob, channel, iov, 2, 32 + 10, 4, blob_op_complete, NULL,
	test_blob_io_readv(blob, channel, iov, 2, SZ + 10, 4, blob_op_complete, NULL,
			   ext_api ? &ext_opts : NULL);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_00, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, (SZ - 4) * 512) == 0);

	/* Read second cluster
	 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
@@ -7385,15 +7391,15 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	iov[2].iov_base = payload_read + 3 * 512;
	iov[2].iov_len = 4 * 512;
	iov[3].iov_base = payload_read + 7 * 512;
	iov[3].iov_len = 25 * 512;
	iov[3].iov_len = (SZ - 7) * 512;

	test_blob_io_readv(blob, channel, iov, 4, 32, 32, blob_op_complete, NULL,
	test_blob_io_readv(blob, channel, iov, 4, SZ, SZ, blob_op_complete, NULL,
			   ext_api ? &ext_opts : NULL);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 12 * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, 18 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, (SZ - 14) * 512) == 0);

	/* Read whole two clusters
	 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
@@ -7406,9 +7412,9 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	iov[2].iov_base = payload_read + 9 * 512;
	iov[2].iov_len = 16 * 512;
	iov[3].iov_base = payload_read + 25 * 512;
	iov[3].iov_len = 39 * 512;
	iov[3].iov_len = (2 * SZ - 25) * 512;

	test_blob_io_readv(blob, channel, iov, 4, 0, 64, blob_op_complete, NULL,
	test_blob_io_readv(blob, channel, iov, 4, 0, SZ * 2, blob_op_complete, NULL,
			   ext_api ? &ext_opts : NULL);

	CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
@@ -7416,12 +7422,12 @@ test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_ch
	CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 3 * 512, payload_00, 512) == 0);
	CU_ASSERT(memcmp(payload_read + 4 * 512, payload_aa, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + 28 * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ - 4) * 512, payload_ff, 4 * 512) == 0);

	CU_ASSERT(memcmp(payload_read + (32 + 0) * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (32 + 4) * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (32 + 12) * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (32 + 14) * 512, payload_00, 18 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 0) * 512, payload_ff, 4 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 4) * 512, payload_00, 8 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 12) * 512, payload_ff, 2 * 512) == 0);
	CU_ASSERT(memcmp(payload_read + (SZ + 14) * 512, payload_00, (SZ - 14) * 512) == 0);
}

static void