test/bdevio: fix bytes vs blocks => early return of test

blockdev_compare_and_write and blockdev_write_read check
if data_length is multiple of block size and silently
succeed if it is not. There are multiple test that test
e.g. invalid size but the actual bdev API is
never called and tested because of the early return.
The intend of this behavior presumably was to allow
to run test like e.g. the 512bytes rw test on a 4K
formatted namespace without failing. Instead of silently
succeeding which introduces the issues described this
patch changes all sizes to be multiple of block size and
removes the test for valid block size to let the
return value of the bdev API functions indicate failure like
intended. All previous 4k tests are now performing io of
1 block size. Previous 512byte tests now perform
8 * block size (to have 4k test size for 512byte formatted
namespaces). Write zeroes test are now using the
write zeroes buffer size instead of a hardcoded value
and align accordingly to block size io.
Furthermore, no cmp&write test is ever executed because
data_length is set to 1 trying to indicate 1 block but
it is tested against valid block bytes and silently
succeeded. Also write and read helpers in cmp&write test
expect bytes not blocks. For consistency use bytes in the
test and only convert to blocks when calling the cmp&write
blocks API.

Signed-off-by: Jonas Pfefferle <pepperjo@japf.ch>
Change-Id: I662094c2bcd08c0e9dc5573177a2e7a0edd275ce
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12382
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Jonas Pfefferle 2022-04-19 11:15:15 +02:00 committed by Jim Harris
parent 4e241cba01
commit a6e0224634

View File

@ -218,6 +218,15 @@ quick_test_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg)
wake_ut_thread();
}
static uint64_t
bdev_bytes_to_blocks(struct spdk_bdev *bdev, uint64_t bytes)
{
uint32_t block_size = spdk_bdev_get_block_size(bdev);
CU_ASSERT(bytes % block_size == 0);
return bytes / block_size;
}
static void
__blockdev_write(void *arg)
{
@ -259,10 +268,12 @@ __blockdev_compare_and_write(void *arg)
{
struct bdevio_request *req = arg;
struct io_target *target = req->target;
struct spdk_bdev *bdev = target->bdev;
int rc;
rc = spdk_bdev_comparev_and_writev_blocks(target->bdev_desc, target->ch, req->iov, req->iovcnt,
req->fused_iov, req->fused_iovcnt, req->offset, req->data_len, quick_test_complete, NULL);
req->fused_iov, req->fused_iovcnt, bdev_bytes_to_blocks(bdev, req->offset),
bdev_bytes_to_blocks(bdev, req->data_len), quick_test_complete, NULL);
if (rc) {
g_completion_success = false;
@ -425,18 +436,6 @@ blockdev_write_read_data_match(char *rx_buf, char *tx_buf, int data_length)
return rc;
}
static bool
blockdev_io_valid_blocks(struct spdk_bdev *bdev, uint64_t data_length)
{
if (data_length < spdk_bdev_get_block_size(bdev) ||
data_length % spdk_bdev_get_block_size(bdev) ||
data_length / spdk_bdev_get_block_size(bdev) > spdk_bdev_get_num_blocks(bdev)) {
return false;
}
return true;
}
static void
blockdev_write_read(uint32_t data_length, uint32_t iov_len, int pattern, uint64_t offset,
int expected_rc, bool write_zeroes)
@ -448,10 +447,6 @@ blockdev_write_read(uint32_t data_length, uint32_t iov_len, int pattern, uint64_
target = g_current_io_target;
if (!blockdev_io_valid_blocks(target->bdev, data_length)) {
return;
}
if (!write_zeroes) {
initialize_buffer(&tx_buf, pattern, data_length);
initialize_buffer(&rx_buf, 0, data_length);
@ -497,10 +492,6 @@ blockdev_compare_and_write(uint32_t data_length, uint32_t iov_len, uint64_t offs
target = g_current_io_target;
if (!blockdev_io_valid_blocks(target->bdev, data_length)) {
return;
}
initialize_buffer(&tx_buf, 0xAA, data_length);
initialize_buffer(&rx_buf, 0, data_length);
initialize_buffer(&write_buf, 0xBB, data_length);
@ -523,15 +514,17 @@ blockdev_compare_and_write(uint32_t data_length, uint32_t iov_len, uint64_t offs
}
static void
blockdev_write_read_4k(void)
blockdev_write_read_block(void)
{
uint32_t data_length;
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = 4K */
data_length = 4096;
/* Data size = 1 block */
data_length = spdk_bdev_get_block_size(bdev);
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 0;
pattern = 0xA3;
@ -543,15 +536,17 @@ blockdev_write_read_4k(void)
}
static void
blockdev_write_zeroes_read_4k(void)
blockdev_write_zeroes_read_block(void)
{
uint32_t data_length;
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = 4K */
data_length = 4096;
/* Data size = 1 block */
data_length = spdk_bdev_get_block_size(bdev);
offset = 0;
pattern = 0xA3;
/* Params are valid, hence the expected return value
@ -571,8 +566,12 @@ blockdev_write_zeroes_read_no_split(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = block size aligned ZERO_BUFFER_SIZE */
data_length = ZERO_BUFFER_SIZE; /* from bdev_internal.h */
data_length -= ZERO_BUFFER_SIZE % spdk_bdev_get_block_size(bdev);
offset = 0;
pattern = 0xA3;
/* Params are valid, hence the expected return value
@ -593,8 +592,12 @@ blockdev_write_zeroes_read_split(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = block size aligned 3 * ZERO_BUFFER_SIZE */
data_length = 3 * ZERO_BUFFER_SIZE; /* from bdev_internal.h */
data_length -= data_length % spdk_bdev_get_block_size(bdev);
offset = 0;
pattern = 0xA3;
/* Params are valid, hence the expected return value
@ -617,8 +620,13 @@ blockdev_write_zeroes_read_split_partial(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
uint32_t block_size = spdk_bdev_get_block_size(bdev);
/* Data size = block size aligned 7 * ZERO_BUFFER_SIZE / 2 */
data_length = ZERO_BUFFER_SIZE * 7 / 2;
data_length -= data_length % block_size;
offset = 0;
pattern = 0xA3;
/* Params are valid, hence the expected return value
@ -629,16 +637,18 @@ blockdev_write_zeroes_read_split_partial(void)
}
static void
blockdev_writev_readv_4k(void)
blockdev_writev_readv_block(void)
{
uint32_t data_length, iov_len;
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = 4K */
data_length = 4096;
iov_len = 4096;
/* Data size = 1 block */
data_length = spdk_bdev_get_block_size(bdev);
iov_len = data_length;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 0;
pattern = 0xA3;
@ -654,9 +664,12 @@ blockdev_comparev_and_writev(void)
{
uint32_t data_length, iov_len;
uint64_t offset;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
data_length = 1;
iov_len = 1;
/* Data size = acwu size */
data_length = spdk_bdev_get_block_size(bdev) * spdk_bdev_get_acwu(bdev);
iov_len = data_length;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 0;
@ -664,16 +677,19 @@ blockdev_comparev_and_writev(void)
}
static void
blockdev_writev_readv_30x4k(void)
blockdev_writev_readv_30x1block(void)
{
uint32_t data_length, iov_len;
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
uint32_t block_size = spdk_bdev_get_block_size(bdev);
/* Data size = 4K */
data_length = 4096 * 30;
iov_len = 4096;
/* Data size = 30 * block size */
data_length = block_size * 30;
iov_len = block_size;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 0;
pattern = 0xA3;
@ -685,17 +701,19 @@ blockdev_writev_readv_30x4k(void)
}
static void
blockdev_write_read_512Bytes(void)
blockdev_write_read_8blocks(void)
{
uint32_t data_length;
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = 512 */
data_length = 512;
/* Data size = 8 * block size */
data_length = spdk_bdev_get_block_size(bdev) * 8;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 8192;
offset = data_length;
pattern = 0xA3;
/* Params are valid, hence the expected return value
* of write and read for all blockdevs is 0. */
@ -705,18 +723,20 @@ blockdev_write_read_512Bytes(void)
}
static void
blockdev_writev_readv_512Bytes(void)
blockdev_writev_readv_8blocks(void)
{
uint32_t data_length, iov_len;
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = 512 */
data_length = 512;
iov_len = 512;
/* Data size = 8 * block size */
data_length = spdk_bdev_get_block_size(bdev) * 8;
iov_len = data_length;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 8192;
offset = data_length;
pattern = 0xA3;
/* Params are valid, hence the expected return value
* of write and read for all blockdevs is 0. */
@ -732,11 +752,16 @@ blockdev_write_read_size_gt_128k(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
uint32_t block_size = spdk_bdev_get_block_size(bdev);
/* Data size = 132K */
data_length = 135168;
/* Data size = block size aligned 128K + 1 block */
data_length = 128 * 1024;
data_length -= data_length % block_size;
data_length += block_size;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 8192;
offset = block_size * 2;
pattern = 0xA3;
/* Params are valid, hence the expected return value
* of write and read for all blockdevs is 0. */
@ -752,12 +777,17 @@ blockdev_writev_readv_size_gt_128k(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
uint32_t block_size = spdk_bdev_get_block_size(bdev);
/* Data size = 132K */
data_length = 135168;
iov_len = 135168;
/* Data size = block size aligned 128K + 1 block */
data_length = 128 * 1024;
data_length -= data_length % block_size;
data_length += block_size;
iov_len = data_length;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 8192;
offset = block_size * 2;
pattern = 0xA3;
/* Params are valid, hence the expected return value
* of write and read for all blockdevs is 0. */
@ -773,12 +803,17 @@ blockdev_writev_readv_size_gt_128k_two_iov(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
uint32_t block_size = spdk_bdev_get_block_size(bdev);
/* Data size = 132K */
data_length = 135168;
iov_len = 128 * 1024;
/* Data size = block size aligned 128K + 1 block */
data_length = 128 * 1024;
data_length -= data_length % block_size;
iov_len = data_length;
data_length += block_size;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 8192;
offset = block_size * 2;
pattern = 0xA3;
/* Params are valid, hence the expected return value
* of write and read for all blockdevs is 0. */
@ -794,11 +829,14 @@ blockdev_write_read_invalid_size(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
uint32_t block_size = spdk_bdev_get_block_size(bdev);
/* Data size is not a multiple of the block size */
data_length = 0x1015;
data_length = block_size - 1;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 8192;
offset = block_size * 2;
pattern = 0xA3;
/* Params are invalid, hence the expected return value
* of write and read for all blockdevs is < 0 */
@ -846,16 +884,17 @@ blockdev_write_read_offset_plus_nbytes_equals_bdev_size(void)
static void
blockdev_write_read_offset_plus_nbytes_gt_bdev_size(void)
{
struct io_target *target;
struct spdk_bdev *bdev;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
char *tx_buf = NULL;
char *rx_buf = NULL;
int data_length;
uint64_t offset;
int pattern;
uint32_t block_size = spdk_bdev_get_block_size(bdev);
/* Tests the overflow condition of the blockdevs. */
data_length = 4096;
data_length = block_size * 2;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
pattern = 0xA3;
@ -865,7 +904,7 @@ blockdev_write_read_offset_plus_nbytes_gt_bdev_size(void)
/* The start offset has been set to a valid value
* but offset + nbytes is greater than the Total size
* of the blockdev. The test should fail. */
offset = ((spdk_bdev_get_num_blocks(bdev) * spdk_bdev_get_block_size(bdev)) - 1024);
offset = (spdk_bdev_get_num_blocks(bdev) - 1) * block_size;
initialize_buffer(&tx_buf, pattern, data_length);
initialize_buffer(&rx_buf, 0, data_length);
@ -884,8 +923,10 @@ blockdev_write_read_max_offset(void)
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
data_length = 4096;
data_length = spdk_bdev_get_block_size(bdev);
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
/* The start offset has been set to UINT64_MAX such that
* adding nbytes wraps around and points to an invalid address. */
@ -899,15 +940,17 @@ blockdev_write_read_max_offset(void)
}
static void
blockdev_overlapped_write_read_8k(void)
blockdev_overlapped_write_read_2blocks(void)
{
int data_length;
uint64_t offset;
int pattern;
int expected_rc;
struct io_target *target = g_current_io_target;
struct spdk_bdev *bdev = target->bdev;
/* Data size = 8K */
data_length = 8192;
/* Data size = 2 blocks */
data_length = spdk_bdev_get_block_size(bdev) * 2;
CU_ASSERT_TRUE(data_length < BUFFER_SIZE);
offset = 0;
pattern = 0xA3;
@ -918,13 +961,13 @@ blockdev_overlapped_write_read_8k(void)
* from the same offset for each blockdev */
blockdev_write_read(data_length, 0, pattern, offset, expected_rc, 0);
/* Overwrite the pattern 0xbb of size 8K on an address offset overlapping
* with the address written above and assert the new value in
/* Overwrite the pattern 0xbb of size 2*block size on an address offset
* overlapping with the address written above and assert the new value in
* the overlapped address range */
/* Populate 8k with value 0xBB */
/* Populate 2*block size with value 0xBB */
pattern = 0xBB;
/* Offset = 6144; Overlap offset addresses and write value 0xbb */
offset = 4096;
/* Offset = 1 block; Overlap offset addresses and write value 0xbb */
offset = spdk_bdev_get_block_size(bdev);
/* Assert the write by comparing it with values read
* from the overlapped offset for each blockdev */
blockdev_write_read(data_length, 0, pattern, offset, expected_rc, 0);
@ -1171,17 +1214,20 @@ __setup_ut_on_single_target(struct io_target *target)
}
if (
CU_add_test(suite, "blockdev write read 4k", blockdev_write_read_4k) == NULL
|| CU_add_test(suite, "blockdev write zeroes read 4k", blockdev_write_zeroes_read_4k) == NULL
CU_add_test(suite, "blockdev write read block",
blockdev_write_read_block) == NULL
|| CU_add_test(suite, "blockdev write zeroes read block",
blockdev_write_zeroes_read_block) == NULL
|| CU_add_test(suite, "blockdev write zeroes read no split",
blockdev_write_zeroes_read_no_split) == NULL
|| CU_add_test(suite, "blockdev write zeroes read split", blockdev_write_zeroes_read_split) == NULL
|| CU_add_test(suite, "blockdev write zeroes read split",
blockdev_write_zeroes_read_split) == NULL
|| CU_add_test(suite, "blockdev write zeroes read split partial",
blockdev_write_zeroes_read_split_partial) == NULL
|| CU_add_test(suite, "blockdev reset",
blockdev_test_reset) == NULL
|| CU_add_test(suite, "blockdev write read 512 bytes",
blockdev_write_read_512Bytes) == NULL
|| CU_add_test(suite, "blockdev write read 8 blocks",
blockdev_write_read_8blocks) == NULL
|| CU_add_test(suite, "blockdev write read size > 128k",
blockdev_write_read_size_gt_128k) == NULL
|| CU_add_test(suite, "blockdev write read invalid size",
@ -1192,18 +1238,20 @@ __setup_ut_on_single_target(struct io_target *target)
blockdev_write_read_offset_plus_nbytes_gt_bdev_size) == NULL
|| CU_add_test(suite, "blockdev write read max offset",
blockdev_write_read_max_offset) == NULL
|| CU_add_test(suite, "blockdev write read 8k on overlapped address offset",
blockdev_overlapped_write_read_8k) == NULL
|| CU_add_test(suite, "blockdev writev readv 4k", blockdev_writev_readv_4k) == NULL
|| CU_add_test(suite, "blockdev writev readv 30 x 4k",
blockdev_writev_readv_30x4k) == NULL
|| CU_add_test(suite, "blockdev writev readv 512 bytes",
blockdev_writev_readv_512Bytes) == NULL
|| CU_add_test(suite, "blockdev write read 2 blocks on overlapped address offset",
blockdev_overlapped_write_read_2blocks) == NULL
|| CU_add_test(suite, "blockdev writev readv 8 blocks",
blockdev_writev_readv_8blocks) == NULL
|| CU_add_test(suite, "blockdev writev readv 30 x 1block",
blockdev_writev_readv_30x1block) == NULL
|| CU_add_test(suite, "blockdev writev readv block",
blockdev_writev_readv_block) == NULL
|| CU_add_test(suite, "blockdev writev readv size > 128k",
blockdev_writev_readv_size_gt_128k) == NULL
|| CU_add_test(suite, "blockdev writev readv size > 128k in two iovs",
blockdev_writev_readv_size_gt_128k_two_iov) == NULL
|| CU_add_test(suite, "blockdev comparev and writev", blockdev_comparev_and_writev) == NULL
|| CU_add_test(suite, "blockdev comparev and writev",
blockdev_comparev_and_writev) == NULL
|| CU_add_test(suite, "blockdev nvme passthru rw",
blockdev_test_nvme_passthru_rw) == NULL
|| CU_add_test(suite, "blockdev nvme passthru vendor specific",