diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 4eb954ad6..f40787dfc 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -1809,6 +1809,175 @@ blob_operation_split_rw(void) free(payload_pattern); } +static void +blob_operation_split_rw_iov(void) +{ + struct spdk_blob_store *bs; + struct spdk_bs_dev *dev; + struct spdk_blob *blob; + struct spdk_io_channel *channel; + struct spdk_blob_opts opts; + spdk_blob_id blobid; + uint64_t cluster_size; + + uint64_t payload_size; + uint8_t *payload_read; + uint8_t *payload_write; + uint8_t *payload_pattern; + + uint64_t page_size; + uint64_t pages_per_cluster; + uint64_t pages_per_payload; + + struct iovec iov_read[2]; + struct iovec iov_write[2]; + + uint64_t i; + + dev = init_dev(); + + spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + bs = g_bs; + + cluster_size = spdk_bs_get_cluster_size(bs); + page_size = spdk_bs_get_page_size(bs); + pages_per_cluster = cluster_size / page_size; + pages_per_payload = pages_per_cluster * 5; + payload_size = cluster_size * 5; + + payload_read = malloc(payload_size); + SPDK_CU_ASSERT_FATAL(payload_read != NULL); + + payload_write = malloc(payload_size); + SPDK_CU_ASSERT_FATAL(payload_write != NULL); + + payload_pattern = malloc(payload_size); + SPDK_CU_ASSERT_FATAL(payload_pattern != NULL); + + /* Prepare random pattern to write */ + for (i = 0; i < pages_per_payload; i++) { + *((uint64_t *)(payload_pattern + page_size * i)) = (i + 1); + } + + channel = spdk_bs_alloc_io_channel(bs); + SPDK_CU_ASSERT_FATAL(channel != NULL); + + /* Create blob */ + spdk_blob_opts_init(&opts); + opts.thin_provision = false; + opts.num_clusters = 5; + + spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); + blobid = g_blobid; + + spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_blob != NULL); + blob = g_blob; + + CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); + + /* Initial read should return zeroes payload */ + memset(payload_read, 0xFF, payload_size); + iov_read[0].iov_base = payload_read; + iov_read[0].iov_len = cluster_size * 3; + iov_read[1].iov_base = payload_read + cluster_size * 3; + iov_read[1].iov_len = cluster_size * 2; + spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(spdk_mem_all_zero(payload_read, payload_size)); + + /* First of iovs fills whole blob except last page and second of iovs writes last page + * with a pattern. */ + iov_write[0].iov_base = payload_pattern; + iov_write[0].iov_len = payload_size - page_size; + iov_write[1].iov_base = payload_pattern; + iov_write[1].iov_len = page_size; + spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + /* Read whole blob and check consistency */ + memset(payload_read, 0xFF, payload_size); + iov_read[0].iov_base = payload_read; + iov_read[0].iov_len = cluster_size * 2; + iov_read[1].iov_base = payload_read + cluster_size * 2; + iov_read[1].iov_len = cluster_size * 3; + spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size - page_size) == 0); + CU_ASSERT(memcmp(payload_pattern, payload_read + payload_size - page_size, page_size) == 0); + + /* First of iovs fills only first page and second of iovs writes whole blob except + * first page with a pattern. */ + iov_write[0].iov_base = payload_pattern; + iov_write[0].iov_len = page_size; + iov_write[1].iov_base = payload_pattern; + iov_write[1].iov_len = payload_size - page_size; + spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + /* Read whole blob and check consistency */ + memset(payload_read, 0xFF, payload_size); + iov_read[0].iov_base = payload_read; + iov_read[0].iov_len = cluster_size * 4; + iov_read[1].iov_base = payload_read + cluster_size * 4; + iov_read[1].iov_len = cluster_size; + spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(memcmp(payload_pattern, payload_read + page_size, payload_size - page_size) == 0); + CU_ASSERT(memcmp(payload_pattern, payload_read, page_size) == 0); + + + /* Fill whole blob with a pattern (5 clusters) */ + + /* 1. Read test. */ + _blob_io_write_no_split(blob, channel, payload_pattern, 0, pages_per_payload, + blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + memset(payload_read, 0xFF, payload_size); + iov_read[0].iov_base = payload_read; + iov_read[0].iov_len = cluster_size; + iov_read[1].iov_base = payload_read + cluster_size; + iov_read[1].iov_len = cluster_size * 4; + spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0); + + /* 2. Write test. */ + iov_write[0].iov_base = payload_read; + iov_write[0].iov_len = cluster_size * 2; + iov_write[1].iov_base = payload_read + cluster_size * 2; + iov_write[1].iov_len = cluster_size * 3; + spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + memset(payload_read, 0xFF, payload_size); + _blob_io_read_no_split(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0); + + spdk_blob_close(blob, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + spdk_bs_free_io_channel(channel); + + /* Unload the blob store */ + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + g_blob = NULL; + g_blobid = 0; + + free(payload_read); + free(payload_write); + free(payload_pattern); +} + static void blob_unmap(void) { @@ -4993,7 +5162,8 @@ int main(int argc, char **argv) CU_add_test(suite, "blob_relations", blob_relations) == NULL || CU_add_test(suite, "blob_inflate_rw", blob_inflate_rw) == NULL || CU_add_test(suite, "blob_snapshot_freeze_io", blob_snapshot_freeze_io) == NULL || - CU_add_test(suite, "blob_operation_split_rw", blob_operation_split_rw) == NULL + CU_add_test(suite, "blob_operation_split_rw", blob_operation_split_rw) == NULL || + CU_add_test(suite, "blob_operation_split_rw_iov", blob_operation_split_rw_iov) == NULL ) { CU_cleanup_registry(); return CU_get_error();