ut/bdev: Prepare test code for submitting batched split I/Os

Current test code works only for sequential split I/Os. The next
patch will support submitting batchedsplit I/Os.

Prepare test code as a separate patch to make review easier.

Change-Id: I05b732c9a656ecab74a2594bf50ddf42eb41584e
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/425877
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-09-14 15:16:13 +09:00 committed by Changpeng Liu
parent 0df515a842
commit 3c7894ffff

View File

@ -88,14 +88,19 @@ stub_destruct(void *ctx)
return 0;
}
struct ut_expected_io {
uint8_t type;
uint64_t offset;
uint64_t length;
int iovcnt;
struct iovec iov[BDEV_IO_NUM_CHILD_IOV];
TAILQ_ENTRY(ut_expected_io) link;
};
struct bdev_ut_channel {
TAILQ_HEAD(, spdk_bdev_io) outstanding_io;
uint32_t outstanding_io_count;
uint8_t expected_iotype;
uint64_t expected_offset;
uint64_t expected_length;
int expected_iovcnt;
struct iovec expected_iov[BDEV_IO_NUM_CHILD_IOV];
TAILQ_HEAD(, ut_expected_io) expected_io;
};
static bool g_io_done;
@ -103,39 +108,73 @@ 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;
static struct ut_expected_io *
ut_alloc_expected_io(uint8_t type, uint64_t offset, uint64_t length, int iovcnt)
{
struct ut_expected_io *expected_io;
expected_io = calloc(1, sizeof(*expected_io));
SPDK_CU_ASSERT_FATAL(expected_io != NULL);
expected_io->type = type;
expected_io->offset = offset;
expected_io->length = length;
expected_io->iovcnt = iovcnt;
return expected_io;
}
static void
ut_expected_io_set_iov(struct ut_expected_io *expected_io, int pos, void *base, size_t len)
{
expected_io->iov[pos].iov_base = base;
expected_io->iov[pos].iov_len = len;
}
static void
stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
{
struct bdev_ut_channel *ch = spdk_io_channel_get_ctx(_ch);
struct ut_expected_io *expected_io;
struct iovec *iov, *expected_iov;
int i;
TAILQ_INSERT_TAIL(&ch->outstanding_io, bdev_io, module_link);
ch->outstanding_io_count++;
if (ch->expected_iotype != SPDK_BDEV_IO_TYPE_INVALID) {
CU_ASSERT(bdev_io->type == ch->expected_iotype);
expected_io = TAILQ_FIRST(&ch->expected_io);
if (expected_io == NULL) {
return;
}
TAILQ_REMOVE(&ch->expected_io, expected_io, link);
if (expected_io->type != SPDK_BDEV_IO_TYPE_INVALID) {
CU_ASSERT(bdev_io->type == expected_io->type);
}
if (ch->expected_length == 0) {
if (expected_io->length == 0) {
free(expected_io);
return;
}
CU_ASSERT(ch->expected_offset == bdev_io->u.bdev.offset_blocks);
CU_ASSERT(ch->expected_length = bdev_io->u.bdev.num_blocks);
CU_ASSERT(expected_io->offset == bdev_io->u.bdev.offset_blocks);
CU_ASSERT(expected_io->length = bdev_io->u.bdev.num_blocks);
if (ch->expected_iovcnt == 0) {
if (expected_io->iovcnt == 0) {
free(expected_io);
/* UNMAP, WRITE_ZEROES and FLUSH don't have iovs, so we can just return now. */
return;
}
CU_ASSERT(ch->expected_iovcnt == bdev_io->u.bdev.iovcnt);
for (i = 0; i < ch->expected_iovcnt; i++) {
CU_ASSERT(expected_io->iovcnt == bdev_io->u.bdev.iovcnt);
for (i = 0; i < expected_io->iovcnt; i++) {
iov = &bdev_io->u.bdev.iovs[i];
expected_iov = &ch->expected_iov[i];
expected_iov = &expected_io->iov[i];
CU_ASSERT(iov->iov_len == expected_iov->iov_len);
CU_ASSERT(iov->iov_base == expected_iov->iov_base);
}
free(expected_io);
}
static uint32_t
@ -188,6 +227,7 @@ bdev_ut_create_ch(void *io_device, void *ctx_buf)
TAILQ_INIT(&ch->outstanding_io);
ch->outstanding_io_count = 0;
TAILQ_INIT(&ch->expected_io);
return 0;
}
@ -792,6 +832,7 @@ bdev_io_split(void)
.bdev_io_cache_size = 64,
};
struct iovec iov[BDEV_IO_NUM_CHILD_IOV * 2];
struct ut_expected_io *expected_io;
uint64_t i;
int rc;
@ -813,12 +854,9 @@ bdev_io_split(void)
g_io_done = false;
/* First test that the I/O does not get split if split_on_optimal_io_boundary == false. */
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_READ;
g_bdev_ut_channel->expected_offset = 14;
g_bdev_ut_channel->expected_length = 8;
g_bdev_ut_channel->expected_iovcnt = 1;
g_bdev_ut_channel->expected_iov[0].iov_base = (void *)0xF000;
g_bdev_ut_channel->expected_iov[0].iov_len = 8 * 512;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 8, 1);
ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 8 * 512);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL);
CU_ASSERT(rc == 0);
@ -840,12 +878,9 @@ bdev_io_split(void)
* will submit the first child immediately.
*/
g_io_done = false;
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_READ;
g_bdev_ut_channel->expected_offset = 14;
g_bdev_ut_channel->expected_length = 2;
g_bdev_ut_channel->expected_iovcnt = 1;
g_bdev_ut_channel->expected_iov[0].iov_base = (void *)0xF000;
g_bdev_ut_channel->expected_iov[0].iov_len = 2 * 512;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1);
ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL);
CU_ASSERT(rc == 0);
@ -854,11 +889,9 @@ bdev_io_split(void)
/* Now set up the expected values for the second child. The second child will
* get submitted once the first child is completed by stub_complete_io().
*/
g_bdev_ut_channel->expected_offset = 16;
g_bdev_ut_channel->expected_length = 6;
g_bdev_ut_channel->expected_iovcnt = 1;
g_bdev_ut_channel->expected_iov[0].iov_base = (void *)(0xF000 + 2 * 512);
g_bdev_ut_channel->expected_iov[0].iov_len = 6 * 512;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1);
ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1);
stub_complete_io(1);
@ -882,36 +915,27 @@ bdev_io_split(void)
iov[2].iov_len = 11 * 512;
g_io_done = false;
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_WRITE;
g_bdev_ut_channel->expected_offset = 14;
g_bdev_ut_channel->expected_length = 2;
g_bdev_ut_channel->expected_iovcnt = 2;
g_bdev_ut_channel->expected_iov[0].iov_base = (void *)0x10000;
g_bdev_ut_channel->expected_iov[0].iov_len = 512;
g_bdev_ut_channel->expected_iov[1].iov_base = (void *)0x20000;
g_bdev_ut_channel->expected_iov[1].iov_len = 512;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 2);
ut_expected_io_set_iov(expected_io, 0, (void *)0x10000, 512);
ut_expected_io_set_iov(expected_io, 1, (void *)0x20000, 512);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
rc = spdk_bdev_writev_blocks(desc, io_ch, iov, 3, 14, 32, io_done, NULL);
CU_ASSERT(rc == 0);
CU_ASSERT(g_io_done == false);
g_bdev_ut_channel->expected_offset = 16;
g_bdev_ut_channel->expected_length = 16;
g_bdev_ut_channel->expected_iovcnt = 1;
g_bdev_ut_channel->expected_iov[0].iov_base = (void *)(0x20000 + 512);
g_bdev_ut_channel->expected_iov[0].iov_len = 16 * 512;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 16, 1);
ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 512), 16 * 512);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1);
stub_complete_io(1);
CU_ASSERT(g_io_done == false);
g_bdev_ut_channel->expected_offset = 32;
g_bdev_ut_channel->expected_length = 14;
g_bdev_ut_channel->expected_iovcnt = 2;
g_bdev_ut_channel->expected_iov[0].iov_base = (void *)(0x20000 + 17 * 512);
g_bdev_ut_channel->expected_iov[0].iov_len = 3 * 512;
g_bdev_ut_channel->expected_iov[1].iov_base = (void *)0x30000;
g_bdev_ut_channel->expected_iov[1].iov_len = 11 * 512;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 2);
ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 17 * 512), 3 * 512);
ut_expected_io_set_iov(expected_io, 1, (void *)0x30000, 11 * 512);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1);
stub_complete_io(1);
@ -931,27 +955,25 @@ bdev_io_split(void)
bdev->optimal_io_boundary = BDEV_IO_NUM_CHILD_IOV;
g_io_done = false;
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_READ;
g_bdev_ut_channel->expected_offset = 0;
g_bdev_ut_channel->expected_length = BDEV_IO_NUM_CHILD_IOV;
g_bdev_ut_channel->expected_iovcnt = BDEV_IO_NUM_CHILD_IOV;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, BDEV_IO_NUM_CHILD_IOV,
BDEV_IO_NUM_CHILD_IOV);
for (i = 0; i < BDEV_IO_NUM_CHILD_IOV; i++) {
g_bdev_ut_channel->expected_iov[i].iov_base = (void *)((i + 1) * 0x10000);
g_bdev_ut_channel->expected_iov[i].iov_len = 512;
ut_expected_io_set_iov(expected_io, i, (void *)((i + 1) * 0x10000), 512);
}
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
rc = spdk_bdev_readv_blocks(desc, io_ch, iov, BDEV_IO_NUM_CHILD_IOV * 2, 0,
BDEV_IO_NUM_CHILD_IOV * 2, io_done, NULL);
CU_ASSERT(rc == 0);
CU_ASSERT(g_io_done == false);
g_bdev_ut_channel->expected_offset = BDEV_IO_NUM_CHILD_IOV;
g_bdev_ut_channel->expected_length = BDEV_IO_NUM_CHILD_IOV;
g_bdev_ut_channel->expected_iovcnt = BDEV_IO_NUM_CHILD_IOV;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, BDEV_IO_NUM_CHILD_IOV,
BDEV_IO_NUM_CHILD_IOV, BDEV_IO_NUM_CHILD_IOV);
for (i = 0; i < BDEV_IO_NUM_CHILD_IOV; i++) {
g_bdev_ut_channel->expected_iov[i].iov_base = (void *)((i + 1 + BDEV_IO_NUM_CHILD_IOV) * 0x10000);
g_bdev_ut_channel->expected_iov[i].iov_len = 512;
ut_expected_io_set_iov(expected_io, i,
(void *)((i + 1 + BDEV_IO_NUM_CHILD_IOV) * 0x10000), 512);
}
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1);
stub_complete_io(1);
@ -987,10 +1009,8 @@ bdev_io_split(void)
*/
bdev->optimal_io_boundary = 15;
g_io_done = false;
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_WRITE_ZEROES;
g_bdev_ut_channel->expected_offset = 9;
g_bdev_ut_channel->expected_length = 36;
g_bdev_ut_channel->expected_iovcnt = 0;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, 9, 36, 0);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
rc = spdk_bdev_write_zeroes_blocks(desc, io_ch, 9, 36, io_done, NULL);
CU_ASSERT(rc == 0);
@ -1002,10 +1022,8 @@ bdev_io_split(void)
/* Test an UNMAP. This should also not be split. */
bdev->optimal_io_boundary = 16;
g_io_done = false;
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_UNMAP;
g_bdev_ut_channel->expected_offset = 15;
g_bdev_ut_channel->expected_length = 2;
g_bdev_ut_channel->expected_iovcnt = 0;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_UNMAP, 15, 2, 0);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
rc = spdk_bdev_unmap_blocks(desc, io_ch, 15, 2, io_done, NULL);
CU_ASSERT(rc == 0);
@ -1017,10 +1035,8 @@ bdev_io_split(void)
/* Test a FLUSH. This should also not be split. */
bdev->optimal_io_boundary = 16;
g_io_done = false;
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_FLUSH;
g_bdev_ut_channel->expected_offset = 15;
g_bdev_ut_channel->expected_length = 2;
g_bdev_ut_channel->expected_iovcnt = 0;
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_FLUSH, 15, 2, 0);
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
rc = spdk_bdev_flush_blocks(desc, io_ch, 15, 2, io_done, NULL);
CU_ASSERT(rc == 0);
@ -1029,11 +1045,7 @@ bdev_io_split(void)
stub_complete_io(1);
CU_ASSERT(g_io_done == true);
/* Reset values so next test is not affected by leftover values. */
g_bdev_ut_channel->expected_iotype = SPDK_BDEV_IO_TYPE_INVALID;
g_bdev_ut_channel->expected_offset = 0;
g_bdev_ut_channel->expected_length = 0;
g_bdev_ut_channel->expected_iovcnt = 0;
CU_ASSERT(TAILQ_EMPTY(&g_bdev_ut_channel->expected_io));
spdk_put_io_channel(io_ch);
spdk_bdev_close(desc);