Commit 079ad446 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Jim Harris
Browse files

dif: Support multiple iovecs for data buffer in spdk_dif_set_md_interleave_iovs



This patch allows multiple iovecs as argument of
spdk_dif_set_md_interleave_iovs.

Subsequent patches will support SGL data buffer in
spdk_dif_generate_stream too. UT code tests only
spdk_dif_set_md_interleave until then.

Change-Id: I7ac03a3c8f7bcd922af4f29b404ebf3acc4b89e5
Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453736


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 2821762a
Loading
Loading
Loading
Loading
+60 −1
Original line number Diff line number Diff line
@@ -1333,6 +1333,64 @@ dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
	return iovcnt - sgl.iovcnt;
}

static int
dif_set_md_interleave_iovs_split(struct iovec *iovs, int iovcnt,
				 struct iovec *buf_iovs, int buf_iovcnt,
				 uint32_t data_offset, uint32_t data_len,
				 uint32_t *_mapped_len,
				 const struct spdk_dif_ctx *ctx)
{
	uint32_t data_block_size, head_unalign;
	uint32_t num_blocks, offset_blocks;
	struct _dif_sgl dif_sgl;
	struct _dif_sgl buf_sgl;
	uint8_t *buf;
	uint32_t buf_len, remaining;

	data_block_size = ctx->block_size - ctx->md_size;
	num_blocks = data_len / data_block_size;

	_dif_sgl_init(&dif_sgl, iovs, iovcnt);
	_dif_sgl_init(&buf_sgl, buf_iovs, buf_iovcnt);

	if (!_dif_sgl_is_valid(&buf_sgl, num_blocks * ctx->block_size)) {
		SPDK_ERRLOG("Buffer overflow will occur.\n");
		return -ERANGE;
	}

	offset_blocks = data_offset / data_block_size;
	head_unalign = data_offset % data_block_size;

	_dif_sgl_fast_forward(&buf_sgl, offset_blocks * ctx->block_size);

	while (offset_blocks < num_blocks) {
		_dif_sgl_fast_forward(&buf_sgl, head_unalign);

		remaining = data_block_size - head_unalign;
		while (remaining != 0) {
			_dif_sgl_get_buf(&buf_sgl, (void *)&buf, &buf_len);
			buf_len = spdk_min(buf_len, remaining);

			if (!_dif_sgl_append(&dif_sgl, buf, buf_len)) {
				goto end;
			}
			_dif_sgl_advance(&buf_sgl, buf_len);
			remaining -= buf_len;
		}
		_dif_sgl_fast_forward(&buf_sgl, ctx->md_size);
		offset_blocks++;

		head_unalign = 0;
	}

end:
	if (_mapped_len != NULL) {
		*_mapped_len = dif_sgl.total_size;
	}

	return iovcnt - dif_sgl.iovcnt;
}

int
spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
				struct iovec *buf_iovs, int buf_iovcnt,
@@ -1363,7 +1421,8 @@ spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
						  buf_iovs[0].iov_base, buf_iovs[0].iov_len,
						  data_offset, data_len, _mapped_len, ctx);
	} else {
		return -EINVAL;
		return dif_set_md_interleave_iovs_split(iovs, iovcnt, buf_iovs, buf_iovcnt,
							data_offset, data_len, _mapped_len, ctx);
	}
}

+92 −0
Original line number Diff line number Diff line
@@ -1493,6 +1493,96 @@ set_md_interleave_iovs_test(void)
	free(buf2);
}

static void
set_md_interleave_iovs_split_test(void)
{
	struct spdk_dif_ctx ctx = {};
	struct iovec iovs1[7], dif_iovs[8];
	uint32_t dif_check_flags, mapped_len = 0, read_base = 0;
	int rc, i;

	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
			  SPDK_DIF_FLAGS_REFTAG_CHECK;

	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
			       dif_check_flags, 22, 0xFFFF, 0x22, GUARD_SEED);
	CU_ASSERT(rc == 0);

	/* The first SGL data buffer:
	 * - Create iovec array to leave a space for metadata for each block
	 * - Split vectored read and so creating iovec array is done before every vectored read.
	 */
	_iov_alloc_buf(&iovs1[0], 512 + 8 + 128);
	_iov_alloc_buf(&iovs1[1], 128);
	_iov_alloc_buf(&iovs1[2], 256 + 8);
	_iov_alloc_buf(&iovs1[3], 100);
	_iov_alloc_buf(&iovs1[4], 412 + 5);
	_iov_alloc_buf(&iovs1[5], 3 + 300);
	_iov_alloc_buf(&iovs1[6], 212 + 8);

	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
					     0, 512 * 4, &mapped_len, &ctx);
	CU_ASSERT(rc == 8);
	CU_ASSERT(mapped_len == 512 * 4);
	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base, 512) == true);
	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);

	read_base = ut_readv(0, 128, dif_iovs, 8);
	CU_ASSERT(read_base == 128);

	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
					     read_base, 512 * 4, &mapped_len, &ctx);
	CU_ASSERT(rc == 8);
	CU_ASSERT(mapped_len == 384 + 512 * 3);
	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 128, 384) == true);
	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);

	read_base += ut_readv(read_base, 383, dif_iovs, 8);
	CU_ASSERT(read_base == 511);

	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
					     read_base, 512 * 4, &mapped_len, &ctx);
	CU_ASSERT(rc == 8);
	CU_ASSERT(mapped_len == 1 + 512 * 3);
	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 511, 1) == true);
	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);

	read_base += ut_readv(read_base, 1 + 512 * 2 + 128, dif_iovs, 8);
	CU_ASSERT(read_base == 512 * 3 + 128);

	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
					     read_base, 512 * 4, &mapped_len, &ctx);
	CU_ASSERT(rc == 2);
	CU_ASSERT(mapped_len == 384);
	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[5].iov_base + 3 + 128, 172) == true);
	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[6].iov_base, 212) == true);

	read_base += ut_readv(read_base, 384, dif_iovs, 8);
	CU_ASSERT(read_base == 512 * 4);

	for (i = 0; i < 7; i++) {
		_iov_free_buf(&iovs1[i]);
	}
}

static void
dif_generate_stream_test(void)
{
@@ -1629,6 +1719,8 @@ main(int argc, char **argv)
		CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test",
			    dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL ||
		CU_add_test(suite, "set_md_interleave_iovs_test", set_md_interleave_iovs_test) == NULL ||
		CU_add_test(suite, "set_md_interleave_iovs_split_test",
			    set_md_interleave_iovs_split_test) == NULL ||
		CU_add_test(suite, "dif_generate_stream_test", dif_generate_stream_test) == NULL
	) {
		CU_cleanup_registry();