1a6dbe372Spaul luse /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2022 Intel Corporation.
3a6dbe372Spaul luse * All rights reserved.
4a6dbe372Spaul luse */
5a6dbe372Spaul luse
664eebbd1Syupeng #include "spdk/stdinc.h"
7ae431e31SKonrad Sztyber #include "spdk_internal/cunit.h"
864eebbd1Syupeng #include "spdk/env.h"
964eebbd1Syupeng
1059d79ec5SArtur Paszkiewicz #include "common/lib/ut_multithread.c"
1159d79ec5SArtur Paszkiewicz
1264eebbd1Syupeng #include "bdev/raid/concat.c"
131ec4c2eeSKrzysztof Smolinski #include "../common.c"
1464eebbd1Syupeng
15ba460005SKrzysztof Smolinski DEFINE_STUB(spdk_bdev_readv_blocks_with_md, int, (struct spdk_bdev_desc *desc,
16ba460005SKrzysztof Smolinski struct spdk_io_channel *ch,
17ba460005SKrzysztof Smolinski struct iovec *iov, int iovcnt, void *md,
18ba460005SKrzysztof Smolinski uint64_t offset_blocks, uint64_t num_blocks,
19ba460005SKrzysztof Smolinski spdk_bdev_io_completion_cb cb, void *cb_arg), 0);
20ba460005SKrzysztof Smolinski DEFINE_STUB(spdk_bdev_writev_blocks_with_md, int, (struct spdk_bdev_desc *desc,
21ba460005SKrzysztof Smolinski struct spdk_io_channel *ch,
22ba460005SKrzysztof Smolinski struct iovec *iov, int iovcnt, void *md,
23ba460005SKrzysztof Smolinski uint64_t offset_blocks, uint64_t num_blocks,
24ba460005SKrzysztof Smolinski spdk_bdev_io_completion_cb cb, void *cb_arg), 0);
25*1b9c5629SArtur Paszkiewicz DEFINE_STUB(raid_bdev_remap_dix_reftag, int, (void *md_buf, uint64_t num_blocks,
26*1b9c5629SArtur Paszkiewicz struct spdk_bdev *bdev, uint32_t remapped_offset), -1);
27ba460005SKrzysztof Smolinski
2864eebbd1Syupeng #define BLOCK_LEN (4096)
2964eebbd1Syupeng
3064eebbd1Syupeng enum CONCAT_IO_TYPE {
3164eebbd1Syupeng CONCAT_NONE = 0,
3264eebbd1Syupeng CONCAT_WRITEV,
3364eebbd1Syupeng CONCAT_READV,
3464eebbd1Syupeng CONCAT_FLUSH,
3564eebbd1Syupeng CONCAT_UNMAP,
3664eebbd1Syupeng };
3764eebbd1Syupeng
3864eebbd1Syupeng #define MAX_RECORDS (10)
3964eebbd1Syupeng /*
4064eebbd1Syupeng * Store the information of io requests sent to the underlying bdevs.
4164eebbd1Syupeng * For a single null payload request to the concat bdev,
4264eebbd1Syupeng * we may send multiple requests to the underling bdevs,
4364eebbd1Syupeng * so we store the io request information to arrays.
4464eebbd1Syupeng */
4564eebbd1Syupeng struct req_records {
4664eebbd1Syupeng uint64_t offset_blocks[MAX_RECORDS];
4764eebbd1Syupeng uint64_t num_blocks[MAX_RECORDS];
4864eebbd1Syupeng enum CONCAT_IO_TYPE io_type[MAX_RECORDS];
4964eebbd1Syupeng int count;
50256bfe76Syidong0635 void *md;
5164eebbd1Syupeng } g_req_records;
5264eebbd1Syupeng
5364eebbd1Syupeng /*
5464eebbd1Syupeng * g_succeed is true means the spdk_bdev_readv/writev/unmap/flush_blocks
5564eebbd1Syupeng * functions will return 0.
5664eebbd1Syupeng * g_succeed is false means the spdk_bdev_readv/writev/unmap/flush_blocks
5764eebbd1Syupeng * functions will return -ENOMEM.
5864eebbd1Syupeng * We always set it to false before an IO request, then the raid_bdev_queue_io_wait
5964eebbd1Syupeng * function will re-submit the request, and the raid_bdev_queue_io_wait function will
6064eebbd1Syupeng * set g_succeed to true, then the IO will succeed next time.
6164eebbd1Syupeng */
6264eebbd1Syupeng bool g_succeed;
6364eebbd1Syupeng
6464eebbd1Syupeng DEFINE_STUB_V(raid_bdev_module_list_add, (struct raid_bdev_module *raid_module));
6564eebbd1Syupeng DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *bdev_io));
6664eebbd1Syupeng
6764eebbd1Syupeng int
spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,struct iovec * iov,int iovcnt,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg,struct spdk_bdev_ext_io_opts * opts)68256bfe76Syidong0635 spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
6964eebbd1Syupeng struct iovec *iov, int iovcnt, uint64_t offset_blocks, uint64_t num_blocks,
70256bfe76Syidong0635 spdk_bdev_io_completion_cb cb, void *cb_arg, struct spdk_bdev_ext_io_opts *opts)
7164eebbd1Syupeng {
7264eebbd1Syupeng if (g_succeed) {
7364eebbd1Syupeng int i = g_req_records.count;
7464eebbd1Syupeng
7564eebbd1Syupeng g_req_records.offset_blocks[i] = offset_blocks;
7664eebbd1Syupeng g_req_records.num_blocks[i] = num_blocks;
7764eebbd1Syupeng g_req_records.io_type[i] = CONCAT_READV;
7864eebbd1Syupeng g_req_records.count++;
7964eebbd1Syupeng cb(NULL, true, cb_arg);
80256bfe76Syidong0635 g_req_records.md = opts->metadata;
8164eebbd1Syupeng return 0;
8264eebbd1Syupeng } else {
8364eebbd1Syupeng return -ENOMEM;
8464eebbd1Syupeng }
8564eebbd1Syupeng }
8664eebbd1Syupeng
8764eebbd1Syupeng int
spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,struct iovec * iov,int iovcnt,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg,struct spdk_bdev_ext_io_opts * opts)88256bfe76Syidong0635 spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
8964eebbd1Syupeng struct iovec *iov, int iovcnt, uint64_t offset_blocks, uint64_t num_blocks,
90256bfe76Syidong0635 spdk_bdev_io_completion_cb cb, void *cb_arg, struct spdk_bdev_ext_io_opts *opts)
9164eebbd1Syupeng {
9264eebbd1Syupeng if (g_succeed) {
9364eebbd1Syupeng int i = g_req_records.count;
9464eebbd1Syupeng
9564eebbd1Syupeng g_req_records.offset_blocks[i] = offset_blocks;
9664eebbd1Syupeng g_req_records.num_blocks[i] = num_blocks;
9764eebbd1Syupeng g_req_records.io_type[i] = CONCAT_WRITEV;
9864eebbd1Syupeng g_req_records.count++;
9964eebbd1Syupeng cb(NULL, true, cb_arg);
100256bfe76Syidong0635 g_req_records.md = opts->metadata;
10164eebbd1Syupeng return 0;
10264eebbd1Syupeng } else {
10364eebbd1Syupeng return -ENOMEM;
10464eebbd1Syupeng }
10564eebbd1Syupeng }
10664eebbd1Syupeng
10764eebbd1Syupeng int
spdk_bdev_unmap_blocks(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg)10864eebbd1Syupeng spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
10964eebbd1Syupeng uint64_t offset_blocks, uint64_t num_blocks,
11064eebbd1Syupeng spdk_bdev_io_completion_cb cb, void *cb_arg)
11164eebbd1Syupeng {
11264eebbd1Syupeng if (g_succeed) {
11364eebbd1Syupeng int i = g_req_records.count;
11464eebbd1Syupeng
11564eebbd1Syupeng g_req_records.offset_blocks[i] = offset_blocks;
11664eebbd1Syupeng g_req_records.num_blocks[i] = num_blocks;
11764eebbd1Syupeng g_req_records.io_type[i] = CONCAT_UNMAP;
11864eebbd1Syupeng g_req_records.count++;
11964eebbd1Syupeng cb(NULL, true, cb_arg);
12064eebbd1Syupeng return 0;
12164eebbd1Syupeng } else {
12264eebbd1Syupeng return -ENOMEM;
12364eebbd1Syupeng }
12464eebbd1Syupeng }
12564eebbd1Syupeng
12664eebbd1Syupeng int
spdk_bdev_flush_blocks(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg)12764eebbd1Syupeng spdk_bdev_flush_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
12864eebbd1Syupeng uint64_t offset_blocks, uint64_t num_blocks,
12964eebbd1Syupeng spdk_bdev_io_completion_cb cb, void *cb_arg)
13064eebbd1Syupeng {
13164eebbd1Syupeng if (g_succeed) {
13264eebbd1Syupeng int i = g_req_records.count;
13364eebbd1Syupeng
13464eebbd1Syupeng g_req_records.offset_blocks[i] = offset_blocks;
13564eebbd1Syupeng g_req_records.num_blocks[i] = num_blocks;
13664eebbd1Syupeng g_req_records.io_type[i] = CONCAT_FLUSH;
13764eebbd1Syupeng g_req_records.count++;
13864eebbd1Syupeng cb(NULL, true, cb_arg);
13964eebbd1Syupeng return 0;
14064eebbd1Syupeng } else {
14164eebbd1Syupeng return -ENOMEM;
14264eebbd1Syupeng }
14364eebbd1Syupeng }
14464eebbd1Syupeng
14564eebbd1Syupeng void
raid_bdev_queue_io_wait(struct raid_bdev_io * raid_io,struct spdk_bdev * bdev,struct spdk_io_channel * ch,spdk_bdev_io_wait_cb cb_fn)14664eebbd1Syupeng raid_bdev_queue_io_wait(struct raid_bdev_io *raid_io, struct spdk_bdev *bdev,
14764eebbd1Syupeng struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn)
14864eebbd1Syupeng {
14964eebbd1Syupeng g_succeed = true;
15064eebbd1Syupeng cb_fn(raid_io);
15164eebbd1Syupeng }
15264eebbd1Syupeng
153fc3c9b37SArtur Paszkiewicz void
raid_test_bdev_io_complete(struct raid_bdev_io * raid_io,enum spdk_bdev_io_status status)154a4e1703eSArtur Paszkiewicz raid_test_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status)
155a4e1703eSArtur Paszkiewicz {
156a4e1703eSArtur Paszkiewicz CU_ASSERT(status == SPDK_BDEV_IO_STATUS_SUCCESS);
157a4e1703eSArtur Paszkiewicz }
158a4e1703eSArtur Paszkiewicz
159a4e1703eSArtur Paszkiewicz static void
init_globals(void)16064eebbd1Syupeng init_globals(void)
16164eebbd1Syupeng {
16264eebbd1Syupeng int i;
16364eebbd1Syupeng
16464eebbd1Syupeng for (i = 0; i < MAX_RECORDS; i++) {
16564eebbd1Syupeng g_req_records.offset_blocks[i] = 0;
16664eebbd1Syupeng g_req_records.num_blocks[i] = 0;
16764eebbd1Syupeng g_req_records.io_type[i] = CONCAT_NONE;
16864eebbd1Syupeng }
16964eebbd1Syupeng g_req_records.count = 0;
17064eebbd1Syupeng g_succeed = false;
17164eebbd1Syupeng }
17264eebbd1Syupeng
17364eebbd1Syupeng static int
test_setup(void)17464eebbd1Syupeng test_setup(void)
17564eebbd1Syupeng {
17664eebbd1Syupeng uint8_t num_base_bdevs_values[] = { 3, 4, 5 };
17764eebbd1Syupeng uint64_t base_bdev_blockcnt_values[] = { 1, 1024, 1024 * 1024 };
17864eebbd1Syupeng uint32_t base_bdev_blocklen_values[] = { 512, 4096 };
17964eebbd1Syupeng uint32_t strip_size_kb_values[] = { 1, 4, 128 };
18064eebbd1Syupeng uint8_t *num_base_bdevs;
18164eebbd1Syupeng uint64_t *base_bdev_blockcnt;
18264eebbd1Syupeng uint32_t *base_bdev_blocklen;
18364eebbd1Syupeng uint32_t *strip_size_kb;
1841ec4c2eeSKrzysztof Smolinski uint64_t params_count;
1851ec4c2eeSKrzysztof Smolinski int rc;
18664eebbd1Syupeng
1871ec4c2eeSKrzysztof Smolinski params_count = SPDK_COUNTOF(num_base_bdevs_values) *
18864eebbd1Syupeng SPDK_COUNTOF(base_bdev_blockcnt_values) *
18964eebbd1Syupeng SPDK_COUNTOF(base_bdev_blocklen_values) *
19064eebbd1Syupeng SPDK_COUNTOF(strip_size_kb_values);
1911ec4c2eeSKrzysztof Smolinski rc = raid_test_params_alloc(params_count);
1921ec4c2eeSKrzysztof Smolinski if (rc) {
1931ec4c2eeSKrzysztof Smolinski return rc;
19464eebbd1Syupeng }
19564eebbd1Syupeng
19664eebbd1Syupeng ARRAY_FOR_EACH(num_base_bdevs_values, num_base_bdevs) {
19764eebbd1Syupeng ARRAY_FOR_EACH(base_bdev_blockcnt_values, base_bdev_blockcnt) {
19864eebbd1Syupeng ARRAY_FOR_EACH(base_bdev_blocklen_values, base_bdev_blocklen) {
19964eebbd1Syupeng ARRAY_FOR_EACH(strip_size_kb_values, strip_size_kb) {
20099537401SArtur Paszkiewicz struct raid_params params = {
20199537401SArtur Paszkiewicz .num_base_bdevs = *num_base_bdevs,
20299537401SArtur Paszkiewicz .base_bdev_blockcnt = *base_bdev_blockcnt,
20399537401SArtur Paszkiewicz .base_bdev_blocklen = *base_bdev_blocklen,
20499537401SArtur Paszkiewicz .strip_size = *strip_size_kb * 1024 / *base_bdev_blocklen,
20599537401SArtur Paszkiewicz };
2061ec4c2eeSKrzysztof Smolinski if (params.strip_size == 0 ||
20799537401SArtur Paszkiewicz params.strip_size > params.base_bdev_blockcnt) {
20864eebbd1Syupeng continue;
20964eebbd1Syupeng }
2101ec4c2eeSKrzysztof Smolinski raid_test_params_add(¶ms);
21164eebbd1Syupeng }
21264eebbd1Syupeng }
21364eebbd1Syupeng }
21464eebbd1Syupeng }
21564eebbd1Syupeng
21664eebbd1Syupeng return 0;
21764eebbd1Syupeng }
21864eebbd1Syupeng
21964eebbd1Syupeng static int
test_cleanup(void)22064eebbd1Syupeng test_cleanup(void)
22164eebbd1Syupeng {
2221ec4c2eeSKrzysztof Smolinski raid_test_params_free();
22364eebbd1Syupeng return 0;
22464eebbd1Syupeng }
22564eebbd1Syupeng
22664eebbd1Syupeng static struct raid_bdev *
create_concat(struct raid_params * params)2271ec4c2eeSKrzysztof Smolinski create_concat(struct raid_params *params)
22864eebbd1Syupeng {
2291ec4c2eeSKrzysztof Smolinski struct raid_bdev *raid_bdev = raid_test_create_raid_bdev(params, &g_concat_module);
23064eebbd1Syupeng
23164eebbd1Syupeng CU_ASSERT(concat_start(raid_bdev) == 0);
23264eebbd1Syupeng return raid_bdev;
23364eebbd1Syupeng }
23464eebbd1Syupeng
23564eebbd1Syupeng static void
delete_concat(struct raid_bdev * raid_bdev)23664eebbd1Syupeng delete_concat(struct raid_bdev *raid_bdev)
23764eebbd1Syupeng {
23864eebbd1Syupeng concat_stop(raid_bdev);
2391ec4c2eeSKrzysztof Smolinski raid_test_delete_raid_bdev(raid_bdev);
24064eebbd1Syupeng }
24164eebbd1Syupeng
24264eebbd1Syupeng static void
test_concat_start(void)24364eebbd1Syupeng test_concat_start(void)
24464eebbd1Syupeng {
24564eebbd1Syupeng struct raid_bdev *raid_bdev;
2461ec4c2eeSKrzysztof Smolinski struct raid_params *params;
24764eebbd1Syupeng struct concat_block_range *block_range;
24864eebbd1Syupeng uint64_t total_blockcnt;
24964eebbd1Syupeng int i;
25064eebbd1Syupeng
2511ec4c2eeSKrzysztof Smolinski RAID_PARAMS_FOR_EACH(params) {
25264eebbd1Syupeng raid_bdev = create_concat(params);
25364eebbd1Syupeng block_range = raid_bdev->module_private;
25464eebbd1Syupeng total_blockcnt = 0;
25564eebbd1Syupeng for (i = 0; i < params->num_base_bdevs; i++) {
25664eebbd1Syupeng CU_ASSERT(block_range[i].start == total_blockcnt);
25764eebbd1Syupeng CU_ASSERT(block_range[i].length == params->base_bdev_blockcnt);
25864eebbd1Syupeng total_blockcnt += params->base_bdev_blockcnt;
25964eebbd1Syupeng }
26064eebbd1Syupeng delete_concat(raid_bdev);
26164eebbd1Syupeng }
26264eebbd1Syupeng }
26364eebbd1Syupeng
26464eebbd1Syupeng static void
raid_io_cleanup(struct raid_bdev_io * raid_io)265a4e1703eSArtur Paszkiewicz raid_io_cleanup(struct raid_bdev_io *raid_io)
26664eebbd1Syupeng {
267a4e1703eSArtur Paszkiewicz if (raid_io->iovs) {
268a4e1703eSArtur Paszkiewicz free(raid_io->iovs->iov_base);
269a4e1703eSArtur Paszkiewicz free(raid_io->iovs);
27064eebbd1Syupeng }
271256bfe76Syidong0635
272a4e1703eSArtur Paszkiewicz free(raid_io);
27364eebbd1Syupeng }
27464eebbd1Syupeng
27564eebbd1Syupeng static void
raid_io_initialize(struct raid_bdev_io * raid_io,struct raid_bdev_io_channel * raid_ch,struct raid_bdev * raid_bdev,uint64_t lba,uint64_t blocks,int16_t iotype)276a4e1703eSArtur Paszkiewicz raid_io_initialize(struct raid_bdev_io *raid_io, struct raid_bdev_io_channel *raid_ch,
277a4e1703eSArtur Paszkiewicz struct raid_bdev *raid_bdev, uint64_t lba, uint64_t blocks, int16_t iotype)
27864eebbd1Syupeng {
279a4e1703eSArtur Paszkiewicz struct iovec *iovs;
280a4e1703eSArtur Paszkiewicz int iovcnt;
281a4e1703eSArtur Paszkiewicz void *md_buf;
28264eebbd1Syupeng
283a4e1703eSArtur Paszkiewicz if (iotype == SPDK_BDEV_IO_TYPE_UNMAP || iotype == SPDK_BDEV_IO_TYPE_FLUSH) {
284a4e1703eSArtur Paszkiewicz iovs = NULL;
285a4e1703eSArtur Paszkiewicz iovcnt = 0;
286a4e1703eSArtur Paszkiewicz md_buf = NULL;
287a4e1703eSArtur Paszkiewicz } else {
288a4e1703eSArtur Paszkiewicz iovcnt = 1;
289a4e1703eSArtur Paszkiewicz iovs = calloc(iovcnt, sizeof(struct iovec));
290a4e1703eSArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(iovs != NULL);
291a4e1703eSArtur Paszkiewicz iovs->iov_len = raid_io->num_blocks * BLOCK_LEN;
292a4e1703eSArtur Paszkiewicz iovs->iov_base = calloc(1, iovs->iov_len);
293a4e1703eSArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(iovs->iov_base != NULL);
294a4e1703eSArtur Paszkiewicz md_buf = (void *)0xAEDFEBAC;
29564eebbd1Syupeng }
29664eebbd1Syupeng
297a4e1703eSArtur Paszkiewicz raid_test_bdev_io_init(raid_io, raid_bdev, raid_ch, iotype, lba, blocks, iovs, iovcnt, md_buf);
29864eebbd1Syupeng }
29964eebbd1Syupeng
30064eebbd1Syupeng static void
submit_and_verify_rw(enum CONCAT_IO_TYPE io_type,struct raid_params * params)3011ec4c2eeSKrzysztof Smolinski submit_and_verify_rw(enum CONCAT_IO_TYPE io_type, struct raid_params *params)
30264eebbd1Syupeng {
30364eebbd1Syupeng struct raid_bdev *raid_bdev;
30464eebbd1Syupeng struct raid_bdev_io *raid_io;
30564eebbd1Syupeng struct raid_bdev_io_channel *raid_ch;
30664eebbd1Syupeng uint64_t lba, blocks;
30764eebbd1Syupeng int i;
30864eebbd1Syupeng
30964eebbd1Syupeng lba = 0;
31064eebbd1Syupeng blocks = 1;
31164eebbd1Syupeng for (i = 0; i < params->num_base_bdevs; i++) {
31264eebbd1Syupeng init_globals();
31364eebbd1Syupeng raid_bdev = create_concat(params);
314a4e1703eSArtur Paszkiewicz raid_io = calloc(1, sizeof(*raid_io));
315a4e1703eSArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(raid_io != NULL);
31659d79ec5SArtur Paszkiewicz raid_ch = raid_test_create_io_channel(raid_bdev);
31764eebbd1Syupeng
31864eebbd1Syupeng switch (io_type) {
31964eebbd1Syupeng case CONCAT_WRITEV:
320a4e1703eSArtur Paszkiewicz raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, blocks, SPDK_BDEV_IO_TYPE_WRITE);
32164eebbd1Syupeng concat_submit_rw_request(raid_io);
32264eebbd1Syupeng break;
32364eebbd1Syupeng case CONCAT_READV:
324a4e1703eSArtur Paszkiewicz raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, blocks, SPDK_BDEV_IO_TYPE_READ);
32564eebbd1Syupeng concat_submit_rw_request(raid_io);
32664eebbd1Syupeng break;
32764eebbd1Syupeng case CONCAT_UNMAP:
328a4e1703eSArtur Paszkiewicz raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, blocks, SPDK_BDEV_IO_TYPE_UNMAP);
32964eebbd1Syupeng concat_submit_null_payload_request(raid_io);
33064eebbd1Syupeng break;
33164eebbd1Syupeng case CONCAT_FLUSH:
332a4e1703eSArtur Paszkiewicz raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, blocks, SPDK_BDEV_IO_TYPE_FLUSH);
33364eebbd1Syupeng concat_submit_null_payload_request(raid_io);
33464eebbd1Syupeng break;
33564eebbd1Syupeng default:
33664eebbd1Syupeng CU_ASSERT(false);
33764eebbd1Syupeng }
33864eebbd1Syupeng
33964eebbd1Syupeng /*
34064eebbd1Syupeng * We submit request to the first lba of each underlying device,
34164eebbd1Syupeng * so the offset of the underling device should always be 0.
34264eebbd1Syupeng */
34364eebbd1Syupeng CU_ASSERT(g_req_records.offset_blocks[0] == 0);
34464eebbd1Syupeng CU_ASSERT(g_req_records.num_blocks[0] == blocks);
34564eebbd1Syupeng CU_ASSERT(g_req_records.io_type[0] == io_type);
34664eebbd1Syupeng CU_ASSERT(g_req_records.count == 1);
347256bfe76Syidong0635 CU_ASSERT(g_req_records.md == (void *)0xAEDFEBAC);
348a4e1703eSArtur Paszkiewicz raid_io_cleanup(raid_io);
34959d79ec5SArtur Paszkiewicz raid_test_destroy_io_channel(raid_ch);
35064eebbd1Syupeng delete_concat(raid_bdev);
35164eebbd1Syupeng lba += params->base_bdev_blockcnt;
35264eebbd1Syupeng }
35364eebbd1Syupeng }
35464eebbd1Syupeng
35564eebbd1Syupeng static void
test_concat_rw(void)35664eebbd1Syupeng test_concat_rw(void)
35764eebbd1Syupeng {
3581ec4c2eeSKrzysztof Smolinski struct raid_params *params;
35964eebbd1Syupeng enum CONCAT_IO_TYPE io_type_list[] = {CONCAT_WRITEV, CONCAT_READV};
36064eebbd1Syupeng enum CONCAT_IO_TYPE io_type;
36164eebbd1Syupeng int i;
36264eebbd1Syupeng
3631ec4c2eeSKrzysztof Smolinski RAID_PARAMS_FOR_EACH(params) {
36464eebbd1Syupeng for (i = 0; i < 2; i ++) {
36564eebbd1Syupeng io_type = io_type_list[i];
36664eebbd1Syupeng submit_and_verify_rw(io_type, params);
36764eebbd1Syupeng }
36864eebbd1Syupeng }
36964eebbd1Syupeng }
37064eebbd1Syupeng
37164eebbd1Syupeng static void
submit_and_verify_null_payload(enum CONCAT_IO_TYPE io_type,struct raid_params * params)3721ec4c2eeSKrzysztof Smolinski submit_and_verify_null_payload(enum CONCAT_IO_TYPE io_type, struct raid_params *params)
37364eebbd1Syupeng {
37464eebbd1Syupeng struct raid_bdev *raid_bdev;
37564eebbd1Syupeng struct raid_bdev_io *raid_io;
37664eebbd1Syupeng struct raid_bdev_io_channel *raid_ch;
37764eebbd1Syupeng uint64_t lba, blocks;
37864eebbd1Syupeng
37964eebbd1Syupeng /*
38064eebbd1Syupeng * In this unittest, all base bdevs have the same blockcnt.
38164eebbd1Syupeng * If the base_bdev_blockcnt > 1, the request will start from
38264eebbd1Syupeng * the second bdev, and across two bdevs.
38364eebbd1Syupeng * If the base_bdev_blockcnt == 1, the request will start from
38464eebbd1Syupeng * the third bdev. In this case, if there are only 3 bdevs,
38564eebbd1Syupeng * we can not set blocks to base_bdev_blockcnt + 1 because the request
38664eebbd1Syupeng * will be beyond the end of the last bdev, so we set the blocks to 1
38764eebbd1Syupeng */
38864eebbd1Syupeng lba = params->base_bdev_blockcnt + 1;
38964eebbd1Syupeng if (params->base_bdev_blockcnt == 1 && params->num_base_bdevs == 3) {
39064eebbd1Syupeng blocks = 1;
39164eebbd1Syupeng } else {
39264eebbd1Syupeng blocks = params->base_bdev_blockcnt + 1;
39364eebbd1Syupeng }
39464eebbd1Syupeng init_globals();
39564eebbd1Syupeng raid_bdev = create_concat(params);
396a4e1703eSArtur Paszkiewicz raid_io = calloc(1, sizeof(*raid_io));
397a4e1703eSArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(raid_io != NULL);
39859d79ec5SArtur Paszkiewicz raid_ch = raid_test_create_io_channel(raid_bdev);
39964eebbd1Syupeng
40064eebbd1Syupeng switch (io_type) {
40164eebbd1Syupeng case CONCAT_UNMAP:
402a4e1703eSArtur Paszkiewicz raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, blocks, SPDK_BDEV_IO_TYPE_UNMAP);
40364eebbd1Syupeng concat_submit_null_payload_request(raid_io);
40464eebbd1Syupeng break;
40564eebbd1Syupeng case CONCAT_FLUSH:
406a4e1703eSArtur Paszkiewicz raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, blocks, SPDK_BDEV_IO_TYPE_FLUSH);
40764eebbd1Syupeng concat_submit_null_payload_request(raid_io);
40864eebbd1Syupeng break;
40964eebbd1Syupeng default:
41064eebbd1Syupeng CU_ASSERT(false);
41164eebbd1Syupeng }
41264eebbd1Syupeng
41364eebbd1Syupeng if (params->base_bdev_blockcnt == 1) {
41464eebbd1Syupeng if (params->num_base_bdevs == 3) {
41564eebbd1Syupeng CU_ASSERT(g_req_records.count == 1);
41664eebbd1Syupeng CU_ASSERT(g_req_records.offset_blocks[0] == 0);
41764eebbd1Syupeng CU_ASSERT(g_req_records.num_blocks[0] == 1);
41864eebbd1Syupeng } else {
41964eebbd1Syupeng CU_ASSERT(g_req_records.count == 2);
42064eebbd1Syupeng CU_ASSERT(g_req_records.offset_blocks[0] == 0);
42164eebbd1Syupeng CU_ASSERT(g_req_records.num_blocks[0] == 1);
42264eebbd1Syupeng CU_ASSERT(g_req_records.io_type[0] == io_type);
42364eebbd1Syupeng CU_ASSERT(g_req_records.offset_blocks[1] == 0);
42464eebbd1Syupeng CU_ASSERT(g_req_records.num_blocks[1] == 1);
42564eebbd1Syupeng CU_ASSERT(g_req_records.io_type[1] == io_type);
42664eebbd1Syupeng }
42764eebbd1Syupeng } else {
42864eebbd1Syupeng CU_ASSERT(g_req_records.count == 2);
42964eebbd1Syupeng CU_ASSERT(g_req_records.offset_blocks[0] == 1);
43064eebbd1Syupeng CU_ASSERT(g_req_records.num_blocks[0] == params->base_bdev_blockcnt - 1);
43164eebbd1Syupeng CU_ASSERT(g_req_records.io_type[0] == io_type);
43264eebbd1Syupeng CU_ASSERT(g_req_records.offset_blocks[1] == 0);
43364eebbd1Syupeng CU_ASSERT(g_req_records.num_blocks[1] == 2);
43464eebbd1Syupeng CU_ASSERT(g_req_records.io_type[1] == io_type);
43564eebbd1Syupeng }
436a4e1703eSArtur Paszkiewicz raid_io_cleanup(raid_io);
43759d79ec5SArtur Paszkiewicz raid_test_destroy_io_channel(raid_ch);
43864eebbd1Syupeng delete_concat(raid_bdev);
43964eebbd1Syupeng }
44064eebbd1Syupeng
44164eebbd1Syupeng static void
test_concat_null_payload(void)44264eebbd1Syupeng test_concat_null_payload(void)
44364eebbd1Syupeng {
4441ec4c2eeSKrzysztof Smolinski struct raid_params *params;
44564eebbd1Syupeng enum CONCAT_IO_TYPE io_type_list[] = {CONCAT_FLUSH, CONCAT_UNMAP};
44664eebbd1Syupeng enum CONCAT_IO_TYPE io_type;
44764eebbd1Syupeng int i;
44864eebbd1Syupeng
4491ec4c2eeSKrzysztof Smolinski RAID_PARAMS_FOR_EACH(params) {
45064eebbd1Syupeng for (i = 0; i < 2; i ++) {
45164eebbd1Syupeng io_type = io_type_list[i];
45264eebbd1Syupeng submit_and_verify_null_payload(io_type, params);
45364eebbd1Syupeng }
45464eebbd1Syupeng }
45564eebbd1Syupeng }
45664eebbd1Syupeng
45764eebbd1Syupeng int
main(int argc,char ** argv)45864eebbd1Syupeng main(int argc, char **argv)
45964eebbd1Syupeng {
46064eebbd1Syupeng CU_pSuite suite = NULL;
46164eebbd1Syupeng unsigned int num_failures;
46264eebbd1Syupeng
46364eebbd1Syupeng CU_initialize_registry();
46464eebbd1Syupeng
46564eebbd1Syupeng suite = CU_add_suite("concat", test_setup, test_cleanup);
46664eebbd1Syupeng CU_ADD_TEST(suite, test_concat_start);
46764eebbd1Syupeng CU_ADD_TEST(suite, test_concat_rw);
46864eebbd1Syupeng CU_ADD_TEST(suite, test_concat_null_payload);
46964eebbd1Syupeng
47059d79ec5SArtur Paszkiewicz allocate_threads(1);
47159d79ec5SArtur Paszkiewicz set_thread(0);
47259d79ec5SArtur Paszkiewicz
473ea941caeSKonrad Sztyber num_failures = spdk_ut_run_tests(argc, argv, NULL);
47464eebbd1Syupeng CU_cleanup_registry();
47559d79ec5SArtur Paszkiewicz
47659d79ec5SArtur Paszkiewicz free_threads();
47759d79ec5SArtur Paszkiewicz
47864eebbd1Syupeng return num_failures;
47964eebbd1Syupeng }
480