Commit dadd2a6d authored by Piotr Pelplinski's avatar Piotr Pelplinski Committed by Jim Harris
Browse files

bdev: add unit tests for double buffering in bdev modules



Signed-off-by: default avatarPiotr Pelplinski <piotr.pelplinski@intel.com>
Change-Id: Idcfb328a26fc85f3c144da9c27086a71c00d0d46
Reviewed-on: https://review.gerrithub.io/427830


Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarMaciej Szwed <maciej.szwed@intel.com>
parent c1f1a876
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ spdk_mempool_get(struct spdk_mempool *_mp)
		return NULL;
	}

	if (posix_memalign(&buf, 64, 0x1000)) {
	if (posix_memalign(&buf, 64, 0x10000)) {
		return NULL;
	} else {
		if (mp) {
+229 −1
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ struct bdev_ut_channel {
};

static bool g_io_done;
static struct spdk_bdev_io *g_bdev_io;
static enum spdk_bdev_io_status g_io_status;
static uint32_t g_bdev_ut_io_device;
static struct bdev_ut_channel *g_bdev_ut_channel;
@@ -140,6 +141,8 @@ stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
	struct iovec *iov, *expected_iov;
	int i;

	g_bdev_io = bdev_io;

	TAILQ_INSERT_TAIL(&ch->outstanding_io, bdev_io, module_link);
	ch->outstanding_io_count++;

@@ -178,6 +181,13 @@ stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
	free(expected_io);
}

static void
stub_submit_request_aligned_buffer(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
{
	spdk_bdev_io_get_buf(bdev_io, stub_submit_request,
			     bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
}

static uint32_t
stub_complete_io(uint32_t num_to_complete)
{
@@ -1172,6 +1182,223 @@ bdev_io_split_with_io_wait(void)
	spdk_bdev_finish(bdev_fini_cb, NULL);
}

static void
bdev_io_alignment(void)
{
	struct spdk_bdev *bdev;
	struct spdk_bdev_desc *desc;
	struct spdk_io_channel *io_ch;
	struct spdk_bdev_opts bdev_opts = {
		.bdev_io_pool_size = 20,
		.bdev_io_cache_size = 2,
	};
	int rc;
	void *buf;
	struct iovec iovs[2];
	int iovcnt;
	uint64_t alignment;

	rc = spdk_bdev_set_opts(&bdev_opts);
	CU_ASSERT(rc == 0);
	spdk_bdev_initialize(bdev_init_cb, NULL);

	fn_table.submit_request = stub_submit_request_aligned_buffer;
	bdev = allocate_bdev("bdev0");

	rc = spdk_bdev_open(bdev, true, NULL, NULL, &desc);
	CU_ASSERT(rc == 0);
	CU_ASSERT(desc != NULL);
	io_ch = spdk_bdev_get_io_channel(desc);
	CU_ASSERT(io_ch != NULL);

	/* Create aligned buffer */
	rc = posix_memalign(&buf, 4096, 8192);
	SPDK_CU_ASSERT_FATAL(rc == 0);

	/* Pass aligned single buffer with no alignment required */
	alignment = 1;
	bdev->required_alignment = spdk_u32log2(alignment);

	rc = spdk_bdev_write_blocks(desc, io_ch, buf, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	stub_complete_io(1);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));

	rc = spdk_bdev_read_blocks(desc, io_ch, buf, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	stub_complete_io(1);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));

	/* Pass unaligned single buffer with no alignment required */
	alignment = 1;
	bdev->required_alignment = spdk_u32log2(alignment);

	rc = spdk_bdev_write_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == buf + 4);
	stub_complete_io(1);

	rc = spdk_bdev_read_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == buf + 4);
	stub_complete_io(1);

	/* Pass unaligned single buffer with 512 alignment required */
	alignment = 512;
	bdev->required_alignment = spdk_u32log2(alignment);

	rc = spdk_bdev_write_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);

	rc = spdk_bdev_read_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);

	/* Pass unaligned single buffer with 4096 alignment required */
	alignment = 4096;
	bdev->required_alignment = spdk_u32log2(alignment);

	rc = spdk_bdev_write_blocks(desc, io_ch, buf + 8, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);

	rc = spdk_bdev_read_blocks(desc, io_ch, buf + 8, 0, 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);

	/* Pass aligned iovs with no alignment required */
	alignment = 1;
	bdev->required_alignment = spdk_u32log2(alignment);

	iovcnt = 1;
	iovs[0].iov_base = buf;
	iovs[0].iov_len = 512;

	rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base);

	rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base);

	/* Pass unaligned iovs with no alignment required */
	alignment = 1;
	bdev->required_alignment = spdk_u32log2(alignment);

	iovcnt = 2;
	iovs[0].iov_base = buf + 16;
	iovs[0].iov_len = 256;
	iovs[1].iov_base = buf + 16 + 256 + 32;
	iovs[1].iov_len = 256;

	rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base);

	rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base);

	/* Pass unaligned iov with 2048 alignment required */
	alignment = 2048;
	bdev->required_alignment = spdk_u32log2(alignment);

	iovcnt = 2;
	iovs[0].iov_base = buf + 16;
	iovs[0].iov_len = 256;
	iovs[1].iov_base = buf + 16 + 256 + 32;
	iovs[1].iov_len = 256;

	rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == iovcnt);
	CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);

	rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == iovcnt);
	CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);

	/* Pass iov without allocated buffer without alignment required */
	alignment = 1;
	bdev->required_alignment = spdk_u32log2(alignment);

	iovcnt = 1;
	iovs[0].iov_base = NULL;
	iovs[0].iov_len = 0;

	rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);

	/* Pass iov without allocated buffer with 1024 alignment required */
	alignment = 1024;
	bdev->required_alignment = spdk_u32log2(alignment);

	iovcnt = 1;
	iovs[0].iov_base = NULL;
	iovs[0].iov_len = 0;

	rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0);
	CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt,
				    alignment));
	stub_complete_io(1);

	spdk_put_io_channel(io_ch);
	spdk_bdev_close(desc);
	free_bdev(bdev);
	spdk_bdev_finish(bdev_fini_cb, NULL);

	free(buf);
}

int
main(int argc, char **argv)
{
@@ -1198,7 +1425,8 @@ main(int argc, char **argv)
		CU_add_test(suite, "bdev_io_wait", bdev_io_wait_test) == NULL ||
		CU_add_test(suite, "bdev_io_spans_boundary", bdev_io_spans_boundary_test) == NULL ||
		CU_add_test(suite, "bdev_io_split", bdev_io_split) == NULL ||
		CU_add_test(suite, "bdev_io_split_with_io_wait", bdev_io_split_with_io_wait) == NULL
		CU_add_test(suite, "bdev_io_split_with_io_wait", bdev_io_split_with_io_wait) == NULL ||
		CU_add_test(suite, "bdev_io_alignment", bdev_io_alignment) == NULL
	) {
		CU_cleanup_registry();
		return CU_get_error();