14ee51dcbSJim Harris /*- 24ee51dcbSJim Harris * BSD LICENSE 34ee51dcbSJim Harris * 4437e54f7SEvgeniy Kochetov * Copyright (c) Intel Corporation. All rights reserved. 5437e54f7SEvgeniy Kochetov * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved. 64ee51dcbSJim Harris * 74ee51dcbSJim Harris * Redistribution and use in source and binary forms, with or without 84ee51dcbSJim Harris * modification, are permitted provided that the following conditions 94ee51dcbSJim Harris * are met: 104ee51dcbSJim Harris * 114ee51dcbSJim Harris * * Redistributions of source code must retain the above copyright 124ee51dcbSJim Harris * notice, this list of conditions and the following disclaimer. 134ee51dcbSJim Harris * * Redistributions in binary form must reproduce the above copyright 144ee51dcbSJim Harris * notice, this list of conditions and the following disclaimer in 154ee51dcbSJim Harris * the documentation and/or other materials provided with the 164ee51dcbSJim Harris * distribution. 174ee51dcbSJim Harris * * Neither the name of Intel Corporation nor the names of its 184ee51dcbSJim Harris * contributors may be used to endorse or promote products derived 194ee51dcbSJim Harris * from this software without specific prior written permission. 204ee51dcbSJim Harris * 214ee51dcbSJim Harris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 224ee51dcbSJim Harris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 234ee51dcbSJim Harris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 244ee51dcbSJim Harris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 254ee51dcbSJim Harris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 264ee51dcbSJim Harris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 274ee51dcbSJim Harris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 284ee51dcbSJim Harris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 294ee51dcbSJim Harris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 304ee51dcbSJim Harris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 314ee51dcbSJim Harris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 324ee51dcbSJim Harris */ 334ee51dcbSJim Harris 344ee51dcbSJim Harris #include "spdk_cunit.h" 354ee51dcbSJim Harris 36270a25dfSBen Walker #include "common/lib/ut_multithread.c" 375ffa5c00SPawel Wodkowski #include "unit/lib/json_mock.c" 38229f6494SDaniel Verkamp 39c4fee1e9SPawel Wodkowski #include "spdk/config.h" 40229f6494SDaniel Verkamp /* HACK: disable VTune integration so the unit test doesn't need VTune headers and libs to build */ 41229f6494SDaniel Verkamp #undef SPDK_CONFIG_VTUNE 42229f6494SDaniel Verkamp 43d8c3ff5fSJim Harris #include "bdev/bdev.c" 444ee51dcbSJim Harris 45afaabcceSJim Harris struct spdk_trace_histories *g_trace_histories; 46afaabcceSJim Harris DEFINE_STUB_V(spdk_trace_add_register_fn, (struct spdk_trace_register_fn *reg_fn)); 47afaabcceSJim Harris DEFINE_STUB_V(spdk_trace_register_owner, (uint8_t type, char id_prefix)); 48afaabcceSJim Harris DEFINE_STUB_V(spdk_trace_register_object, (uint8_t type, char id_prefix)); 49617184beSJim Harris DEFINE_STUB_V(spdk_trace_register_description, (const char *name, 50afaabcceSJim Harris uint16_t tpoint_id, uint8_t owner_type, 51afaabcceSJim Harris uint8_t object_type, uint8_t new_object, 52dd1c38ccSJim Harris uint8_t arg1_type, const char *arg1_name)); 53afaabcceSJim Harris DEFINE_STUB_V(_spdk_trace_record, (uint64_t tsc, uint16_t tpoint_id, uint16_t poller_id, 54afaabcceSJim Harris uint32_t size, uint64_t object_id, uint64_t arg1)); 551d83a09dSPiotr Pelplinski DEFINE_STUB(spdk_notify_send, uint64_t, (const char *type, const char *ctx), 0); 561d83a09dSPiotr Pelplinski DEFINE_STUB(spdk_notify_type_register, struct spdk_notify_type *, (const char *type), NULL); 571d83a09dSPiotr Pelplinski 58afaabcceSJim Harris 5942dba604SPiotr Pelplinski int g_status; 6042dba604SPiotr Pelplinski int g_count; 6179ed1ba1SMaciej Szwed enum spdk_bdev_event_type g_event_type1; 6279ed1ba1SMaciej Szwed enum spdk_bdev_event_type g_event_type2; 6342dba604SPiotr Pelplinski struct spdk_histogram_data *g_histogram; 6423975858SEvgeniy Kochetov void *g_unregister_arg; 6523975858SEvgeniy Kochetov int g_unregister_rc; 6642dba604SPiotr Pelplinski 674ee51dcbSJim Harris void 684ee51dcbSJim Harris spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io, 694ee51dcbSJim Harris int *sc, int *sk, int *asc, int *ascq) 704ee51dcbSJim Harris { 714ee51dcbSJim Harris } 724ee51dcbSJim Harris 734ee51dcbSJim Harris static int 744ee51dcbSJim Harris null_init(void) 754ee51dcbSJim Harris { 764ee51dcbSJim Harris return 0; 774ee51dcbSJim Harris } 784ee51dcbSJim Harris 794ee51dcbSJim Harris static int 804ee51dcbSJim Harris null_clean(void) 814ee51dcbSJim Harris { 824ee51dcbSJim Harris return 0; 834ee51dcbSJim Harris } 844ee51dcbSJim Harris 8557d174ffSJim Harris static int 8657d174ffSJim Harris stub_destruct(void *ctx) 874ee51dcbSJim Harris { 8857d174ffSJim Harris return 0; 8957d174ffSJim Harris } 9057d174ffSJim Harris 913c7894ffSShuhei Matsumoto struct ut_expected_io { 923c7894ffSShuhei Matsumoto uint8_t type; 933c7894ffSShuhei Matsumoto uint64_t offset; 943c7894ffSShuhei Matsumoto uint64_t length; 953c7894ffSShuhei Matsumoto int iovcnt; 963c7894ffSShuhei Matsumoto struct iovec iov[BDEV_IO_NUM_CHILD_IOV]; 97e2918289SKonrad Sztyber void *md_buf; 983c7894ffSShuhei Matsumoto TAILQ_ENTRY(ut_expected_io) link; 993c7894ffSShuhei Matsumoto }; 1003c7894ffSShuhei Matsumoto 10132d7c91cSJim Harris struct bdev_ut_channel { 10232d7c91cSJim Harris TAILQ_HEAD(, spdk_bdev_io) outstanding_io; 10332d7c91cSJim Harris uint32_t outstanding_io_count; 1043c7894ffSShuhei Matsumoto TAILQ_HEAD(, ut_expected_io) expected_io; 10532d7c91cSJim Harris }; 10632d7c91cSJim Harris 1074bd97621SJim Harris static bool g_io_done; 108dadd2a6dSPiotr Pelplinski static struct spdk_bdev_io *g_bdev_io; 1090df515a8SShuhei Matsumoto static enum spdk_bdev_io_status g_io_status; 110c55c85f8SChangpeng Liu static enum spdk_bdev_io_status g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 11132d7c91cSJim Harris static uint32_t g_bdev_ut_io_device; 11232d7c91cSJim Harris static struct bdev_ut_channel *g_bdev_ut_channel; 113ae43c81aSJim Harris static void *g_compare_read_buf; 114ae43c81aSJim Harris static uint32_t g_compare_read_buf_len; 115ae43c81aSJim Harris static void *g_compare_write_buf; 116ae43c81aSJim Harris static uint32_t g_compare_write_buf_len; 1177cd20dd3SShuhei Matsumoto static bool g_abort_done; 1187cd20dd3SShuhei Matsumoto static enum spdk_bdev_io_status g_abort_status; 11932d7c91cSJim Harris 1203c7894ffSShuhei Matsumoto static struct ut_expected_io * 1213c7894ffSShuhei Matsumoto ut_alloc_expected_io(uint8_t type, uint64_t offset, uint64_t length, int iovcnt) 1223c7894ffSShuhei Matsumoto { 1233c7894ffSShuhei Matsumoto struct ut_expected_io *expected_io; 1243c7894ffSShuhei Matsumoto 1253c7894ffSShuhei Matsumoto expected_io = calloc(1, sizeof(*expected_io)); 1263c7894ffSShuhei Matsumoto SPDK_CU_ASSERT_FATAL(expected_io != NULL); 1273c7894ffSShuhei Matsumoto 1283c7894ffSShuhei Matsumoto expected_io->type = type; 1293c7894ffSShuhei Matsumoto expected_io->offset = offset; 1303c7894ffSShuhei Matsumoto expected_io->length = length; 1313c7894ffSShuhei Matsumoto expected_io->iovcnt = iovcnt; 1323c7894ffSShuhei Matsumoto 1333c7894ffSShuhei Matsumoto return expected_io; 1343c7894ffSShuhei Matsumoto } 1353c7894ffSShuhei Matsumoto 1363c7894ffSShuhei Matsumoto static void 1373c7894ffSShuhei Matsumoto ut_expected_io_set_iov(struct ut_expected_io *expected_io, int pos, void *base, size_t len) 1383c7894ffSShuhei Matsumoto { 1393c7894ffSShuhei Matsumoto expected_io->iov[pos].iov_base = base; 1403c7894ffSShuhei Matsumoto expected_io->iov[pos].iov_len = len; 1413c7894ffSShuhei Matsumoto } 1423c7894ffSShuhei Matsumoto 14332d7c91cSJim Harris static void 14432d7c91cSJim Harris stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 14532d7c91cSJim Harris { 14632d7c91cSJim Harris struct bdev_ut_channel *ch = spdk_io_channel_get_ctx(_ch); 1473c7894ffSShuhei Matsumoto struct ut_expected_io *expected_io; 1484bd97621SJim Harris struct iovec *iov, *expected_iov; 1497cd20dd3SShuhei Matsumoto struct spdk_bdev_io *bio_to_abort; 1504bd97621SJim Harris int i; 15132d7c91cSJim Harris 152dadd2a6dSPiotr Pelplinski g_bdev_io = bdev_io; 153dadd2a6dSPiotr Pelplinski 154ae43c81aSJim Harris if (g_compare_read_buf && bdev_io->type == SPDK_BDEV_IO_TYPE_READ) { 155ae43c81aSJim Harris uint32_t len = bdev_io->u.bdev.iovs[0].iov_len; 156ae43c81aSJim Harris 157ae43c81aSJim Harris CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 158ae43c81aSJim Harris CU_ASSERT(g_compare_read_buf_len == len); 159ae43c81aSJim Harris memcpy(bdev_io->u.bdev.iovs[0].iov_base, g_compare_read_buf, len); 160ae43c81aSJim Harris } 161ae43c81aSJim Harris 162ae43c81aSJim Harris if (g_compare_write_buf && bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) { 163ae43c81aSJim Harris uint32_t len = bdev_io->u.bdev.iovs[0].iov_len; 164ae43c81aSJim Harris 165ae43c81aSJim Harris CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 166ae43c81aSJim Harris CU_ASSERT(g_compare_write_buf_len == len); 167ae43c81aSJim Harris memcpy(g_compare_write_buf, bdev_io->u.bdev.iovs[0].iov_base, len); 168ae43c81aSJim Harris } 169ae43c81aSJim Harris 170ca0eeaabSMaciej Szwed if (g_compare_read_buf && bdev_io->type == SPDK_BDEV_IO_TYPE_COMPARE) { 171ca0eeaabSMaciej Szwed uint32_t len = bdev_io->u.bdev.iovs[0].iov_len; 172ca0eeaabSMaciej Szwed 173ca0eeaabSMaciej Szwed CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 174ca0eeaabSMaciej Szwed CU_ASSERT(g_compare_read_buf_len == len); 175ca0eeaabSMaciej Szwed if (memcmp(bdev_io->u.bdev.iovs[0].iov_base, g_compare_read_buf, len)) { 176ca0eeaabSMaciej Szwed g_io_exp_status = SPDK_BDEV_IO_STATUS_MISCOMPARE; 177ca0eeaabSMaciej Szwed } 178ca0eeaabSMaciej Szwed } 179ca0eeaabSMaciej Szwed 1807cd20dd3SShuhei Matsumoto if (bdev_io->type == SPDK_BDEV_IO_TYPE_ABORT) { 1817cd20dd3SShuhei Matsumoto if (g_io_exp_status == SPDK_BDEV_IO_STATUS_SUCCESS) { 1827cd20dd3SShuhei Matsumoto TAILQ_FOREACH(bio_to_abort, &ch->outstanding_io, module_link) { 1837cd20dd3SShuhei Matsumoto if (bio_to_abort == bdev_io->u.abort.bio_to_abort) { 1847cd20dd3SShuhei Matsumoto TAILQ_REMOVE(&ch->outstanding_io, bio_to_abort, module_link); 1857cd20dd3SShuhei Matsumoto ch->outstanding_io_count--; 1867cd20dd3SShuhei Matsumoto spdk_bdev_io_complete(bio_to_abort, SPDK_BDEV_IO_STATUS_FAILED); 1877cd20dd3SShuhei Matsumoto break; 1887cd20dd3SShuhei Matsumoto } 1897cd20dd3SShuhei Matsumoto } 1907cd20dd3SShuhei Matsumoto } 1917cd20dd3SShuhei Matsumoto } 1927cd20dd3SShuhei Matsumoto 19332d7c91cSJim Harris TAILQ_INSERT_TAIL(&ch->outstanding_io, bdev_io, module_link); 19432d7c91cSJim Harris ch->outstanding_io_count++; 1954bd97621SJim Harris 1963c7894ffSShuhei Matsumoto expected_io = TAILQ_FIRST(&ch->expected_io); 1973c7894ffSShuhei Matsumoto if (expected_io == NULL) { 1983c7894ffSShuhei Matsumoto return; 1993c7894ffSShuhei Matsumoto } 2003c7894ffSShuhei Matsumoto TAILQ_REMOVE(&ch->expected_io, expected_io, link); 2013c7894ffSShuhei Matsumoto 2023c7894ffSShuhei Matsumoto if (expected_io->type != SPDK_BDEV_IO_TYPE_INVALID) { 2033c7894ffSShuhei Matsumoto CU_ASSERT(bdev_io->type == expected_io->type); 2044bd97621SJim Harris } 2054bd97621SJim Harris 206e2918289SKonrad Sztyber if (expected_io->md_buf != NULL) { 207e2918289SKonrad Sztyber CU_ASSERT(expected_io->md_buf == bdev_io->u.bdev.md_buf); 208e2918289SKonrad Sztyber } 209e2918289SKonrad Sztyber 2103c7894ffSShuhei Matsumoto if (expected_io->length == 0) { 2113c7894ffSShuhei Matsumoto free(expected_io); 2124bd97621SJim Harris return; 2134bd97621SJim Harris } 2144bd97621SJim Harris 2153c7894ffSShuhei Matsumoto CU_ASSERT(expected_io->offset == bdev_io->u.bdev.offset_blocks); 2163c7894ffSShuhei Matsumoto CU_ASSERT(expected_io->length = bdev_io->u.bdev.num_blocks); 2174bd97621SJim Harris 2183c7894ffSShuhei Matsumoto if (expected_io->iovcnt == 0) { 2193c7894ffSShuhei Matsumoto free(expected_io); 2204bd97621SJim Harris /* UNMAP, WRITE_ZEROES and FLUSH don't have iovs, so we can just return now. */ 2214bd97621SJim Harris return; 2224bd97621SJim Harris } 2234bd97621SJim Harris 2243c7894ffSShuhei Matsumoto CU_ASSERT(expected_io->iovcnt == bdev_io->u.bdev.iovcnt); 2253c7894ffSShuhei Matsumoto for (i = 0; i < expected_io->iovcnt; i++) { 2264bd97621SJim Harris iov = &bdev_io->u.bdev.iovs[i]; 2273c7894ffSShuhei Matsumoto expected_iov = &expected_io->iov[i]; 2284bd97621SJim Harris CU_ASSERT(iov->iov_len == expected_iov->iov_len); 2294bd97621SJim Harris CU_ASSERT(iov->iov_base == expected_iov->iov_base); 2304bd97621SJim Harris } 2313c7894ffSShuhei Matsumoto 2323c7894ffSShuhei Matsumoto free(expected_io); 23332d7c91cSJim Harris } 23432d7c91cSJim Harris 235dadd2a6dSPiotr Pelplinski static void 23680da9548SMaciej Szwed stub_submit_request_get_buf_cb(struct spdk_io_channel *_ch, 2374b92ffb3SShuhei Matsumoto struct spdk_bdev_io *bdev_io, bool success) 2384b92ffb3SShuhei Matsumoto { 2394b92ffb3SShuhei Matsumoto CU_ASSERT(success == true); 2404b92ffb3SShuhei Matsumoto 2414b92ffb3SShuhei Matsumoto stub_submit_request(_ch, bdev_io); 2424b92ffb3SShuhei Matsumoto } 2434b92ffb3SShuhei Matsumoto 2444b92ffb3SShuhei Matsumoto static void 24580da9548SMaciej Szwed stub_submit_request_get_buf(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 246dadd2a6dSPiotr Pelplinski { 24780da9548SMaciej Szwed spdk_bdev_io_get_buf(bdev_io, stub_submit_request_get_buf_cb, 248dadd2a6dSPiotr Pelplinski bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); 249dadd2a6dSPiotr Pelplinski } 250dadd2a6dSPiotr Pelplinski 25132d7c91cSJim Harris static uint32_t 25232d7c91cSJim Harris stub_complete_io(uint32_t num_to_complete) 25332d7c91cSJim Harris { 25432d7c91cSJim Harris struct bdev_ut_channel *ch = g_bdev_ut_channel; 25532d7c91cSJim Harris struct spdk_bdev_io *bdev_io; 256c55c85f8SChangpeng Liu static enum spdk_bdev_io_status io_status; 25732d7c91cSJim Harris uint32_t num_completed = 0; 25832d7c91cSJim Harris 25932d7c91cSJim Harris while (num_completed < num_to_complete) { 26032d7c91cSJim Harris if (TAILQ_EMPTY(&ch->outstanding_io)) { 26132d7c91cSJim Harris break; 26232d7c91cSJim Harris } 26332d7c91cSJim Harris bdev_io = TAILQ_FIRST(&ch->outstanding_io); 26432d7c91cSJim Harris TAILQ_REMOVE(&ch->outstanding_io, bdev_io, module_link); 26532d7c91cSJim Harris ch->outstanding_io_count--; 266c55c85f8SChangpeng Liu io_status = g_io_exp_status == SPDK_BDEV_IO_STATUS_SUCCESS ? SPDK_BDEV_IO_STATUS_SUCCESS : 267c55c85f8SChangpeng Liu g_io_exp_status; 268c55c85f8SChangpeng Liu spdk_bdev_io_complete(bdev_io, io_status); 26932d7c91cSJim Harris num_completed++; 27032d7c91cSJim Harris } 27132d7c91cSJim Harris 27232d7c91cSJim Harris return num_completed; 27332d7c91cSJim Harris } 27432d7c91cSJim Harris 27532d7c91cSJim Harris static struct spdk_io_channel * 27632d7c91cSJim Harris bdev_ut_get_io_channel(void *ctx) 27732d7c91cSJim Harris { 27832d7c91cSJim Harris return spdk_get_io_channel(&g_bdev_ut_io_device); 27932d7c91cSJim Harris } 28032d7c91cSJim Harris 281e2918289SKonrad Sztyber static bool g_io_types_supported[SPDK_BDEV_NUM_IO_TYPES] = { 282e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_READ] = true, 283e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_WRITE] = true, 284bee042e4SMaciej Szwed [SPDK_BDEV_IO_TYPE_COMPARE] = true, 285e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_UNMAP] = true, 286e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_FLUSH] = true, 287e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_RESET] = true, 288e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_NVME_ADMIN] = true, 289e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_NVME_IO] = true, 290e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_NVME_IO_MD] = true, 291e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_WRITE_ZEROES] = true, 292e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_ZCOPY] = true, 2937cd20dd3SShuhei Matsumoto [SPDK_BDEV_IO_TYPE_ABORT] = true, 294e2918289SKonrad Sztyber }; 295e2918289SKonrad Sztyber 296e2918289SKonrad Sztyber static void 297e2918289SKonrad Sztyber ut_enable_io_type(enum spdk_bdev_io_type io_type, bool enable) 298e2918289SKonrad Sztyber { 299e2918289SKonrad Sztyber g_io_types_supported[io_type] = enable; 300e2918289SKonrad Sztyber } 301e2918289SKonrad Sztyber 302e2918289SKonrad Sztyber static bool 303e2918289SKonrad Sztyber stub_io_type_supported(void *_bdev, enum spdk_bdev_io_type io_type) 304e2918289SKonrad Sztyber { 305e2918289SKonrad Sztyber return g_io_types_supported[io_type]; 306e2918289SKonrad Sztyber } 3074bd97621SJim Harris 30857d174ffSJim Harris static struct spdk_bdev_fn_table fn_table = { 30957d174ffSJim Harris .destruct = stub_destruct, 31032d7c91cSJim Harris .submit_request = stub_submit_request, 31132d7c91cSJim Harris .get_io_channel = bdev_ut_get_io_channel, 3124bd97621SJim Harris .io_type_supported = stub_io_type_supported, 31357d174ffSJim Harris }; 31457d174ffSJim Harris 31532d7c91cSJim Harris static int 31632d7c91cSJim Harris bdev_ut_create_ch(void *io_device, void *ctx_buf) 31732d7c91cSJim Harris { 31832d7c91cSJim Harris struct bdev_ut_channel *ch = ctx_buf; 31932d7c91cSJim Harris 32032d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel == NULL); 32132d7c91cSJim Harris g_bdev_ut_channel = ch; 32232d7c91cSJim Harris 32332d7c91cSJim Harris TAILQ_INIT(&ch->outstanding_io); 32432d7c91cSJim Harris ch->outstanding_io_count = 0; 3253c7894ffSShuhei Matsumoto TAILQ_INIT(&ch->expected_io); 32632d7c91cSJim Harris return 0; 32732d7c91cSJim Harris } 32832d7c91cSJim Harris 32932d7c91cSJim Harris static void 33032d7c91cSJim Harris bdev_ut_destroy_ch(void *io_device, void *ctx_buf) 33132d7c91cSJim Harris { 33232d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel != NULL); 33332d7c91cSJim Harris g_bdev_ut_channel = NULL; 33432d7c91cSJim Harris } 33532d7c91cSJim Harris 336d83a3489STomasz Zawadzki struct spdk_bdev_module bdev_ut_if; 337d83a3489STomasz Zawadzki 33832d7c91cSJim Harris static int 33932d7c91cSJim Harris bdev_ut_module_init(void) 34032d7c91cSJim Harris { 34132d7c91cSJim Harris spdk_io_device_register(&g_bdev_ut_io_device, bdev_ut_create_ch, bdev_ut_destroy_ch, 342c9402000SBen Walker sizeof(struct bdev_ut_channel), NULL); 343d83a3489STomasz Zawadzki spdk_bdev_module_init_done(&bdev_ut_if); 34432d7c91cSJim Harris return 0; 34532d7c91cSJim Harris } 34632d7c91cSJim Harris 34732d7c91cSJim Harris static void 34832d7c91cSJim Harris bdev_ut_module_fini(void) 34932d7c91cSJim Harris { 3508ef7818aSJim Harris spdk_io_device_unregister(&g_bdev_ut_io_device, NULL); 35132d7c91cSJim Harris } 35232d7c91cSJim Harris 35319100ed5SDaniel Verkamp struct spdk_bdev_module bdev_ut_if = { 3544d367354SPawel Wodkowski .name = "bdev_ut", 35532d7c91cSJim Harris .module_init = bdev_ut_module_init, 35632d7c91cSJim Harris .module_fini = bdev_ut_module_fini, 357d83a3489STomasz Zawadzki .async_init = true, 3584d367354SPawel Wodkowski }; 3594d367354SPawel Wodkowski 3604d367354SPawel Wodkowski static void vbdev_ut_examine(struct spdk_bdev *bdev); 3614d367354SPawel Wodkowski 36232d7c91cSJim Harris static int 36332d7c91cSJim Harris vbdev_ut_module_init(void) 36432d7c91cSJim Harris { 36532d7c91cSJim Harris return 0; 36632d7c91cSJim Harris } 36732d7c91cSJim Harris 36832d7c91cSJim Harris static void 36932d7c91cSJim Harris vbdev_ut_module_fini(void) 37032d7c91cSJim Harris { 37132d7c91cSJim Harris } 37232d7c91cSJim Harris 37319100ed5SDaniel Verkamp struct spdk_bdev_module vbdev_ut_if = { 3744d367354SPawel Wodkowski .name = "vbdev_ut", 37532d7c91cSJim Harris .module_init = vbdev_ut_module_init, 37632d7c91cSJim Harris .module_fini = vbdev_ut_module_fini, 3779d258c75SPiotr Pelplinski .examine_config = vbdev_ut_examine, 3784d367354SPawel Wodkowski }; 3794d367354SPawel Wodkowski 380df6b55fdSgila SPDK_BDEV_MODULE_REGISTER(bdev_ut, &bdev_ut_if) 381df6b55fdSgila SPDK_BDEV_MODULE_REGISTER(vbdev_ut, &vbdev_ut_if) 3824d367354SPawel Wodkowski 383e075a3dcSJim Harris static void 384e075a3dcSJim Harris vbdev_ut_examine(struct spdk_bdev *bdev) 385e075a3dcSJim Harris { 3864d367354SPawel Wodkowski spdk_bdev_module_examine_done(&vbdev_ut_if); 387e075a3dcSJim Harris } 388e075a3dcSJim Harris 38957d174ffSJim Harris static struct spdk_bdev * 39057d174ffSJim Harris allocate_bdev(char *name) 39157d174ffSJim Harris { 39257d174ffSJim Harris struct spdk_bdev *bdev; 393b9afa3c7SSebastian Basierski int rc; 39457d174ffSJim Harris 39557d174ffSJim Harris bdev = calloc(1, sizeof(*bdev)); 39657d174ffSJim Harris SPDK_CU_ASSERT_FATAL(bdev != NULL); 39757d174ffSJim Harris 39857d174ffSJim Harris bdev->name = name; 39957d174ffSJim Harris bdev->fn_table = &fn_table; 4004d367354SPawel Wodkowski bdev->module = &bdev_ut_if; 4015616c1edSShuhei Matsumoto bdev->blockcnt = 1024; 4024bd97621SJim Harris bdev->blocklen = 512; 40357d174ffSJim Harris 404b9afa3c7SSebastian Basierski rc = spdk_bdev_register(bdev); 405b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 40657d174ffSJim Harris 40757d174ffSJim Harris return bdev; 40857d174ffSJim Harris } 40957d174ffSJim Harris 41057d174ffSJim Harris static struct spdk_bdev * 411bfd1e46eSJim Harris allocate_vbdev(char *name) 41257d174ffSJim Harris { 41357d174ffSJim Harris struct spdk_bdev *bdev; 414b9afa3c7SSebastian Basierski int rc; 41557d174ffSJim Harris 41657d174ffSJim Harris bdev = calloc(1, sizeof(*bdev)); 41757d174ffSJim Harris SPDK_CU_ASSERT_FATAL(bdev != NULL); 41857d174ffSJim Harris 41957d174ffSJim Harris bdev->name = name; 42057d174ffSJim Harris bdev->fn_table = &fn_table; 4214d367354SPawel Wodkowski bdev->module = &vbdev_ut_if; 42257d174ffSJim Harris 423bfd1e46eSJim Harris rc = spdk_bdev_register(bdev); 424b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 42557d174ffSJim Harris 42657d174ffSJim Harris return bdev; 42757d174ffSJim Harris } 42857d174ffSJim Harris 42957d174ffSJim Harris static void 43057d174ffSJim Harris free_bdev(struct spdk_bdev *bdev) 43157d174ffSJim Harris { 4322baeea7dSMaciej Szwed spdk_bdev_unregister(bdev, NULL, NULL); 433270a25dfSBen Walker poll_threads(); 4344473942fSPawel Wodkowski memset(bdev, 0xFF, sizeof(*bdev)); 43557d174ffSJim Harris free(bdev); 43657d174ffSJim Harris } 43757d174ffSJim Harris 43857d174ffSJim Harris static void 43957d174ffSJim Harris free_vbdev(struct spdk_bdev *bdev) 44057d174ffSJim Harris { 441b6aaba08STomasz Zawadzki spdk_bdev_unregister(bdev, NULL, NULL); 442270a25dfSBen Walker poll_threads(); 4434473942fSPawel Wodkowski memset(bdev, 0xFF, sizeof(*bdev)); 44457d174ffSJim Harris free(bdev); 44557d174ffSJim Harris } 44657d174ffSJim Harris 44757d174ffSJim Harris static void 44864ccd4b9SYanbo Zhou get_device_stat_cb(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, void *cb_arg, int rc) 44964ccd4b9SYanbo Zhou { 45064ccd4b9SYanbo Zhou const char *bdev_name; 45164ccd4b9SYanbo Zhou 45264ccd4b9SYanbo Zhou CU_ASSERT(bdev != NULL); 45364ccd4b9SYanbo Zhou CU_ASSERT(rc == 0); 45464ccd4b9SYanbo Zhou bdev_name = spdk_bdev_get_name(bdev); 45564ccd4b9SYanbo Zhou CU_ASSERT_STRING_EQUAL(bdev_name, "bdev0"); 45664ccd4b9SYanbo Zhou 45764ccd4b9SYanbo Zhou free(stat); 45864ccd4b9SYanbo Zhou free_bdev(bdev); 459270a25dfSBen Walker 460270a25dfSBen Walker *(bool *)cb_arg = true; 46164ccd4b9SYanbo Zhou } 46264ccd4b9SYanbo Zhou 46364ccd4b9SYanbo Zhou static void 46423975858SEvgeniy Kochetov bdev_unregister_cb(void *cb_arg, int rc) 46523975858SEvgeniy Kochetov { 46623975858SEvgeniy Kochetov g_unregister_arg = cb_arg; 46723975858SEvgeniy Kochetov g_unregister_rc = rc; 46823975858SEvgeniy Kochetov } 46923975858SEvgeniy Kochetov 47023975858SEvgeniy Kochetov static void 471*75dfecbbSShuhei Matsumoto bdev_ut_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 472*75dfecbbSShuhei Matsumoto { 473*75dfecbbSShuhei Matsumoto } 474*75dfecbbSShuhei Matsumoto 475*75dfecbbSShuhei Matsumoto static void 476437e54f7SEvgeniy Kochetov bdev_open_cb1(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 477437e54f7SEvgeniy Kochetov { 478437e54f7SEvgeniy Kochetov struct spdk_bdev_desc *desc = *(struct spdk_bdev_desc **)event_ctx; 479437e54f7SEvgeniy Kochetov 480437e54f7SEvgeniy Kochetov g_event_type1 = type; 4819522ed36SEvgeniy Kochetov if (SPDK_BDEV_EVENT_REMOVE == type) { 482437e54f7SEvgeniy Kochetov spdk_bdev_close(desc); 483437e54f7SEvgeniy Kochetov } 4849522ed36SEvgeniy Kochetov } 485437e54f7SEvgeniy Kochetov 486437e54f7SEvgeniy Kochetov static void 487437e54f7SEvgeniy Kochetov bdev_open_cb2(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 488437e54f7SEvgeniy Kochetov { 489437e54f7SEvgeniy Kochetov struct spdk_bdev_desc *desc = *(struct spdk_bdev_desc **)event_ctx; 490437e54f7SEvgeniy Kochetov 491437e54f7SEvgeniy Kochetov g_event_type2 = type; 4929522ed36SEvgeniy Kochetov if (SPDK_BDEV_EVENT_REMOVE == type) { 493437e54f7SEvgeniy Kochetov spdk_bdev_close(desc); 494437e54f7SEvgeniy Kochetov } 4959522ed36SEvgeniy Kochetov } 496437e54f7SEvgeniy Kochetov 497437e54f7SEvgeniy Kochetov static void 49864ccd4b9SYanbo Zhou get_device_stat_test(void) 49964ccd4b9SYanbo Zhou { 50064ccd4b9SYanbo Zhou struct spdk_bdev *bdev; 50164ccd4b9SYanbo Zhou struct spdk_bdev_io_stat *stat; 502270a25dfSBen Walker bool done; 50364ccd4b9SYanbo Zhou 50464ccd4b9SYanbo Zhou bdev = allocate_bdev("bdev0"); 50564ccd4b9SYanbo Zhou stat = calloc(1, sizeof(struct spdk_bdev_io_stat)); 50664ccd4b9SYanbo Zhou if (stat == NULL) { 50764ccd4b9SYanbo Zhou free_bdev(bdev); 50864ccd4b9SYanbo Zhou return; 50964ccd4b9SYanbo Zhou } 510270a25dfSBen Walker 511270a25dfSBen Walker done = false; 512270a25dfSBen Walker spdk_bdev_get_device_stat(bdev, stat, get_device_stat_cb, &done); 513270a25dfSBen Walker while (!done) { poll_threads(); } 514270a25dfSBen Walker 515270a25dfSBen Walker 51664ccd4b9SYanbo Zhou } 51764ccd4b9SYanbo Zhou 51864ccd4b9SYanbo Zhou static void 51957d174ffSJim Harris open_write_test(void) 52057d174ffSJim Harris { 5214473942fSPawel Wodkowski struct spdk_bdev *bdev[9]; 5224473942fSPawel Wodkowski struct spdk_bdev_desc *desc[9] = {}; 52357d174ffSJim Harris int rc; 52457d174ffSJim Harris 52557d174ffSJim Harris /* 52657d174ffSJim Harris * Create a tree of bdevs to test various open w/ write cases. 52757d174ffSJim Harris * 5284473942fSPawel Wodkowski * bdev0 through bdev3 are physical block devices, such as NVMe 52957d174ffSJim Harris * namespaces or Ceph block devices. 53057d174ffSJim Harris * 5314473942fSPawel Wodkowski * bdev4 is a virtual bdev with multiple base bdevs. This models 53257d174ffSJim Harris * caching or RAID use cases. 53357d174ffSJim Harris * 5344473942fSPawel Wodkowski * bdev5 through bdev7 are all virtual bdevs with the same base 5354473942fSPawel Wodkowski * bdev (except bdev7). This models partitioning or logical volume 5364473942fSPawel Wodkowski * use cases. 53757d174ffSJim Harris * 5384473942fSPawel Wodkowski * bdev7 is a virtual bdev with multiple base bdevs. One of base bdevs 5394473942fSPawel Wodkowski * (bdev2) is shared with other virtual bdevs: bdev5 and bdev6. This 5404473942fSPawel Wodkowski * models caching, RAID, partitioning or logical volumes use cases. 5414473942fSPawel Wodkowski * 5424473942fSPawel Wodkowski * bdev8 is a virtual bdev with multiple base bdevs, but these 54357d174ffSJim Harris * base bdevs are themselves virtual bdevs. 54457d174ffSJim Harris * 5454473942fSPawel Wodkowski * bdev8 54657d174ffSJim Harris * | 54757d174ffSJim Harris * +----------+ 54857d174ffSJim Harris * | | 5494473942fSPawel Wodkowski * bdev4 bdev5 bdev6 bdev7 55057d174ffSJim Harris * | | | | 5514473942fSPawel Wodkowski * +---+---+ +---+ + +---+---+ 5524473942fSPawel Wodkowski * | | \ | / \ 5534473942fSPawel Wodkowski * bdev0 bdev1 bdev2 bdev3 55457d174ffSJim Harris */ 55557d174ffSJim Harris 55657d174ffSJim Harris bdev[0] = allocate_bdev("bdev0"); 5574d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, &bdev_ut_if); 5584fc7e666SJim Harris CU_ASSERT(rc == 0); 5594fc7e666SJim Harris 56057d174ffSJim Harris bdev[1] = allocate_bdev("bdev1"); 5614d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if); 5624fc7e666SJim Harris CU_ASSERT(rc == 0); 5634fc7e666SJim Harris 56457d174ffSJim Harris bdev[2] = allocate_bdev("bdev2"); 5654d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, &bdev_ut_if); 5664fc7e666SJim Harris CU_ASSERT(rc == 0); 56757d174ffSJim Harris 5684473942fSPawel Wodkowski bdev[3] = allocate_bdev("bdev3"); 5694d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if); 5704fc7e666SJim Harris CU_ASSERT(rc == 0); 57157d174ffSJim Harris 572bfd1e46eSJim Harris bdev[4] = allocate_vbdev("bdev4"); 5734d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, &bdev_ut_if); 5744fc7e666SJim Harris CU_ASSERT(rc == 0); 5754fc7e666SJim Harris 576bfd1e46eSJim Harris bdev[5] = allocate_vbdev("bdev5"); 5774473942fSPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if); 5784473942fSPawel Wodkowski CU_ASSERT(rc == 0); 5794473942fSPawel Wodkowski 580bfd1e46eSJim Harris bdev[6] = allocate_vbdev("bdev6"); 58157d174ffSJim Harris 582bfd1e46eSJim Harris bdev[7] = allocate_vbdev("bdev7"); 5834473942fSPawel Wodkowski 584bfd1e46eSJim Harris bdev[8] = allocate_vbdev("bdev8"); 5854473942fSPawel Wodkowski 58657d174ffSJim Harris /* Open bdev0 read-only. This should succeed. */ 587*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc[0]); 58857d174ffSJim Harris CU_ASSERT(rc == 0); 5891196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[0] != NULL); 590*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev[0] == spdk_bdev_desc_get_bdev(desc[0])); 59157d174ffSJim Harris spdk_bdev_close(desc[0]); 59257d174ffSJim Harris 5934fc7e666SJim Harris /* 5944fc7e666SJim Harris * Open bdev1 read/write. This should fail since bdev1 has been claimed 5954fc7e666SJim Harris * by a vbdev module. 5964fc7e666SJim Harris */ 597*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev1", true, bdev_ut_event_cb, NULL, &desc[1]); 5984fc7e666SJim Harris CU_ASSERT(rc == -EPERM); 59957d174ffSJim Harris 60057d174ffSJim Harris /* 6014473942fSPawel Wodkowski * Open bdev4 read/write. This should fail since bdev3 has been claimed 6024fc7e666SJim Harris * by a vbdev module. 60357d174ffSJim Harris */ 604*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev4", true, bdev_ut_event_cb, NULL, &desc[4]); 60557d174ffSJim Harris CU_ASSERT(rc == -EPERM); 60657d174ffSJim Harris 60757d174ffSJim Harris /* Open bdev4 read-only. This should succeed. */ 608*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev4", false, bdev_ut_event_cb, NULL, &desc[4]); 60957d174ffSJim Harris CU_ASSERT(rc == 0); 6101196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[4] != NULL); 611*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev[4] == spdk_bdev_desc_get_bdev(desc[4])); 61257d174ffSJim Harris spdk_bdev_close(desc[4]); 61357d174ffSJim Harris 6144473942fSPawel Wodkowski /* 6154473942fSPawel Wodkowski * Open bdev8 read/write. This should succeed since it is a leaf 6164473942fSPawel Wodkowski * bdev. 6174473942fSPawel Wodkowski */ 618*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev8", true, bdev_ut_event_cb, NULL, &desc[8]); 6194473942fSPawel Wodkowski CU_ASSERT(rc == 0); 6201196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[8] != NULL); 621*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev[8] == spdk_bdev_desc_get_bdev(desc[8])); 6224473942fSPawel Wodkowski spdk_bdev_close(desc[8]); 62357d174ffSJim Harris 6244473942fSPawel Wodkowski /* 6254473942fSPawel Wodkowski * Open bdev5 read/write. This should fail since bdev4 has been claimed 6264473942fSPawel Wodkowski * by a vbdev module. 6274473942fSPawel Wodkowski */ 628*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev5", true, bdev_ut_event_cb, NULL, &desc[5]); 6294473942fSPawel Wodkowski CU_ASSERT(rc == -EPERM); 6304473942fSPawel Wodkowski 6314473942fSPawel Wodkowski /* Open bdev4 read-only. This should succeed. */ 632*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev5", false, bdev_ut_event_cb, NULL, &desc[5]); 6334473942fSPawel Wodkowski CU_ASSERT(rc == 0); 6341196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[5] != NULL); 635*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev[5] == spdk_bdev_desc_get_bdev(desc[5])); 6364473942fSPawel Wodkowski spdk_bdev_close(desc[5]); 6374473942fSPawel Wodkowski 6384473942fSPawel Wodkowski free_vbdev(bdev[8]); 6394473942fSPawel Wodkowski 64057d174ffSJim Harris free_vbdev(bdev[5]); 64157d174ffSJim Harris free_vbdev(bdev[6]); 6424473942fSPawel Wodkowski free_vbdev(bdev[7]); 6434473942fSPawel Wodkowski 6444473942fSPawel Wodkowski free_vbdev(bdev[4]); 64557d174ffSJim Harris 64657d174ffSJim Harris free_bdev(bdev[0]); 64757d174ffSJim Harris free_bdev(bdev[1]); 64857d174ffSJim Harris free_bdev(bdev[2]); 6494473942fSPawel Wodkowski free_bdev(bdev[3]); 6504ee51dcbSJim Harris } 6514ee51dcbSJim Harris 652906ce694SDaniel Verkamp static void 653e83f9767SDaniel Verkamp bytes_to_blocks_test(void) 654e83f9767SDaniel Verkamp { 655e83f9767SDaniel Verkamp struct spdk_bdev bdev; 656e83f9767SDaniel Verkamp uint64_t offset_blocks, num_blocks; 657e83f9767SDaniel Verkamp 658e83f9767SDaniel Verkamp memset(&bdev, 0, sizeof(bdev)); 659e83f9767SDaniel Verkamp 660e83f9767SDaniel Verkamp bdev.blocklen = 512; 661e83f9767SDaniel Verkamp 662e83f9767SDaniel Verkamp /* All parameters valid */ 663e83f9767SDaniel Verkamp offset_blocks = 0; 664e83f9767SDaniel Verkamp num_blocks = 0; 6650e58d154SJim Harris CU_ASSERT(bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0); 666e83f9767SDaniel Verkamp CU_ASSERT(offset_blocks == 1); 667e83f9767SDaniel Verkamp CU_ASSERT(num_blocks == 2); 668e83f9767SDaniel Verkamp 669e83f9767SDaniel Verkamp /* Offset not a block multiple */ 6700e58d154SJim Harris CU_ASSERT(bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0); 671e83f9767SDaniel Verkamp 672e83f9767SDaniel Verkamp /* Length not a block multiple */ 6730e58d154SJim Harris CU_ASSERT(bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0); 67402be32d4Slorneli 67502be32d4Slorneli /* In case blocklen not the power of two */ 67602be32d4Slorneli bdev.blocklen = 100; 6770e58d154SJim Harris CU_ASSERT(bdev_bytes_to_blocks(&bdev, 100, &offset_blocks, 200, &num_blocks) == 0); 67802be32d4Slorneli CU_ASSERT(offset_blocks == 1); 67902be32d4Slorneli CU_ASSERT(num_blocks == 2); 68002be32d4Slorneli 68102be32d4Slorneli /* Offset not a block multiple */ 6820e58d154SJim Harris CU_ASSERT(bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 100, &num_blocks) != 0); 68302be32d4Slorneli 68402be32d4Slorneli /* Length not a block multiple */ 6850e58d154SJim Harris CU_ASSERT(bdev_bytes_to_blocks(&bdev, 100, &offset_blocks, 3, &num_blocks) != 0); 686e83f9767SDaniel Verkamp } 687e83f9767SDaniel Verkamp 688e83f9767SDaniel Verkamp static void 689d4822a7dSSlawomir Mrozowicz num_blocks_test(void) 690d4822a7dSSlawomir Mrozowicz { 691d4822a7dSSlawomir Mrozowicz struct spdk_bdev bdev; 6921196deb5SSeth Howell struct spdk_bdev_desc *desc = NULL; 6939522ed36SEvgeniy Kochetov struct spdk_bdev_desc *desc_ext = NULL; 6941196deb5SSeth Howell int rc; 695d4822a7dSSlawomir Mrozowicz 696d4822a7dSSlawomir Mrozowicz memset(&bdev, 0, sizeof(bdev)); 697d4822a7dSSlawomir Mrozowicz bdev.name = "num_blocks"; 698d4822a7dSSlawomir Mrozowicz bdev.fn_table = &fn_table; 6994d367354SPawel Wodkowski bdev.module = &bdev_ut_if; 700d4822a7dSSlawomir Mrozowicz spdk_bdev_register(&bdev); 701d4822a7dSSlawomir Mrozowicz spdk_bdev_notify_blockcnt_change(&bdev, 50); 702d4822a7dSSlawomir Mrozowicz 703d4822a7dSSlawomir Mrozowicz /* Growing block number */ 704d4822a7dSSlawomir Mrozowicz CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 70) == 0); 705d4822a7dSSlawomir Mrozowicz /* Shrinking block number */ 706d4822a7dSSlawomir Mrozowicz CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 30) == 0); 707d4822a7dSSlawomir Mrozowicz 708d4822a7dSSlawomir Mrozowicz /* In case bdev opened */ 7091196deb5SSeth Howell rc = spdk_bdev_open(&bdev, false, NULL, NULL, &desc); 7101196deb5SSeth Howell CU_ASSERT(rc == 0); 7111196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc != NULL); 712d4822a7dSSlawomir Mrozowicz 713d4822a7dSSlawomir Mrozowicz /* Growing block number */ 714d4822a7dSSlawomir Mrozowicz CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 80) == 0); 715d4822a7dSSlawomir Mrozowicz /* Shrinking block number */ 716d4822a7dSSlawomir Mrozowicz CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 20) != 0); 717d4822a7dSSlawomir Mrozowicz 7189522ed36SEvgeniy Kochetov /* In case bdev opened with ext API */ 7199522ed36SEvgeniy Kochetov rc = spdk_bdev_open_ext("num_blocks", false, bdev_open_cb1, &desc_ext, &desc_ext); 7209522ed36SEvgeniy Kochetov CU_ASSERT(rc == 0); 7219522ed36SEvgeniy Kochetov SPDK_CU_ASSERT_FATAL(desc_ext != NULL); 722*75dfecbbSShuhei Matsumoto CU_ASSERT(&bdev == spdk_bdev_desc_get_bdev(desc_ext)); 7239522ed36SEvgeniy Kochetov 7249522ed36SEvgeniy Kochetov g_event_type1 = 0xFF; 7259522ed36SEvgeniy Kochetov /* Growing block number */ 7269522ed36SEvgeniy Kochetov CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 90) == 0); 7279522ed36SEvgeniy Kochetov 7289522ed36SEvgeniy Kochetov poll_threads(); 7299522ed36SEvgeniy Kochetov CU_ASSERT_EQUAL(g_event_type1, SPDK_BDEV_EVENT_RESIZE); 7309522ed36SEvgeniy Kochetov 7319522ed36SEvgeniy Kochetov g_event_type1 = 0xFF; 7329522ed36SEvgeniy Kochetov /* Growing block number and closing */ 7339522ed36SEvgeniy Kochetov CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 100) == 0); 7349522ed36SEvgeniy Kochetov 735d4822a7dSSlawomir Mrozowicz spdk_bdev_close(desc); 7369522ed36SEvgeniy Kochetov spdk_bdev_close(desc_ext); 737d4822a7dSSlawomir Mrozowicz spdk_bdev_unregister(&bdev, NULL, NULL); 738270a25dfSBen Walker 739270a25dfSBen Walker poll_threads(); 7409522ed36SEvgeniy Kochetov 7419522ed36SEvgeniy Kochetov /* Callback is not called for closed device */ 7429522ed36SEvgeniy Kochetov CU_ASSERT_EQUAL(g_event_type1, 0xFF); 743d4822a7dSSlawomir Mrozowicz } 744d4822a7dSSlawomir Mrozowicz 745d4822a7dSSlawomir Mrozowicz static void 746906ce694SDaniel Verkamp io_valid_test(void) 747906ce694SDaniel Verkamp { 748906ce694SDaniel Verkamp struct spdk_bdev bdev; 749906ce694SDaniel Verkamp 750906ce694SDaniel Verkamp memset(&bdev, 0, sizeof(bdev)); 751906ce694SDaniel Verkamp 752906ce694SDaniel Verkamp bdev.blocklen = 512; 753d4822a7dSSlawomir Mrozowicz spdk_bdev_notify_blockcnt_change(&bdev, 100); 754906ce694SDaniel Verkamp 755906ce694SDaniel Verkamp /* All parameters valid */ 7560e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 1, 2) == true); 757906ce694SDaniel Verkamp 758906ce694SDaniel Verkamp /* Last valid block */ 7590e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 99, 1) == true); 760906ce694SDaniel Verkamp 761906ce694SDaniel Verkamp /* Offset past end of bdev */ 7620e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 100, 1) == false); 763906ce694SDaniel Verkamp 764906ce694SDaniel Verkamp /* Offset + length past end of bdev */ 7650e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 99, 2) == false); 766906ce694SDaniel Verkamp 767e83f9767SDaniel Verkamp /* Offset near end of uint64_t range (2^64 - 1) */ 7680e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false); 769906ce694SDaniel Verkamp } 770906ce694SDaniel Verkamp 771b9afa3c7SSebastian Basierski static void 772b9afa3c7SSebastian Basierski alias_add_del_test(void) 773b9afa3c7SSebastian Basierski { 7746deac3e6Swuzhouhui struct spdk_bdev *bdev[3]; 775b9afa3c7SSebastian Basierski int rc; 776b9afa3c7SSebastian Basierski 777b9afa3c7SSebastian Basierski /* Creating and registering bdevs */ 778b9afa3c7SSebastian Basierski bdev[0] = allocate_bdev("bdev0"); 779b9afa3c7SSebastian Basierski SPDK_CU_ASSERT_FATAL(bdev[0] != 0); 780b9afa3c7SSebastian Basierski 781b9afa3c7SSebastian Basierski bdev[1] = allocate_bdev("bdev1"); 782b9afa3c7SSebastian Basierski SPDK_CU_ASSERT_FATAL(bdev[1] != 0); 783b9afa3c7SSebastian Basierski 7846deac3e6Swuzhouhui bdev[2] = allocate_bdev("bdev2"); 7856deac3e6Swuzhouhui SPDK_CU_ASSERT_FATAL(bdev[2] != 0); 7866deac3e6Swuzhouhui 787270a25dfSBen Walker poll_threads(); 788270a25dfSBen Walker 789b9afa3c7SSebastian Basierski /* 790b9afa3c7SSebastian Basierski * Trying adding an alias identical to name. 791b9afa3c7SSebastian Basierski * Alias is identical to name, so it can not be added to aliases list 792b9afa3c7SSebastian Basierski */ 793b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name); 794b9afa3c7SSebastian Basierski CU_ASSERT(rc == -EEXIST); 795b9afa3c7SSebastian Basierski 796b9afa3c7SSebastian Basierski /* 797b9afa3c7SSebastian Basierski * Trying to add empty alias, 798b9afa3c7SSebastian Basierski * this one should fail 799b9afa3c7SSebastian Basierski */ 800b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[0], NULL); 801b9afa3c7SSebastian Basierski CU_ASSERT(rc == -EINVAL); 802b9afa3c7SSebastian Basierski 803b9afa3c7SSebastian Basierski /* Trying adding same alias to two different registered bdevs */ 804b9afa3c7SSebastian Basierski 805b9afa3c7SSebastian Basierski /* Alias is used first time, so this one should pass */ 806b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[0], "proper alias 0"); 807b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 808b9afa3c7SSebastian Basierski 809b9afa3c7SSebastian Basierski /* Alias was added to another bdev, so this one should fail */ 810b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[1], "proper alias 0"); 811b9afa3c7SSebastian Basierski CU_ASSERT(rc == -EEXIST); 812b9afa3c7SSebastian Basierski 813b9afa3c7SSebastian Basierski /* Alias is used first time, so this one should pass */ 814b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[1], "proper alias 1"); 815b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 816b9afa3c7SSebastian Basierski 817b9afa3c7SSebastian Basierski /* Trying removing an alias from registered bdevs */ 818b9afa3c7SSebastian Basierski 819b9afa3c7SSebastian Basierski /* Alias is not on a bdev aliases list, so this one should fail */ 820b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[0], "not existing"); 821b9afa3c7SSebastian Basierski CU_ASSERT(rc == -ENOENT); 822b9afa3c7SSebastian Basierski 823b9afa3c7SSebastian Basierski /* Alias is present on a bdev aliases list, so this one should pass */ 824b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[0], "proper alias 0"); 825b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 826b9afa3c7SSebastian Basierski 827b9afa3c7SSebastian Basierski /* Alias is present on a bdev aliases list, so this one should pass */ 828b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[1], "proper alias 1"); 829b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 830b9afa3c7SSebastian Basierski 831b9afa3c7SSebastian Basierski /* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */ 832b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name); 833b9afa3c7SSebastian Basierski CU_ASSERT(rc != 0); 834b9afa3c7SSebastian Basierski 8356deac3e6Swuzhouhui /* Trying to del all alias from empty alias list */ 8366deac3e6Swuzhouhui spdk_bdev_alias_del_all(bdev[2]); 83711ccf3beSSeth Howell SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&bdev[2]->aliases)); 8386deac3e6Swuzhouhui 8396deac3e6Swuzhouhui /* Trying to del all alias from non-empty alias list */ 8406deac3e6Swuzhouhui rc = spdk_bdev_alias_add(bdev[2], "alias0"); 8416deac3e6Swuzhouhui CU_ASSERT(rc == 0); 8426deac3e6Swuzhouhui rc = spdk_bdev_alias_add(bdev[2], "alias1"); 8436deac3e6Swuzhouhui CU_ASSERT(rc == 0); 8446deac3e6Swuzhouhui spdk_bdev_alias_del_all(bdev[2]); 8456deac3e6Swuzhouhui CU_ASSERT(TAILQ_EMPTY(&bdev[2]->aliases)); 8466deac3e6Swuzhouhui 847b9afa3c7SSebastian Basierski /* Unregister and free bdevs */ 848b9afa3c7SSebastian Basierski spdk_bdev_unregister(bdev[0], NULL, NULL); 849b9afa3c7SSebastian Basierski spdk_bdev_unregister(bdev[1], NULL, NULL); 8506deac3e6Swuzhouhui spdk_bdev_unregister(bdev[2], NULL, NULL); 851b9afa3c7SSebastian Basierski 852270a25dfSBen Walker poll_threads(); 853270a25dfSBen Walker 854b9afa3c7SSebastian Basierski free(bdev[0]); 855b9afa3c7SSebastian Basierski free(bdev[1]); 8566deac3e6Swuzhouhui free(bdev[2]); 857b9afa3c7SSebastian Basierski } 858b9afa3c7SSebastian Basierski 85932d7c91cSJim Harris static void 86032d7c91cSJim Harris io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 86132d7c91cSJim Harris { 8624bd97621SJim Harris g_io_done = true; 8630df515a8SShuhei Matsumoto g_io_status = bdev_io->internal.status; 86432d7c91cSJim Harris spdk_bdev_free_io(bdev_io); 86532d7c91cSJim Harris } 86632d7c91cSJim Harris 86732d7c91cSJim Harris static void 86832d7c91cSJim Harris bdev_init_cb(void *arg, int rc) 86932d7c91cSJim Harris { 87032d7c91cSJim Harris CU_ASSERT(rc == 0); 87132d7c91cSJim Harris } 87232d7c91cSJim Harris 8738ef7818aSJim Harris static void 8748ef7818aSJim Harris bdev_fini_cb(void *arg) 8758ef7818aSJim Harris { 8768ef7818aSJim Harris } 8778ef7818aSJim Harris 87832d7c91cSJim Harris struct bdev_ut_io_wait_entry { 87932d7c91cSJim Harris struct spdk_bdev_io_wait_entry entry; 88032d7c91cSJim Harris struct spdk_io_channel *io_ch; 88132d7c91cSJim Harris struct spdk_bdev_desc *desc; 88232d7c91cSJim Harris bool submitted; 88332d7c91cSJim Harris }; 88432d7c91cSJim Harris 88532d7c91cSJim Harris static void 88632d7c91cSJim Harris io_wait_cb(void *arg) 88732d7c91cSJim Harris { 88832d7c91cSJim Harris struct bdev_ut_io_wait_entry *entry = arg; 88932d7c91cSJim Harris int rc; 89032d7c91cSJim Harris 89132d7c91cSJim Harris rc = spdk_bdev_read_blocks(entry->desc, entry->io_ch, NULL, 0, 1, io_done, NULL); 89232d7c91cSJim Harris CU_ASSERT(rc == 0); 89332d7c91cSJim Harris entry->submitted = true; 89432d7c91cSJim Harris } 89532d7c91cSJim Harris 89632d7c91cSJim Harris static void 8979da1c738SChangpeng Liu bdev_io_types_test(void) 8989da1c738SChangpeng Liu { 8999da1c738SChangpeng Liu struct spdk_bdev *bdev; 9009da1c738SChangpeng Liu struct spdk_bdev_desc *desc = NULL; 9019da1c738SChangpeng Liu struct spdk_io_channel *io_ch; 9029da1c738SChangpeng Liu struct spdk_bdev_opts bdev_opts = { 9039da1c738SChangpeng Liu .bdev_io_pool_size = 4, 9049da1c738SChangpeng Liu .bdev_io_cache_size = 2, 9059da1c738SChangpeng Liu }; 9069da1c738SChangpeng Liu int rc; 9079da1c738SChangpeng Liu 9089da1c738SChangpeng Liu rc = spdk_bdev_set_opts(&bdev_opts); 9099da1c738SChangpeng Liu CU_ASSERT(rc == 0); 9109da1c738SChangpeng Liu spdk_bdev_initialize(bdev_init_cb, NULL); 9119da1c738SChangpeng Liu poll_threads(); 9129da1c738SChangpeng Liu 9139da1c738SChangpeng Liu bdev = allocate_bdev("bdev0"); 9149da1c738SChangpeng Liu 915*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 9169da1c738SChangpeng Liu CU_ASSERT(rc == 0); 9179da1c738SChangpeng Liu poll_threads(); 9189da1c738SChangpeng Liu SPDK_CU_ASSERT_FATAL(desc != NULL); 919*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 9209da1c738SChangpeng Liu io_ch = spdk_bdev_get_io_channel(desc); 9219da1c738SChangpeng Liu CU_ASSERT(io_ch != NULL); 9229da1c738SChangpeng Liu 9239da1c738SChangpeng Liu /* WRITE and WRITE ZEROES are not supported */ 924e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, false); 925e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE, false); 9269da1c738SChangpeng Liu rc = spdk_bdev_write_zeroes_blocks(desc, io_ch, 0, 128, io_done, NULL); 9279da1c738SChangpeng Liu CU_ASSERT(rc == -ENOTSUP); 928e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, true); 929e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE, true); 9309da1c738SChangpeng Liu 9319da1c738SChangpeng Liu spdk_put_io_channel(io_ch); 9329da1c738SChangpeng Liu spdk_bdev_close(desc); 9339da1c738SChangpeng Liu free_bdev(bdev); 9349da1c738SChangpeng Liu spdk_bdev_finish(bdev_fini_cb, NULL); 9359da1c738SChangpeng Liu poll_threads(); 9369da1c738SChangpeng Liu } 9379da1c738SChangpeng Liu 9389da1c738SChangpeng Liu static void 93932d7c91cSJim Harris bdev_io_wait_test(void) 94032d7c91cSJim Harris { 94132d7c91cSJim Harris struct spdk_bdev *bdev; 942fb0fe6b1SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 94332d7c91cSJim Harris struct spdk_io_channel *io_ch; 94432d7c91cSJim Harris struct spdk_bdev_opts bdev_opts = { 94532d7c91cSJim Harris .bdev_io_pool_size = 4, 94632d7c91cSJim Harris .bdev_io_cache_size = 2, 94732d7c91cSJim Harris }; 94832d7c91cSJim Harris struct bdev_ut_io_wait_entry io_wait_entry; 94932d7c91cSJim Harris struct bdev_ut_io_wait_entry io_wait_entry2; 95032d7c91cSJim Harris int rc; 95132d7c91cSJim Harris 95232d7c91cSJim Harris rc = spdk_bdev_set_opts(&bdev_opts); 95332d7c91cSJim Harris CU_ASSERT(rc == 0); 95432d7c91cSJim Harris spdk_bdev_initialize(bdev_init_cb, NULL); 955270a25dfSBen Walker poll_threads(); 95632d7c91cSJim Harris 95732d7c91cSJim Harris bdev = allocate_bdev("bdev0"); 95832d7c91cSJim Harris 959*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 96032d7c91cSJim Harris CU_ASSERT(rc == 0); 961270a25dfSBen Walker poll_threads(); 962fb0fe6b1SShuhei Matsumoto SPDK_CU_ASSERT_FATAL(desc != NULL); 963*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 96432d7c91cSJim Harris io_ch = spdk_bdev_get_io_channel(desc); 96532d7c91cSJim Harris CU_ASSERT(io_ch != NULL); 96632d7c91cSJim Harris 96732d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 96832d7c91cSJim Harris CU_ASSERT(rc == 0); 96932d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 97032d7c91cSJim Harris CU_ASSERT(rc == 0); 97132d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 97232d7c91cSJim Harris CU_ASSERT(rc == 0); 97332d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 97432d7c91cSJim Harris CU_ASSERT(rc == 0); 97532d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 97632d7c91cSJim Harris 97732d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 97832d7c91cSJim Harris CU_ASSERT(rc == -ENOMEM); 97932d7c91cSJim Harris 98032d7c91cSJim Harris io_wait_entry.entry.bdev = bdev; 98132d7c91cSJim Harris io_wait_entry.entry.cb_fn = io_wait_cb; 98232d7c91cSJim Harris io_wait_entry.entry.cb_arg = &io_wait_entry; 98332d7c91cSJim Harris io_wait_entry.io_ch = io_ch; 98432d7c91cSJim Harris io_wait_entry.desc = desc; 98532d7c91cSJim Harris io_wait_entry.submitted = false; 98632d7c91cSJim Harris /* Cannot use the same io_wait_entry for two different calls. */ 98732d7c91cSJim Harris memcpy(&io_wait_entry2, &io_wait_entry, sizeof(io_wait_entry)); 98832d7c91cSJim Harris io_wait_entry2.entry.cb_arg = &io_wait_entry2; 98932d7c91cSJim Harris 99032d7c91cSJim Harris /* Queue two I/O waits. */ 99132d7c91cSJim Harris rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry.entry); 99232d7c91cSJim Harris CU_ASSERT(rc == 0); 99332d7c91cSJim Harris CU_ASSERT(io_wait_entry.submitted == false); 99432d7c91cSJim Harris rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry2.entry); 99532d7c91cSJim Harris CU_ASSERT(rc == 0); 99632d7c91cSJim Harris CU_ASSERT(io_wait_entry2.submitted == false); 99732d7c91cSJim Harris 99832d7c91cSJim Harris stub_complete_io(1); 99932d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 100032d7c91cSJim Harris CU_ASSERT(io_wait_entry.submitted == true); 100132d7c91cSJim Harris CU_ASSERT(io_wait_entry2.submitted == false); 100232d7c91cSJim Harris 100332d7c91cSJim Harris stub_complete_io(1); 100432d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 100532d7c91cSJim Harris CU_ASSERT(io_wait_entry2.submitted == true); 100632d7c91cSJim Harris 100732d7c91cSJim Harris stub_complete_io(4); 100832d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 100932d7c91cSJim Harris 101032d7c91cSJim Harris spdk_put_io_channel(io_ch); 101132d7c91cSJim Harris spdk_bdev_close(desc); 101232d7c91cSJim Harris free_bdev(bdev); 10138ef7818aSJim Harris spdk_bdev_finish(bdev_fini_cb, NULL); 1014270a25dfSBen Walker poll_threads(); 101532d7c91cSJim Harris } 101632d7c91cSJim Harris 10174bd97621SJim Harris static void 10184bd97621SJim Harris bdev_io_spans_boundary_test(void) 10194bd97621SJim Harris { 10204bd97621SJim Harris struct spdk_bdev bdev; 10214bd97621SJim Harris struct spdk_bdev_io bdev_io; 10224bd97621SJim Harris 10234bd97621SJim Harris memset(&bdev, 0, sizeof(bdev)); 10244bd97621SJim Harris 10254bd97621SJim Harris bdev.optimal_io_boundary = 0; 10264bd97621SJim Harris bdev_io.bdev = &bdev; 10274bd97621SJim Harris 10284bd97621SJim Harris /* bdev has no optimal_io_boundary set - so this should return false. */ 1029aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 10304bd97621SJim Harris 10314bd97621SJim Harris bdev.optimal_io_boundary = 32; 10324bd97621SJim Harris bdev_io.type = SPDK_BDEV_IO_TYPE_RESET; 10334bd97621SJim Harris 10344bd97621SJim Harris /* RESETs are not based on LBAs - so this should return false. */ 1035aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 10364bd97621SJim Harris 10374bd97621SJim Harris bdev_io.type = SPDK_BDEV_IO_TYPE_READ; 10384bd97621SJim Harris bdev_io.u.bdev.offset_blocks = 0; 10394bd97621SJim Harris bdev_io.u.bdev.num_blocks = 32; 10404bd97621SJim Harris 10414bd97621SJim Harris /* This I/O run right up to, but does not cross, the boundary - so this should return false. */ 1042aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 10434bd97621SJim Harris 10444bd97621SJim Harris bdev_io.u.bdev.num_blocks = 33; 10454bd97621SJim Harris 10464bd97621SJim Harris /* This I/O spans a boundary. */ 1047aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == true); 10484bd97621SJim Harris } 10494bd97621SJim Harris 10504bd97621SJim Harris static void 10510e58d154SJim Harris bdev_io_split_test(void) 10524bd97621SJim Harris { 10534bd97621SJim Harris struct spdk_bdev *bdev; 1054fb0fe6b1SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 10554bd97621SJim Harris struct spdk_io_channel *io_ch; 10564bd97621SJim Harris struct spdk_bdev_opts bdev_opts = { 10574bd97621SJim Harris .bdev_io_pool_size = 512, 10584bd97621SJim Harris .bdev_io_cache_size = 64, 10594bd97621SJim Harris }; 10600df515a8SShuhei Matsumoto struct iovec iov[BDEV_IO_NUM_CHILD_IOV * 2]; 10613c7894ffSShuhei Matsumoto struct ut_expected_io *expected_io; 10620df515a8SShuhei Matsumoto uint64_t i; 10634bd97621SJim Harris int rc; 10644bd97621SJim Harris 10654bd97621SJim Harris rc = spdk_bdev_set_opts(&bdev_opts); 10664bd97621SJim Harris CU_ASSERT(rc == 0); 10674bd97621SJim Harris spdk_bdev_initialize(bdev_init_cb, NULL); 10684bd97621SJim Harris 10694bd97621SJim Harris bdev = allocate_bdev("bdev0"); 10704bd97621SJim Harris 1071*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 10724bd97621SJim Harris CU_ASSERT(rc == 0); 1073fb0fe6b1SShuhei Matsumoto SPDK_CU_ASSERT_FATAL(desc != NULL); 1074*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 10754bd97621SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 10764bd97621SJim Harris CU_ASSERT(io_ch != NULL); 10774bd97621SJim Harris 10784bd97621SJim Harris bdev->optimal_io_boundary = 16; 10794bd97621SJim Harris bdev->split_on_optimal_io_boundary = false; 10804bd97621SJim Harris 10814bd97621SJim Harris g_io_done = false; 10824bd97621SJim Harris 10834bd97621SJim Harris /* First test that the I/O does not get split if split_on_optimal_io_boundary == false. */ 10843c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 8, 1); 10853c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 8 * 512); 10863c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 10874bd97621SJim Harris 10884bd97621SJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL); 10894bd97621SJim Harris CU_ASSERT(rc == 0); 10904bd97621SJim Harris CU_ASSERT(g_io_done == false); 10914bd97621SJim Harris 10924bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 10934bd97621SJim Harris stub_complete_io(1); 10944bd97621SJim Harris CU_ASSERT(g_io_done == true); 10954bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 10964bd97621SJim Harris 10974bd97621SJim Harris bdev->split_on_optimal_io_boundary = true; 10984bd97621SJim Harris 10994bd97621SJim Harris /* Now test that a single-vector command is split correctly. 11004bd97621SJim Harris * Offset 14, length 8, payload 0xF000 11014bd97621SJim Harris * Child - Offset 14, length 2, payload 0xF000 11024bd97621SJim Harris * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 11034bd97621SJim Harris * 11048f33ef24SShuhei Matsumoto * Set up the expected values before calling spdk_bdev_read_blocks 11054bd97621SJim Harris */ 11064bd97621SJim Harris g_io_done = false; 11073c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1); 11083c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512); 11093c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 11104bd97621SJim Harris 11113c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1); 11123c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512); 11133c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 11144bd97621SJim Harris 11158f33ef24SShuhei Matsumoto /* spdk_bdev_read_blocks will submit the first child immediately. */ 11168f33ef24SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL); 11178f33ef24SShuhei Matsumoto CU_ASSERT(rc == 0); 11188f33ef24SShuhei Matsumoto CU_ASSERT(g_io_done == false); 11198f33ef24SShuhei Matsumoto 11205616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 11215616c1edSShuhei Matsumoto stub_complete_io(2); 11224bd97621SJim Harris CU_ASSERT(g_io_done == true); 11235616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 11244bd97621SJim Harris 11254bd97621SJim Harris /* Now set up a more complex, multi-vector command that needs to be split, 11264bd97621SJim Harris * including splitting iovecs. 11274bd97621SJim Harris */ 11284bd97621SJim Harris iov[0].iov_base = (void *)0x10000; 11294bd97621SJim Harris iov[0].iov_len = 512; 11304bd97621SJim Harris iov[1].iov_base = (void *)0x20000; 11314bd97621SJim Harris iov[1].iov_len = 20 * 512; 11324bd97621SJim Harris iov[2].iov_base = (void *)0x30000; 11334bd97621SJim Harris iov[2].iov_len = 11 * 512; 11344bd97621SJim Harris 11354bd97621SJim Harris g_io_done = false; 11363c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 2); 11373c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0x10000, 512); 11383c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x20000, 512); 11393c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 11404bd97621SJim Harris 11413c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 16, 1); 11423c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 512), 16 * 512); 11433c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 11444bd97621SJim Harris 11453c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 2); 11463c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 17 * 512), 3 * 512); 11473c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x30000, 11 * 512); 11483c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 11494bd97621SJim Harris 11508f33ef24SShuhei Matsumoto rc = spdk_bdev_writev_blocks(desc, io_ch, iov, 3, 14, 32, io_done, NULL); 11518f33ef24SShuhei Matsumoto CU_ASSERT(rc == 0); 11528f33ef24SShuhei Matsumoto CU_ASSERT(g_io_done == false); 11538f33ef24SShuhei Matsumoto 11545616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 11555616c1edSShuhei Matsumoto stub_complete_io(3); 11564bd97621SJim Harris CU_ASSERT(g_io_done == true); 11574bd97621SJim Harris 11580df515a8SShuhei Matsumoto /* Test multi vector command that needs to be split by strip and then needs to be 11590df515a8SShuhei Matsumoto * split further due to the capacity of child iovs. 11600df515a8SShuhei Matsumoto */ 11610df515a8SShuhei Matsumoto for (i = 0; i < BDEV_IO_NUM_CHILD_IOV * 2; i++) { 11620df515a8SShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 11630df515a8SShuhei Matsumoto iov[i].iov_len = 512; 11640df515a8SShuhei Matsumoto } 11650df515a8SShuhei Matsumoto 11660df515a8SShuhei Matsumoto bdev->optimal_io_boundary = BDEV_IO_NUM_CHILD_IOV; 11670df515a8SShuhei Matsumoto g_io_done = false; 11683c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, BDEV_IO_NUM_CHILD_IOV, 11693c7894ffSShuhei Matsumoto BDEV_IO_NUM_CHILD_IOV); 11700df515a8SShuhei Matsumoto for (i = 0; i < BDEV_IO_NUM_CHILD_IOV; i++) { 11713c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, i, (void *)((i + 1) * 0x10000), 512); 11720df515a8SShuhei Matsumoto } 11733c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 11740df515a8SShuhei Matsumoto 11753c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, BDEV_IO_NUM_CHILD_IOV, 11763c7894ffSShuhei Matsumoto BDEV_IO_NUM_CHILD_IOV, BDEV_IO_NUM_CHILD_IOV); 11770df515a8SShuhei Matsumoto for (i = 0; i < BDEV_IO_NUM_CHILD_IOV; i++) { 11783c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, i, 11793c7894ffSShuhei Matsumoto (void *)((i + 1 + BDEV_IO_NUM_CHILD_IOV) * 0x10000), 512); 11800df515a8SShuhei Matsumoto } 11813c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 11820df515a8SShuhei Matsumoto 11838f33ef24SShuhei Matsumoto rc = spdk_bdev_readv_blocks(desc, io_ch, iov, BDEV_IO_NUM_CHILD_IOV * 2, 0, 11848f33ef24SShuhei Matsumoto BDEV_IO_NUM_CHILD_IOV * 2, io_done, NULL); 11858f33ef24SShuhei Matsumoto CU_ASSERT(rc == 0); 11868f33ef24SShuhei Matsumoto CU_ASSERT(g_io_done == false); 11878f33ef24SShuhei Matsumoto 11880df515a8SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 11890df515a8SShuhei Matsumoto stub_complete_io(1); 11900df515a8SShuhei Matsumoto CU_ASSERT(g_io_done == false); 11910df515a8SShuhei Matsumoto 11920df515a8SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 11930df515a8SShuhei Matsumoto stub_complete_io(1); 11940df515a8SShuhei Matsumoto CU_ASSERT(g_io_done == true); 11955616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 11960df515a8SShuhei Matsumoto 11970df515a8SShuhei Matsumoto /* Test multi vector command that needs to be split by strip and then needs to be 1198598ba408Slorneli * split further due to the capacity of child iovs. In this case, the length of 1199598ba408Slorneli * the rest of iovec array with an I/O boundary is the multiple of block size. 1200598ba408Slorneli */ 1201598ba408Slorneli 1202598ba408Slorneli /* Fill iovec array for exactly one boundary. The iovec cnt for this boundary 1203598ba408Slorneli * is BDEV_IO_NUM_CHILD_IOV + 1, which exceeds the capacity of child iovs. 1204598ba408Slorneli */ 1205598ba408Slorneli for (i = 0; i < BDEV_IO_NUM_CHILD_IOV - 2; i++) { 1206598ba408Slorneli iov[i].iov_base = (void *)((i + 1) * 0x10000); 1207598ba408Slorneli iov[i].iov_len = 512; 1208598ba408Slorneli } 1209598ba408Slorneli for (i = BDEV_IO_NUM_CHILD_IOV - 2; i < BDEV_IO_NUM_CHILD_IOV; i++) { 1210598ba408Slorneli iov[i].iov_base = (void *)((i + 1) * 0x10000); 1211598ba408Slorneli iov[i].iov_len = 256; 1212598ba408Slorneli } 1213598ba408Slorneli iov[BDEV_IO_NUM_CHILD_IOV].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000); 1214598ba408Slorneli iov[BDEV_IO_NUM_CHILD_IOV].iov_len = 512; 1215598ba408Slorneli 1216598ba408Slorneli /* Add an extra iovec to trigger split */ 1217598ba408Slorneli iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000); 1218598ba408Slorneli iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_len = 512; 1219598ba408Slorneli 1220598ba408Slorneli bdev->optimal_io_boundary = BDEV_IO_NUM_CHILD_IOV; 1221598ba408Slorneli g_io_done = false; 1222598ba408Slorneli expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 1223598ba408Slorneli BDEV_IO_NUM_CHILD_IOV - 1, BDEV_IO_NUM_CHILD_IOV); 1224598ba408Slorneli for (i = 0; i < BDEV_IO_NUM_CHILD_IOV - 2; i++) { 1225598ba408Slorneli ut_expected_io_set_iov(expected_io, i, 1226598ba408Slorneli (void *)((i + 1) * 0x10000), 512); 1227598ba408Slorneli } 1228598ba408Slorneli for (i = BDEV_IO_NUM_CHILD_IOV - 2; i < BDEV_IO_NUM_CHILD_IOV; i++) { 1229598ba408Slorneli ut_expected_io_set_iov(expected_io, i, 1230598ba408Slorneli (void *)((i + 1) * 0x10000), 256); 1231598ba408Slorneli } 1232598ba408Slorneli TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1233598ba408Slorneli 1234598ba408Slorneli expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, BDEV_IO_NUM_CHILD_IOV - 1, 1235598ba408Slorneli 1, 1); 1236598ba408Slorneli ut_expected_io_set_iov(expected_io, 0, 1237598ba408Slorneli (void *)((BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000), 512); 1238598ba408Slorneli TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1239598ba408Slorneli 1240598ba408Slorneli expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, BDEV_IO_NUM_CHILD_IOV, 1241598ba408Slorneli 1, 1); 1242598ba408Slorneli ut_expected_io_set_iov(expected_io, 0, 1243598ba408Slorneli (void *)((BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000), 512); 1244598ba408Slorneli TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1245598ba408Slorneli 1246598ba408Slorneli rc = spdk_bdev_readv_blocks(desc, io_ch, iov, BDEV_IO_NUM_CHILD_IOV + 2, 0, 1247598ba408Slorneli BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 1248598ba408Slorneli CU_ASSERT(rc == 0); 1249598ba408Slorneli CU_ASSERT(g_io_done == false); 1250598ba408Slorneli 1251598ba408Slorneli CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1252598ba408Slorneli stub_complete_io(1); 1253598ba408Slorneli CU_ASSERT(g_io_done == false); 1254598ba408Slorneli 1255598ba408Slorneli CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 1256598ba408Slorneli stub_complete_io(2); 1257598ba408Slorneli CU_ASSERT(g_io_done == true); 1258598ba408Slorneli CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 1259598ba408Slorneli 1260598ba408Slorneli /* Test multi vector command that needs to be split by strip and then needs to be 1261efd7b514SChangpeng Liu * split further due to the capacity of child iovs, the child request offset should 1262efd7b514SChangpeng Liu * be rewind to last aligned offset and go success without error. 12630df515a8SShuhei Matsumoto */ 12640df515a8SShuhei Matsumoto for (i = 0; i < BDEV_IO_NUM_CHILD_IOV - 1; i++) { 12650df515a8SShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 12660df515a8SShuhei Matsumoto iov[i].iov_len = 512; 12670df515a8SShuhei Matsumoto } 12680df515a8SShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV - 1].iov_base = (void *)(BDEV_IO_NUM_CHILD_IOV * 0x10000); 12690df515a8SShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV - 1].iov_len = 256; 12700df515a8SShuhei Matsumoto 1271efd7b514SChangpeng Liu iov[BDEV_IO_NUM_CHILD_IOV].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000); 1272efd7b514SChangpeng Liu iov[BDEV_IO_NUM_CHILD_IOV].iov_len = 256; 1273efd7b514SChangpeng Liu 1274efd7b514SChangpeng Liu iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000); 1275efd7b514SChangpeng Liu iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_len = 512; 1276efd7b514SChangpeng Liu 12770df515a8SShuhei Matsumoto bdev->optimal_io_boundary = BDEV_IO_NUM_CHILD_IOV; 12780df515a8SShuhei Matsumoto g_io_done = false; 12790df515a8SShuhei Matsumoto g_io_status = 0; 1280efd7b514SChangpeng Liu /* The first expected io should be start from offset 0 to BDEV_IO_NUM_CHILD_IOV - 1 */ 1281efd7b514SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 1282efd7b514SChangpeng Liu BDEV_IO_NUM_CHILD_IOV - 1, BDEV_IO_NUM_CHILD_IOV - 1); 1283efd7b514SChangpeng Liu for (i = 0; i < BDEV_IO_NUM_CHILD_IOV - 1; i++) { 1284efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, i, 1285efd7b514SChangpeng Liu (void *)((i + 1) * 0x10000), 512); 1286efd7b514SChangpeng Liu } 1287efd7b514SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1288efd7b514SChangpeng Liu /* The second expected io should be start from offset BDEV_IO_NUM_CHILD_IOV - 1 to BDEV_IO_NUM_CHILD_IOV */ 1289efd7b514SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, BDEV_IO_NUM_CHILD_IOV - 1, 1290efd7b514SChangpeng Liu 1, 2); 1291efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, 0, 1292efd7b514SChangpeng Liu (void *)(BDEV_IO_NUM_CHILD_IOV * 0x10000), 256); 1293efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, 1, 1294efd7b514SChangpeng Liu (void *)((BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000), 256); 1295efd7b514SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1296efd7b514SChangpeng Liu /* The third expected io should be start from offset BDEV_IO_NUM_CHILD_IOV to BDEV_IO_NUM_CHILD_IOV + 1 */ 1297efd7b514SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, BDEV_IO_NUM_CHILD_IOV, 1298efd7b514SChangpeng Liu 1, 1); 1299efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, 0, 1300efd7b514SChangpeng Liu (void *)((BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000), 512); 1301efd7b514SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 13020df515a8SShuhei Matsumoto 13030df515a8SShuhei Matsumoto rc = spdk_bdev_readv_blocks(desc, io_ch, iov, BDEV_IO_NUM_CHILD_IOV * 2, 0, 1304efd7b514SChangpeng Liu BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 13050df515a8SShuhei Matsumoto CU_ASSERT(rc == 0); 1306efd7b514SChangpeng Liu CU_ASSERT(g_io_done == false); 1307efd7b514SChangpeng Liu 1308efd7b514SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1309efd7b514SChangpeng Liu stub_complete_io(1); 1310efd7b514SChangpeng Liu CU_ASSERT(g_io_done == false); 1311efd7b514SChangpeng Liu 1312efd7b514SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 1313efd7b514SChangpeng Liu stub_complete_io(2); 13140df515a8SShuhei Matsumoto CU_ASSERT(g_io_done == true); 1315efd7b514SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 13160df515a8SShuhei Matsumoto 13173deaf005SShuhei Matsumoto /* Test multi vector command that needs to be split due to the IO boundary and 13183deaf005SShuhei Matsumoto * the capacity of child iovs. Especially test the case when the command is 13193deaf005SShuhei Matsumoto * split due to the capacity of child iovs, the tail address is not aligned with 13203deaf005SShuhei Matsumoto * block size and is rewinded to the aligned address. 13213deaf005SShuhei Matsumoto * 13223deaf005SShuhei Matsumoto * The iovecs used in read request is complex but is based on the data 13233deaf005SShuhei Matsumoto * collected in the real issue. We change the base addresses but keep the lengths 13243deaf005SShuhei Matsumoto * not to loose the credibility of the test. 13253deaf005SShuhei Matsumoto */ 13263deaf005SShuhei Matsumoto bdev->optimal_io_boundary = 128; 13273deaf005SShuhei Matsumoto g_io_done = false; 13283deaf005SShuhei Matsumoto g_io_status = 0; 13293deaf005SShuhei Matsumoto 13303deaf005SShuhei Matsumoto for (i = 0; i < 31; i++) { 13313deaf005SShuhei Matsumoto iov[i].iov_base = (void *)(0xFEED0000000 + (i << 20)); 13323deaf005SShuhei Matsumoto iov[i].iov_len = 1024; 13333deaf005SShuhei Matsumoto } 13343deaf005SShuhei Matsumoto iov[31].iov_base = (void *)0xFEED1F00000; 13353deaf005SShuhei Matsumoto iov[31].iov_len = 32768; 13363deaf005SShuhei Matsumoto iov[32].iov_base = (void *)0xFEED2000000; 13373deaf005SShuhei Matsumoto iov[32].iov_len = 160; 13383deaf005SShuhei Matsumoto iov[33].iov_base = (void *)0xFEED2100000; 13393deaf005SShuhei Matsumoto iov[33].iov_len = 4096; 13403deaf005SShuhei Matsumoto iov[34].iov_base = (void *)0xFEED2200000; 13413deaf005SShuhei Matsumoto iov[34].iov_len = 4096; 13423deaf005SShuhei Matsumoto iov[35].iov_base = (void *)0xFEED2300000; 13433deaf005SShuhei Matsumoto iov[35].iov_len = 4096; 13443deaf005SShuhei Matsumoto iov[36].iov_base = (void *)0xFEED2400000; 13453deaf005SShuhei Matsumoto iov[36].iov_len = 4096; 13463deaf005SShuhei Matsumoto iov[37].iov_base = (void *)0xFEED2500000; 13473deaf005SShuhei Matsumoto iov[37].iov_len = 4096; 13483deaf005SShuhei Matsumoto iov[38].iov_base = (void *)0xFEED2600000; 13493deaf005SShuhei Matsumoto iov[38].iov_len = 4096; 13503deaf005SShuhei Matsumoto iov[39].iov_base = (void *)0xFEED2700000; 13513deaf005SShuhei Matsumoto iov[39].iov_len = 4096; 13523deaf005SShuhei Matsumoto iov[40].iov_base = (void *)0xFEED2800000; 13533deaf005SShuhei Matsumoto iov[40].iov_len = 4096; 13543deaf005SShuhei Matsumoto iov[41].iov_base = (void *)0xFEED2900000; 13553deaf005SShuhei Matsumoto iov[41].iov_len = 4096; 13563deaf005SShuhei Matsumoto iov[42].iov_base = (void *)0xFEED2A00000; 13573deaf005SShuhei Matsumoto iov[42].iov_len = 4096; 13583deaf005SShuhei Matsumoto iov[43].iov_base = (void *)0xFEED2B00000; 13593deaf005SShuhei Matsumoto iov[43].iov_len = 12288; 13603deaf005SShuhei Matsumoto iov[44].iov_base = (void *)0xFEED2C00000; 13613deaf005SShuhei Matsumoto iov[44].iov_len = 8192; 13623deaf005SShuhei Matsumoto iov[45].iov_base = (void *)0xFEED2F00000; 13633deaf005SShuhei Matsumoto iov[45].iov_len = 4096; 13643deaf005SShuhei Matsumoto iov[46].iov_base = (void *)0xFEED3000000; 13653deaf005SShuhei Matsumoto iov[46].iov_len = 4096; 13663deaf005SShuhei Matsumoto iov[47].iov_base = (void *)0xFEED3100000; 13673deaf005SShuhei Matsumoto iov[47].iov_len = 4096; 13683deaf005SShuhei Matsumoto iov[48].iov_base = (void *)0xFEED3200000; 13693deaf005SShuhei Matsumoto iov[48].iov_len = 24576; 13703deaf005SShuhei Matsumoto iov[49].iov_base = (void *)0xFEED3300000; 13713deaf005SShuhei Matsumoto iov[49].iov_len = 16384; 13723deaf005SShuhei Matsumoto iov[50].iov_base = (void *)0xFEED3400000; 13733deaf005SShuhei Matsumoto iov[50].iov_len = 12288; 13743deaf005SShuhei Matsumoto iov[51].iov_base = (void *)0xFEED3500000; 13753deaf005SShuhei Matsumoto iov[51].iov_len = 4096; 13763deaf005SShuhei Matsumoto iov[52].iov_base = (void *)0xFEED3600000; 13773deaf005SShuhei Matsumoto iov[52].iov_len = 4096; 13783deaf005SShuhei Matsumoto iov[53].iov_base = (void *)0xFEED3700000; 13793deaf005SShuhei Matsumoto iov[53].iov_len = 4096; 13803deaf005SShuhei Matsumoto iov[54].iov_base = (void *)0xFEED3800000; 13813deaf005SShuhei Matsumoto iov[54].iov_len = 28672; 13823deaf005SShuhei Matsumoto iov[55].iov_base = (void *)0xFEED3900000; 13833deaf005SShuhei Matsumoto iov[55].iov_len = 20480; 13843deaf005SShuhei Matsumoto iov[56].iov_base = (void *)0xFEED3A00000; 13853deaf005SShuhei Matsumoto iov[56].iov_len = 4096; 13863deaf005SShuhei Matsumoto iov[57].iov_base = (void *)0xFEED3B00000; 13873deaf005SShuhei Matsumoto iov[57].iov_len = 12288; 13883deaf005SShuhei Matsumoto iov[58].iov_base = (void *)0xFEED3C00000; 13893deaf005SShuhei Matsumoto iov[58].iov_len = 4096; 13903deaf005SShuhei Matsumoto iov[59].iov_base = (void *)0xFEED3D00000; 13913deaf005SShuhei Matsumoto iov[59].iov_len = 4096; 13923deaf005SShuhei Matsumoto iov[60].iov_base = (void *)0xFEED3E00000; 13933deaf005SShuhei Matsumoto iov[60].iov_len = 352; 13943deaf005SShuhei Matsumoto 13953deaf005SShuhei Matsumoto /* The 1st child IO must be from iov[0] to iov[31] split by the capacity 13963deaf005SShuhei Matsumoto * of child iovs, 13973deaf005SShuhei Matsumoto */ 13983deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 126, 32); 13993deaf005SShuhei Matsumoto for (i = 0; i < 32; i++) { 14003deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, i, iov[i].iov_base, iov[i].iov_len); 14013deaf005SShuhei Matsumoto } 14023deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14033deaf005SShuhei Matsumoto 14043deaf005SShuhei Matsumoto /* The 2nd child IO must be from iov[32] to the first 864 bytes of iov[33] 14053deaf005SShuhei Matsumoto * split by the IO boundary requirement. 14063deaf005SShuhei Matsumoto */ 14073deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 126, 2, 2); 14083deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, iov[32].iov_base, iov[32].iov_len); 14093deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[33].iov_base, 864); 14103deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14113deaf005SShuhei Matsumoto 14123deaf005SShuhei Matsumoto /* The 3rd child IO must be from the remaining 3232 bytes of iov[33] to 14133deaf005SShuhei Matsumoto * the first 864 bytes of iov[46] split by the IO boundary requirement. 14143deaf005SShuhei Matsumoto */ 14153deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 128, 128, 14); 14163deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[33].iov_base + 864), 14173deaf005SShuhei Matsumoto iov[33].iov_len - 864); 14183deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[34].iov_base, iov[34].iov_len); 14193deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[35].iov_base, iov[35].iov_len); 14203deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 3, iov[36].iov_base, iov[36].iov_len); 14213deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 4, iov[37].iov_base, iov[37].iov_len); 14223deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 5, iov[38].iov_base, iov[38].iov_len); 14233deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 6, iov[39].iov_base, iov[39].iov_len); 14243deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 7, iov[40].iov_base, iov[40].iov_len); 14253deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 8, iov[41].iov_base, iov[41].iov_len); 14263deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 9, iov[42].iov_base, iov[42].iov_len); 14273deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 10, iov[43].iov_base, iov[43].iov_len); 14283deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 11, iov[44].iov_base, iov[44].iov_len); 14293deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 12, iov[45].iov_base, iov[45].iov_len); 14303deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 13, iov[46].iov_base, 864); 14313deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14323deaf005SShuhei Matsumoto 14333deaf005SShuhei Matsumoto /* The 4th child IO must be from the remaining 3232 bytes of iov[46] to the 14343deaf005SShuhei Matsumoto * first 864 bytes of iov[52] split by the IO boundary requirement. 14353deaf005SShuhei Matsumoto */ 14363deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 256, 128, 7); 14373deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[46].iov_base + 864), 14383deaf005SShuhei Matsumoto iov[46].iov_len - 864); 14393deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[47].iov_base, iov[47].iov_len); 14403deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[48].iov_base, iov[48].iov_len); 14413deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 3, iov[49].iov_base, iov[49].iov_len); 14423deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 4, iov[50].iov_base, iov[50].iov_len); 14433deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 5, iov[51].iov_base, iov[51].iov_len); 14443deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 6, iov[52].iov_base, 864); 14453deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14463deaf005SShuhei Matsumoto 14473deaf005SShuhei Matsumoto /* The 5th child IO must be from the remaining 3232 bytes of iov[52] to 14483deaf005SShuhei Matsumoto * the first 4096 bytes of iov[57] split by the IO boundary requirement. 14493deaf005SShuhei Matsumoto */ 14503deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 384, 128, 6); 14513deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[52].iov_base + 864), 14523deaf005SShuhei Matsumoto iov[52].iov_len - 864); 14533deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[53].iov_base, iov[53].iov_len); 14543deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[54].iov_base, iov[54].iov_len); 14553deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 3, iov[55].iov_base, iov[55].iov_len); 14563deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 4, iov[56].iov_base, iov[56].iov_len); 14573deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 5, iov[57].iov_base, 4960); 14583deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14593deaf005SShuhei Matsumoto 14603deaf005SShuhei Matsumoto /* The 6th child IO must be from the remaining 7328 bytes of iov[57] 14613deaf005SShuhei Matsumoto * to the first 3936 bytes of iov[58] split by the capacity of child iovs. 14623deaf005SShuhei Matsumoto */ 14633deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 512, 30, 3); 14643deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[57].iov_base + 4960), 14653deaf005SShuhei Matsumoto iov[57].iov_len - 4960); 14663deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[58].iov_base, iov[58].iov_len); 14673deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[59].iov_base, 3936); 14683deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14693deaf005SShuhei Matsumoto 14703deaf005SShuhei Matsumoto /* The 7th child IO is from the remaining 160 bytes of iov[59] and iov[60]. */ 14713deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 542, 1, 2); 14723deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[59].iov_base + 3936), 14733deaf005SShuhei Matsumoto iov[59].iov_len - 3936); 14743deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[60].iov_base, iov[60].iov_len); 14753deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14763deaf005SShuhei Matsumoto 14773deaf005SShuhei Matsumoto rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 61, 0, 543, io_done, NULL); 14783deaf005SShuhei Matsumoto CU_ASSERT(rc == 0); 14793deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == false); 14803deaf005SShuhei Matsumoto 14813deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 14823deaf005SShuhei Matsumoto stub_complete_io(1); 14833deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == false); 14843deaf005SShuhei Matsumoto 14853deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 5); 14863deaf005SShuhei Matsumoto stub_complete_io(5); 14873deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == false); 14883deaf005SShuhei Matsumoto 14893deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 14903deaf005SShuhei Matsumoto stub_complete_io(1); 14913deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == true); 14923deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 14933deaf005SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 14943deaf005SShuhei Matsumoto 14954f860d7eSJim Harris /* Test a WRITE_ZEROES that would span an I/O boundary. WRITE_ZEROES should not be 14964f860d7eSJim Harris * split, so test that. 14974bd97621SJim Harris */ 14984bd97621SJim Harris bdev->optimal_io_boundary = 15; 14994bd97621SJim Harris g_io_done = false; 15003c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, 9, 36, 0); 15013c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 15024bd97621SJim Harris 15034bd97621SJim Harris rc = spdk_bdev_write_zeroes_blocks(desc, io_ch, 9, 36, io_done, NULL); 15044bd97621SJim Harris CU_ASSERT(rc == 0); 15054bd97621SJim Harris CU_ASSERT(g_io_done == false); 15064bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 15074bd97621SJim Harris stub_complete_io(1); 15084bd97621SJim Harris CU_ASSERT(g_io_done == true); 15094bd97621SJim Harris 15104f860d7eSJim Harris /* Test an UNMAP. This should also not be split. */ 15114bd97621SJim Harris bdev->optimal_io_boundary = 16; 15124bd97621SJim Harris g_io_done = false; 15133c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_UNMAP, 15, 2, 0); 15143c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 15154bd97621SJim Harris 15164bd97621SJim Harris rc = spdk_bdev_unmap_blocks(desc, io_ch, 15, 2, io_done, NULL); 15174bd97621SJim Harris CU_ASSERT(rc == 0); 15184bd97621SJim Harris CU_ASSERT(g_io_done == false); 15194bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 15204bd97621SJim Harris stub_complete_io(1); 15214bd97621SJim Harris CU_ASSERT(g_io_done == true); 15224bd97621SJim Harris 15234f860d7eSJim Harris /* Test a FLUSH. This should also not be split. */ 15244bd97621SJim Harris bdev->optimal_io_boundary = 16; 15254bd97621SJim Harris g_io_done = false; 15263c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_FLUSH, 15, 2, 0); 15273c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 15284bd97621SJim Harris 15294bd97621SJim Harris rc = spdk_bdev_flush_blocks(desc, io_ch, 15, 2, io_done, NULL); 15304bd97621SJim Harris CU_ASSERT(rc == 0); 15314bd97621SJim Harris CU_ASSERT(g_io_done == false); 15324bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 15334bd97621SJim Harris stub_complete_io(1); 15344bd97621SJim Harris CU_ASSERT(g_io_done == true); 15354bd97621SJim Harris 15363c7894ffSShuhei Matsumoto CU_ASSERT(TAILQ_EMPTY(&g_bdev_ut_channel->expected_io)); 15374bd97621SJim Harris 1538c55c85f8SChangpeng Liu /* Children requests return an error status */ 1539c55c85f8SChangpeng Liu bdev->optimal_io_boundary = 16; 1540c55c85f8SChangpeng Liu iov[0].iov_base = (void *)0x10000; 1541c55c85f8SChangpeng Liu iov[0].iov_len = 512 * 64; 1542c55c85f8SChangpeng Liu g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 1543c55c85f8SChangpeng Liu g_io_done = false; 1544c55c85f8SChangpeng Liu g_io_status = SPDK_BDEV_IO_STATUS_SUCCESS; 1545c55c85f8SChangpeng Liu 1546c55c85f8SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 1, 1, 64, io_done, NULL); 1547c55c85f8SChangpeng Liu CU_ASSERT(rc == 0); 1548c55c85f8SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 5); 1549c55c85f8SChangpeng Liu stub_complete_io(4); 1550c55c85f8SChangpeng Liu CU_ASSERT(g_io_done == false); 1551c55c85f8SChangpeng Liu CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 1552c55c85f8SChangpeng Liu stub_complete_io(1); 1553c55c85f8SChangpeng Liu CU_ASSERT(g_io_done == true); 1554c55c85f8SChangpeng Liu CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 1555c55c85f8SChangpeng Liu 1556089d178aSShuhei Matsumoto /* Test if a multi vector command terminated with failure before continueing 1557089d178aSShuhei Matsumoto * splitting process when one of child I/O failed. 1558089d178aSShuhei Matsumoto * The multi vector command is as same as the above that needs to be split by strip 1559089d178aSShuhei Matsumoto * and then needs to be split further due to the capacity of child iovs. 1560089d178aSShuhei Matsumoto */ 1561089d178aSShuhei Matsumoto for (i = 0; i < BDEV_IO_NUM_CHILD_IOV - 1; i++) { 1562089d178aSShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 1563089d178aSShuhei Matsumoto iov[i].iov_len = 512; 1564089d178aSShuhei Matsumoto } 1565089d178aSShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV - 1].iov_base = (void *)(BDEV_IO_NUM_CHILD_IOV * 0x10000); 1566089d178aSShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV - 1].iov_len = 256; 1567089d178aSShuhei Matsumoto 1568089d178aSShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000); 1569089d178aSShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV].iov_len = 256; 1570089d178aSShuhei Matsumoto 1571089d178aSShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000); 1572089d178aSShuhei Matsumoto iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_len = 512; 1573089d178aSShuhei Matsumoto 1574089d178aSShuhei Matsumoto bdev->optimal_io_boundary = BDEV_IO_NUM_CHILD_IOV; 1575089d178aSShuhei Matsumoto 1576089d178aSShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 1577089d178aSShuhei Matsumoto g_io_done = false; 1578089d178aSShuhei Matsumoto g_io_status = SPDK_BDEV_IO_STATUS_SUCCESS; 1579089d178aSShuhei Matsumoto 1580089d178aSShuhei Matsumoto rc = spdk_bdev_readv_blocks(desc, io_ch, iov, BDEV_IO_NUM_CHILD_IOV * 2, 0, 1581089d178aSShuhei Matsumoto BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 1582089d178aSShuhei Matsumoto CU_ASSERT(rc == 0); 1583089d178aSShuhei Matsumoto CU_ASSERT(g_io_done == false); 1584089d178aSShuhei Matsumoto 1585089d178aSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1586089d178aSShuhei Matsumoto stub_complete_io(1); 1587089d178aSShuhei Matsumoto CU_ASSERT(g_io_done == true); 1588089d178aSShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 1589089d178aSShuhei Matsumoto 1590089d178aSShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 1591089d178aSShuhei Matsumoto 1592ebacdcd9Spaul luse /* for this test we will create the following conditions to hit the code path where 1593ebacdcd9Spaul luse * we are trying to send and IO following a split that has no iovs because we had to 1594ebacdcd9Spaul luse * trim them for alignment reasons. 1595ebacdcd9Spaul luse * 1596ebacdcd9Spaul luse * - 16K boundary, our IO will start at offset 0 with a length of 0x4200 1597ebacdcd9Spaul luse * - Our IOVs are 0x212 in size so that we run into the 16K boundary at child IOV 1598ebacdcd9Spaul luse * position 30 and overshoot by 0x2e. 1599ebacdcd9Spaul luse * - That means we'll send the IO and loop back to pick up the remaining bytes at 1600ebacdcd9Spaul luse * child IOV index 31. When we do, we find that we have to shorten index 31 by 0x2e 1601ebacdcd9Spaul luse * which eliniates that vector so we just send the first split IO with 30 vectors 1602ebacdcd9Spaul luse * and let the completion pick up the last 2 vectors. 1603ebacdcd9Spaul luse */ 1604ebacdcd9Spaul luse bdev->optimal_io_boundary = 32; 1605ebacdcd9Spaul luse bdev->split_on_optimal_io_boundary = true; 1606ebacdcd9Spaul luse g_io_done = false; 1607ebacdcd9Spaul luse 1608ebacdcd9Spaul luse /* Init all parent IOVs to 0x212 */ 1609ebacdcd9Spaul luse for (i = 0; i < BDEV_IO_NUM_CHILD_IOV + 2; i++) { 1610ebacdcd9Spaul luse iov[i].iov_base = (void *)((i + 1) * 0x10000); 1611ebacdcd9Spaul luse iov[i].iov_len = 0x212; 1612ebacdcd9Spaul luse } 1613ebacdcd9Spaul luse 1614ebacdcd9Spaul luse expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, BDEV_IO_NUM_CHILD_IOV, 1615ebacdcd9Spaul luse BDEV_IO_NUM_CHILD_IOV - 1); 1616ebacdcd9Spaul luse /* expect 0-29 to be 1:1 with the parent iov */ 1617ebacdcd9Spaul luse for (i = 0; i < BDEV_IO_NUM_CHILD_IOV - 2; i++) { 1618ebacdcd9Spaul luse ut_expected_io_set_iov(expected_io, i, iov[i].iov_base, iov[i].iov_len); 1619ebacdcd9Spaul luse } 1620ebacdcd9Spaul luse 1621ebacdcd9Spaul luse /* expect index 30 to be shortened to 0x1e4 (0x212 - 0x1e) because of the alignment 1622ebacdcd9Spaul luse * where 0x1e is the amount we overshot the 16K boundary 1623ebacdcd9Spaul luse */ 1624ebacdcd9Spaul luse ut_expected_io_set_iov(expected_io, BDEV_IO_NUM_CHILD_IOV - 2, 1625ebacdcd9Spaul luse (void *)(iov[BDEV_IO_NUM_CHILD_IOV - 2].iov_base), 0x1e4); 1626ebacdcd9Spaul luse TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1627ebacdcd9Spaul luse 1628ebacdcd9Spaul luse /* 2nd child IO will have 2 remaining vectors, one to pick up from the one that was 1629ebacdcd9Spaul luse * shortened that take it to the next boundary and then a final one to get us to 1630ebacdcd9Spaul luse * 0x4200 bytes for the IO. 1631ebacdcd9Spaul luse */ 1632ebacdcd9Spaul luse expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, BDEV_IO_NUM_CHILD_IOV, 1633ebacdcd9Spaul luse BDEV_IO_NUM_CHILD_IOV, 2); 1634ebacdcd9Spaul luse /* position 30 picked up the remaining bytes to the next boundary */ 1635ebacdcd9Spaul luse ut_expected_io_set_iov(expected_io, 0, 1636ebacdcd9Spaul luse (void *)(iov[BDEV_IO_NUM_CHILD_IOV - 2].iov_base + 0x1e4), 0x2e); 1637ebacdcd9Spaul luse 1638ebacdcd9Spaul luse /* position 31 picked the the rest of the trasnfer to get us to 0x4200 */ 1639ebacdcd9Spaul luse ut_expected_io_set_iov(expected_io, 1, 1640ebacdcd9Spaul luse (void *)(iov[BDEV_IO_NUM_CHILD_IOV - 1].iov_base), 0x1d2); 1641ebacdcd9Spaul luse TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1642ebacdcd9Spaul luse 1643ebacdcd9Spaul luse rc = spdk_bdev_readv_blocks(desc, io_ch, iov, BDEV_IO_NUM_CHILD_IOV + 1, 0, 1644ebacdcd9Spaul luse BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 1645ebacdcd9Spaul luse CU_ASSERT(rc == 0); 1646ebacdcd9Spaul luse CU_ASSERT(g_io_done == false); 1647ebacdcd9Spaul luse 1648ebacdcd9Spaul luse CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1649ebacdcd9Spaul luse stub_complete_io(1); 1650ebacdcd9Spaul luse CU_ASSERT(g_io_done == false); 1651ebacdcd9Spaul luse 1652ebacdcd9Spaul luse CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1653ebacdcd9Spaul luse stub_complete_io(1); 1654ebacdcd9Spaul luse CU_ASSERT(g_io_done == true); 1655ebacdcd9Spaul luse CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 1656ebacdcd9Spaul luse 16574bd97621SJim Harris spdk_put_io_channel(io_ch); 16584bd97621SJim Harris spdk_bdev_close(desc); 16594bd97621SJim Harris free_bdev(bdev); 16604bd97621SJim Harris spdk_bdev_finish(bdev_fini_cb, NULL); 1661270a25dfSBen Walker poll_threads(); 16624bd97621SJim Harris } 16634bd97621SJim Harris 1664a8780177SShuhei Matsumoto static void 1665a8780177SShuhei Matsumoto bdev_io_split_with_io_wait(void) 1666a8780177SShuhei Matsumoto { 1667a8780177SShuhei Matsumoto struct spdk_bdev *bdev; 1668b701087fSDarek Stojaczyk struct spdk_bdev_desc *desc = NULL; 1669a8780177SShuhei Matsumoto struct spdk_io_channel *io_ch; 1670a8780177SShuhei Matsumoto struct spdk_bdev_channel *channel; 1671a8780177SShuhei Matsumoto struct spdk_bdev_mgmt_channel *mgmt_ch; 1672a8780177SShuhei Matsumoto struct spdk_bdev_opts bdev_opts = { 1673a8780177SShuhei Matsumoto .bdev_io_pool_size = 2, 1674a8780177SShuhei Matsumoto .bdev_io_cache_size = 1, 1675a8780177SShuhei Matsumoto }; 16765616c1edSShuhei Matsumoto struct iovec iov[3]; 1677a8780177SShuhei Matsumoto struct ut_expected_io *expected_io; 1678a8780177SShuhei Matsumoto int rc; 1679a8780177SShuhei Matsumoto 1680a8780177SShuhei Matsumoto rc = spdk_bdev_set_opts(&bdev_opts); 1681a8780177SShuhei Matsumoto CU_ASSERT(rc == 0); 1682a8780177SShuhei Matsumoto spdk_bdev_initialize(bdev_init_cb, NULL); 1683a8780177SShuhei Matsumoto 1684a8780177SShuhei Matsumoto bdev = allocate_bdev("bdev0"); 1685a8780177SShuhei Matsumoto 1686*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 1687a8780177SShuhei Matsumoto CU_ASSERT(rc == 0); 1688a8780177SShuhei Matsumoto CU_ASSERT(desc != NULL); 1689*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 1690a8780177SShuhei Matsumoto io_ch = spdk_bdev_get_io_channel(desc); 1691a8780177SShuhei Matsumoto CU_ASSERT(io_ch != NULL); 1692a8780177SShuhei Matsumoto channel = spdk_io_channel_get_ctx(io_ch); 1693a8780177SShuhei Matsumoto mgmt_ch = channel->shared_resource->mgmt_ch; 1694a8780177SShuhei Matsumoto 1695a8780177SShuhei Matsumoto bdev->optimal_io_boundary = 16; 1696a8780177SShuhei Matsumoto bdev->split_on_optimal_io_boundary = true; 1697a8780177SShuhei Matsumoto 1698a8780177SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 1699a8780177SShuhei Matsumoto CU_ASSERT(rc == 0); 1700a8780177SShuhei Matsumoto 1701a8780177SShuhei Matsumoto /* Now test that a single-vector command is split correctly. 1702a8780177SShuhei Matsumoto * Offset 14, length 8, payload 0xF000 1703a8780177SShuhei Matsumoto * Child - Offset 14, length 2, payload 0xF000 1704a8780177SShuhei Matsumoto * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 1705a8780177SShuhei Matsumoto * 1706a8780177SShuhei Matsumoto * Set up the expected values before calling spdk_bdev_read_blocks 1707a8780177SShuhei Matsumoto */ 1708a8780177SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1); 1709a8780177SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512); 1710a8780177SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1711a8780177SShuhei Matsumoto 1712a8780177SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1); 1713a8780177SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512); 1714a8780177SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1715a8780177SShuhei Matsumoto 17165616c1edSShuhei Matsumoto /* The following children will be submitted sequentially due to the capacity of 17175616c1edSShuhei Matsumoto * spdk_bdev_io. 17185616c1edSShuhei Matsumoto */ 17195616c1edSShuhei Matsumoto 1720a8780177SShuhei Matsumoto /* The first child I/O will be queued to wait until an spdk_bdev_io becomes available */ 1721a8780177SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL); 1722a8780177SShuhei Matsumoto CU_ASSERT(rc == 0); 1723a8780177SShuhei Matsumoto CU_ASSERT(!TAILQ_EMPTY(&mgmt_ch->io_wait_queue)); 1724a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1725a8780177SShuhei Matsumoto 1726a8780177SShuhei Matsumoto /* Completing the first read I/O will submit the first child */ 1727a8780177SShuhei Matsumoto stub_complete_io(1); 1728a8780177SShuhei Matsumoto CU_ASSERT(TAILQ_EMPTY(&mgmt_ch->io_wait_queue)); 1729a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1730a8780177SShuhei Matsumoto 1731a8780177SShuhei Matsumoto /* Completing the first child will submit the second child */ 1732a8780177SShuhei Matsumoto stub_complete_io(1); 1733a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1734a8780177SShuhei Matsumoto 1735a8780177SShuhei Matsumoto /* Complete the second child I/O. This should result in our callback getting 1736a8780177SShuhei Matsumoto * invoked since the parent I/O is now complete. 1737a8780177SShuhei Matsumoto */ 1738a8780177SShuhei Matsumoto stub_complete_io(1); 1739a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 1740a8780177SShuhei Matsumoto 17415616c1edSShuhei Matsumoto /* Now set up a more complex, multi-vector command that needs to be split, 17425616c1edSShuhei Matsumoto * including splitting iovecs. 17435616c1edSShuhei Matsumoto */ 17445616c1edSShuhei Matsumoto iov[0].iov_base = (void *)0x10000; 17455616c1edSShuhei Matsumoto iov[0].iov_len = 512; 17465616c1edSShuhei Matsumoto iov[1].iov_base = (void *)0x20000; 17475616c1edSShuhei Matsumoto iov[1].iov_len = 20 * 512; 17485616c1edSShuhei Matsumoto iov[2].iov_base = (void *)0x30000; 17495616c1edSShuhei Matsumoto iov[2].iov_len = 11 * 512; 17505616c1edSShuhei Matsumoto 17515616c1edSShuhei Matsumoto g_io_done = false; 17525616c1edSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 2); 17535616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0x10000, 512); 17545616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x20000, 512); 17555616c1edSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 17565616c1edSShuhei Matsumoto 17575616c1edSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 16, 1); 17585616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 512), 16 * 512); 17595616c1edSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 17605616c1edSShuhei Matsumoto 17615616c1edSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 2); 17625616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 17 * 512), 3 * 512); 17635616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x30000, 11 * 512); 17645616c1edSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 17655616c1edSShuhei Matsumoto 17665616c1edSShuhei Matsumoto rc = spdk_bdev_writev_blocks(desc, io_ch, iov, 3, 14, 32, io_done, NULL); 17675616c1edSShuhei Matsumoto CU_ASSERT(rc == 0); 17685616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == false); 17695616c1edSShuhei Matsumoto 17705616c1edSShuhei Matsumoto /* The following children will be submitted sequentially due to the capacity of 17715616c1edSShuhei Matsumoto * spdk_bdev_io. 17725616c1edSShuhei Matsumoto */ 17735616c1edSShuhei Matsumoto 17745616c1edSShuhei Matsumoto /* Completing the first child will submit the second child */ 17755616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 17765616c1edSShuhei Matsumoto stub_complete_io(1); 17775616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == false); 17785616c1edSShuhei Matsumoto 17795616c1edSShuhei Matsumoto /* Completing the second child will submit the third child */ 17805616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 17815616c1edSShuhei Matsumoto stub_complete_io(1); 17825616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == false); 17835616c1edSShuhei Matsumoto 17845616c1edSShuhei Matsumoto /* Completing the third child will result in our callback getting invoked 17855616c1edSShuhei Matsumoto * since the parent I/O is now complete. 17865616c1edSShuhei Matsumoto */ 17875616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 17885616c1edSShuhei Matsumoto stub_complete_io(1); 17895616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == true); 17905616c1edSShuhei Matsumoto 1791a8780177SShuhei Matsumoto CU_ASSERT(TAILQ_EMPTY(&g_bdev_ut_channel->expected_io)); 1792a8780177SShuhei Matsumoto 1793a8780177SShuhei Matsumoto spdk_put_io_channel(io_ch); 1794a8780177SShuhei Matsumoto spdk_bdev_close(desc); 1795a8780177SShuhei Matsumoto free_bdev(bdev); 1796a8780177SShuhei Matsumoto spdk_bdev_finish(bdev_fini_cb, NULL); 1797270a25dfSBen Walker poll_threads(); 1798a8780177SShuhei Matsumoto } 1799a8780177SShuhei Matsumoto 1800dadd2a6dSPiotr Pelplinski static void 1801dadd2a6dSPiotr Pelplinski bdev_io_alignment(void) 1802dadd2a6dSPiotr Pelplinski { 1803dadd2a6dSPiotr Pelplinski struct spdk_bdev *bdev; 1804e2ce08cfSTomasz Zawadzki struct spdk_bdev_desc *desc = NULL; 1805dadd2a6dSPiotr Pelplinski struct spdk_io_channel *io_ch; 1806dadd2a6dSPiotr Pelplinski struct spdk_bdev_opts bdev_opts = { 1807dadd2a6dSPiotr Pelplinski .bdev_io_pool_size = 20, 1808dadd2a6dSPiotr Pelplinski .bdev_io_cache_size = 2, 1809dadd2a6dSPiotr Pelplinski }; 1810dadd2a6dSPiotr Pelplinski int rc; 18119714818dSyidong0635 void *buf = NULL; 1812dadd2a6dSPiotr Pelplinski struct iovec iovs[2]; 1813dadd2a6dSPiotr Pelplinski int iovcnt; 1814dadd2a6dSPiotr Pelplinski uint64_t alignment; 1815dadd2a6dSPiotr Pelplinski 1816dadd2a6dSPiotr Pelplinski rc = spdk_bdev_set_opts(&bdev_opts); 1817dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1818dadd2a6dSPiotr Pelplinski spdk_bdev_initialize(bdev_init_cb, NULL); 1819dadd2a6dSPiotr Pelplinski 182080da9548SMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 1821dadd2a6dSPiotr Pelplinski bdev = allocate_bdev("bdev0"); 1822dadd2a6dSPiotr Pelplinski 1823*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 1824dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1825dadd2a6dSPiotr Pelplinski CU_ASSERT(desc != NULL); 1826*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 1827dadd2a6dSPiotr Pelplinski io_ch = spdk_bdev_get_io_channel(desc); 1828dadd2a6dSPiotr Pelplinski CU_ASSERT(io_ch != NULL); 1829dadd2a6dSPiotr Pelplinski 1830dadd2a6dSPiotr Pelplinski /* Create aligned buffer */ 1831dadd2a6dSPiotr Pelplinski rc = posix_memalign(&buf, 4096, 8192); 1832dadd2a6dSPiotr Pelplinski SPDK_CU_ASSERT_FATAL(rc == 0); 1833dadd2a6dSPiotr Pelplinski 1834dadd2a6dSPiotr Pelplinski /* Pass aligned single buffer with no alignment required */ 1835dadd2a6dSPiotr Pelplinski alignment = 1; 1836dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1837dadd2a6dSPiotr Pelplinski 1838dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf, 0, 1, io_done, NULL); 1839dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1840dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1841dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1842dadd2a6dSPiotr Pelplinski alignment)); 1843dadd2a6dSPiotr Pelplinski 1844dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf, 0, 1, io_done, NULL); 1845dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1846dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1847dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1848dadd2a6dSPiotr Pelplinski alignment)); 1849dadd2a6dSPiotr Pelplinski 1850dadd2a6dSPiotr Pelplinski /* Pass unaligned single buffer with no alignment required */ 1851dadd2a6dSPiotr Pelplinski alignment = 1; 1852dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1853dadd2a6dSPiotr Pelplinski 1854dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 1855dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1856dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1857dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == buf + 4); 1858dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1859dadd2a6dSPiotr Pelplinski 1860dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 1861dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1862dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1863dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == buf + 4); 1864dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1865dadd2a6dSPiotr Pelplinski 1866dadd2a6dSPiotr Pelplinski /* Pass unaligned single buffer with 512 alignment required */ 1867dadd2a6dSPiotr Pelplinski alignment = 512; 1868dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1869dadd2a6dSPiotr Pelplinski 1870dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 1871dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1872dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1); 1873dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov); 1874dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1875dadd2a6dSPiotr Pelplinski alignment)); 1876dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1877dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1878dadd2a6dSPiotr Pelplinski 1879dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 1880dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1881dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1); 1882dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov); 1883dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1884dadd2a6dSPiotr Pelplinski alignment)); 1885dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1886dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1887dadd2a6dSPiotr Pelplinski 1888dadd2a6dSPiotr Pelplinski /* Pass unaligned single buffer with 4096 alignment required */ 1889dadd2a6dSPiotr Pelplinski alignment = 4096; 1890dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1891dadd2a6dSPiotr Pelplinski 1892dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf + 8, 0, 1, io_done, NULL); 1893dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1894dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1); 1895dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov); 1896dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1897dadd2a6dSPiotr Pelplinski alignment)); 1898dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1899dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1900dadd2a6dSPiotr Pelplinski 1901dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf + 8, 0, 1, io_done, NULL); 1902dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1903dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 1); 1904dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov); 1905dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1906dadd2a6dSPiotr Pelplinski alignment)); 1907dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1908dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1909dadd2a6dSPiotr Pelplinski 1910dadd2a6dSPiotr Pelplinski /* Pass aligned iovs with no alignment required */ 1911dadd2a6dSPiotr Pelplinski alignment = 1; 1912dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1913dadd2a6dSPiotr Pelplinski 1914dadd2a6dSPiotr Pelplinski iovcnt = 1; 1915dadd2a6dSPiotr Pelplinski iovs[0].iov_base = buf; 1916dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 512; 1917dadd2a6dSPiotr Pelplinski 1918dadd2a6dSPiotr Pelplinski rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 1919dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1920dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1921dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1922dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 1923dadd2a6dSPiotr Pelplinski 1924dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 1925dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1926dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1927dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1928dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 1929dadd2a6dSPiotr Pelplinski 1930dadd2a6dSPiotr Pelplinski /* Pass unaligned iovs with no alignment required */ 1931dadd2a6dSPiotr Pelplinski alignment = 1; 1932dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1933dadd2a6dSPiotr Pelplinski 1934dadd2a6dSPiotr Pelplinski iovcnt = 2; 1935dadd2a6dSPiotr Pelplinski iovs[0].iov_base = buf + 16; 1936dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 256; 1937dadd2a6dSPiotr Pelplinski iovs[1].iov_base = buf + 16 + 256 + 32; 1938dadd2a6dSPiotr Pelplinski iovs[1].iov_len = 256; 1939dadd2a6dSPiotr Pelplinski 1940dadd2a6dSPiotr Pelplinski rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 1941dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1942dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1943dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1944dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 1945dadd2a6dSPiotr Pelplinski 1946dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 1947dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1948dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1949dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1950dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 1951dadd2a6dSPiotr Pelplinski 1952dadd2a6dSPiotr Pelplinski /* Pass unaligned iov with 2048 alignment required */ 1953dadd2a6dSPiotr Pelplinski alignment = 2048; 1954dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1955dadd2a6dSPiotr Pelplinski 1956dadd2a6dSPiotr Pelplinski iovcnt = 2; 1957dadd2a6dSPiotr Pelplinski iovs[0].iov_base = buf + 16; 1958dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 256; 1959dadd2a6dSPiotr Pelplinski iovs[1].iov_base = buf + 16 + 256 + 32; 1960dadd2a6dSPiotr Pelplinski iovs[1].iov_len = 256; 1961dadd2a6dSPiotr Pelplinski 1962dadd2a6dSPiotr Pelplinski rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 1963dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1964dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == iovcnt); 1965dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov); 1966dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1967dadd2a6dSPiotr Pelplinski alignment)); 1968dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1969dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1970dadd2a6dSPiotr Pelplinski 1971dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 1972dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1973dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == iovcnt); 1974dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_iov); 1975dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1976dadd2a6dSPiotr Pelplinski alignment)); 1977dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1978dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1979dadd2a6dSPiotr Pelplinski 1980dadd2a6dSPiotr Pelplinski /* Pass iov without allocated buffer without alignment required */ 1981dadd2a6dSPiotr Pelplinski alignment = 1; 1982dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1983dadd2a6dSPiotr Pelplinski 1984dadd2a6dSPiotr Pelplinski iovcnt = 1; 1985dadd2a6dSPiotr Pelplinski iovs[0].iov_base = NULL; 1986dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 0; 1987dadd2a6dSPiotr Pelplinski 1988dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 1989dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 1990dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 1991dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 1992dadd2a6dSPiotr Pelplinski alignment)); 1993dadd2a6dSPiotr Pelplinski stub_complete_io(1); 1994dadd2a6dSPiotr Pelplinski 1995dadd2a6dSPiotr Pelplinski /* Pass iov without allocated buffer with 1024 alignment required */ 1996dadd2a6dSPiotr Pelplinski alignment = 1024; 1997dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 1998dadd2a6dSPiotr Pelplinski 1999dadd2a6dSPiotr Pelplinski iovcnt = 1; 2000dadd2a6dSPiotr Pelplinski iovs[0].iov_base = NULL; 2001dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 0; 2002dadd2a6dSPiotr Pelplinski 2003dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 2004dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 2005dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->internal.orig_iovcnt == 0); 2006dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 2007dadd2a6dSPiotr Pelplinski alignment)); 2008dadd2a6dSPiotr Pelplinski stub_complete_io(1); 2009dadd2a6dSPiotr Pelplinski 2010dadd2a6dSPiotr Pelplinski spdk_put_io_channel(io_ch); 2011dadd2a6dSPiotr Pelplinski spdk_bdev_close(desc); 2012dadd2a6dSPiotr Pelplinski free_bdev(bdev); 2013ae43c81aSJim Harris fn_table.submit_request = stub_submit_request; 2014dadd2a6dSPiotr Pelplinski spdk_bdev_finish(bdev_fini_cb, NULL); 2015270a25dfSBen Walker poll_threads(); 2016dadd2a6dSPiotr Pelplinski 2017dadd2a6dSPiotr Pelplinski free(buf); 2018dadd2a6dSPiotr Pelplinski } 2019dadd2a6dSPiotr Pelplinski 202042dba604SPiotr Pelplinski static void 202145f48053SChangpeng Liu bdev_io_alignment_with_boundary(void) 202245f48053SChangpeng Liu { 202345f48053SChangpeng Liu struct spdk_bdev *bdev; 2024e2ce08cfSTomasz Zawadzki struct spdk_bdev_desc *desc = NULL; 202545f48053SChangpeng Liu struct spdk_io_channel *io_ch; 202645f48053SChangpeng Liu struct spdk_bdev_opts bdev_opts = { 202745f48053SChangpeng Liu .bdev_io_pool_size = 20, 202845f48053SChangpeng Liu .bdev_io_cache_size = 2, 202945f48053SChangpeng Liu }; 203045f48053SChangpeng Liu int rc; 20319714818dSyidong0635 void *buf = NULL; 203245f48053SChangpeng Liu struct iovec iovs[2]; 203345f48053SChangpeng Liu int iovcnt; 203445f48053SChangpeng Liu uint64_t alignment; 203545f48053SChangpeng Liu 203645f48053SChangpeng Liu rc = spdk_bdev_set_opts(&bdev_opts); 203745f48053SChangpeng Liu CU_ASSERT(rc == 0); 203845f48053SChangpeng Liu spdk_bdev_initialize(bdev_init_cb, NULL); 203945f48053SChangpeng Liu 204080da9548SMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 204145f48053SChangpeng Liu bdev = allocate_bdev("bdev0"); 204245f48053SChangpeng Liu 2043*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 204445f48053SChangpeng Liu CU_ASSERT(rc == 0); 204545f48053SChangpeng Liu CU_ASSERT(desc != NULL); 2046*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 204745f48053SChangpeng Liu io_ch = spdk_bdev_get_io_channel(desc); 204845f48053SChangpeng Liu CU_ASSERT(io_ch != NULL); 204945f48053SChangpeng Liu 205045f48053SChangpeng Liu /* Create aligned buffer */ 205145f48053SChangpeng Liu rc = posix_memalign(&buf, 4096, 131072); 205245f48053SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0); 205345f48053SChangpeng Liu g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 205445f48053SChangpeng Liu 205545f48053SChangpeng Liu /* 512 * 3 with 2 IO boundary, allocate small data buffer from bdev layer */ 205645f48053SChangpeng Liu alignment = 512; 205745f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 205845f48053SChangpeng Liu bdev->optimal_io_boundary = 2; 205945f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 206045f48053SChangpeng Liu 206145f48053SChangpeng Liu iovcnt = 1; 206245f48053SChangpeng Liu iovs[0].iov_base = NULL; 206345f48053SChangpeng Liu iovs[0].iov_len = 512 * 3; 206445f48053SChangpeng Liu 206545f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 3, io_done, NULL); 206645f48053SChangpeng Liu CU_ASSERT(rc == 0); 206745f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 206845f48053SChangpeng Liu stub_complete_io(2); 206945f48053SChangpeng Liu 207045f48053SChangpeng Liu /* 8KiB with 16 IO boundary, allocate large data buffer from bdev layer */ 207145f48053SChangpeng Liu alignment = 512; 207245f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 207345f48053SChangpeng Liu bdev->optimal_io_boundary = 16; 207445f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 207545f48053SChangpeng Liu 207645f48053SChangpeng Liu iovcnt = 1; 207745f48053SChangpeng Liu iovs[0].iov_base = NULL; 207845f48053SChangpeng Liu iovs[0].iov_len = 512 * 16; 207945f48053SChangpeng Liu 208045f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 16, io_done, NULL); 208145f48053SChangpeng Liu CU_ASSERT(rc == 0); 208245f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 208345f48053SChangpeng Liu stub_complete_io(2); 208445f48053SChangpeng Liu 208545f48053SChangpeng Liu /* 512 * 160 with 128 IO boundary, 63.5KiB + 16.5KiB for the two children requests */ 208645f48053SChangpeng Liu alignment = 512; 208745f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 208845f48053SChangpeng Liu bdev->optimal_io_boundary = 128; 208945f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 209045f48053SChangpeng Liu 209145f48053SChangpeng Liu iovcnt = 1; 209245f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 209345f48053SChangpeng Liu iovs[0].iov_len = 512 * 160; 209445f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 160, io_done, NULL); 209545f48053SChangpeng Liu CU_ASSERT(rc == 0); 209645f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 209745f48053SChangpeng Liu stub_complete_io(2); 209845f48053SChangpeng Liu 209945f48053SChangpeng Liu /* 512 * 3 with 2 IO boundary */ 210045f48053SChangpeng Liu alignment = 512; 210145f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 210245f48053SChangpeng Liu bdev->optimal_io_boundary = 2; 210345f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 210445f48053SChangpeng Liu 210545f48053SChangpeng Liu iovcnt = 2; 210645f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 210745f48053SChangpeng Liu iovs[0].iov_len = 512; 210845f48053SChangpeng Liu iovs[1].iov_base = buf + 16 + 512 + 32; 210945f48053SChangpeng Liu iovs[1].iov_len = 1024; 211045f48053SChangpeng Liu 211145f48053SChangpeng Liu rc = spdk_bdev_writev_blocks(desc, io_ch, iovs, iovcnt, 1, 3, io_done, NULL); 211245f48053SChangpeng Liu CU_ASSERT(rc == 0); 211345f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 211445f48053SChangpeng Liu stub_complete_io(2); 211545f48053SChangpeng Liu 211645f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 3, io_done, NULL); 211745f48053SChangpeng Liu CU_ASSERT(rc == 0); 211845f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 211945f48053SChangpeng Liu stub_complete_io(2); 212045f48053SChangpeng Liu 212145f48053SChangpeng Liu /* 512 * 64 with 32 IO boundary */ 212245f48053SChangpeng Liu bdev->optimal_io_boundary = 32; 212345f48053SChangpeng Liu iovcnt = 2; 212445f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 212545f48053SChangpeng Liu iovs[0].iov_len = 16384; 212645f48053SChangpeng Liu iovs[1].iov_base = buf + 16 + 16384 + 32; 212745f48053SChangpeng Liu iovs[1].iov_len = 16384; 212845f48053SChangpeng Liu 212945f48053SChangpeng Liu rc = spdk_bdev_writev_blocks(desc, io_ch, iovs, iovcnt, 1, 64, io_done, NULL); 213045f48053SChangpeng Liu CU_ASSERT(rc == 0); 213145f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 213245f48053SChangpeng Liu stub_complete_io(3); 213345f48053SChangpeng Liu 213445f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 64, io_done, NULL); 213545f48053SChangpeng Liu CU_ASSERT(rc == 0); 213645f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 213745f48053SChangpeng Liu stub_complete_io(3); 213845f48053SChangpeng Liu 213945f48053SChangpeng Liu /* 512 * 160 with 32 IO boundary */ 214045f48053SChangpeng Liu iovcnt = 1; 214145f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 214245f48053SChangpeng Liu iovs[0].iov_len = 16384 + 65536; 214345f48053SChangpeng Liu 214445f48053SChangpeng Liu rc = spdk_bdev_writev_blocks(desc, io_ch, iovs, iovcnt, 1, 160, io_done, NULL); 214545f48053SChangpeng Liu CU_ASSERT(rc == 0); 214645f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 6); 214745f48053SChangpeng Liu stub_complete_io(6); 214845f48053SChangpeng Liu 214945f48053SChangpeng Liu spdk_put_io_channel(io_ch); 215045f48053SChangpeng Liu spdk_bdev_close(desc); 215145f48053SChangpeng Liu free_bdev(bdev); 2152ae43c81aSJim Harris fn_table.submit_request = stub_submit_request; 215345f48053SChangpeng Liu spdk_bdev_finish(bdev_fini_cb, NULL); 215445f48053SChangpeng Liu poll_threads(); 215545f48053SChangpeng Liu 215645f48053SChangpeng Liu free(buf); 215745f48053SChangpeng Liu } 215845f48053SChangpeng Liu 215945f48053SChangpeng Liu static void 216042dba604SPiotr Pelplinski histogram_status_cb(void *cb_arg, int status) 216142dba604SPiotr Pelplinski { 216242dba604SPiotr Pelplinski g_status = status; 216342dba604SPiotr Pelplinski } 216442dba604SPiotr Pelplinski 216542dba604SPiotr Pelplinski static void 216642dba604SPiotr Pelplinski histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) 216742dba604SPiotr Pelplinski { 216842dba604SPiotr Pelplinski g_status = status; 216942dba604SPiotr Pelplinski g_histogram = histogram; 217042dba604SPiotr Pelplinski } 217142dba604SPiotr Pelplinski 217242dba604SPiotr Pelplinski static void 217342dba604SPiotr Pelplinski histogram_io_count(void *ctx, uint64_t start, uint64_t end, uint64_t count, 217442dba604SPiotr Pelplinski uint64_t total, uint64_t so_far) 217542dba604SPiotr Pelplinski { 217642dba604SPiotr Pelplinski g_count += count; 217742dba604SPiotr Pelplinski } 217842dba604SPiotr Pelplinski 217942dba604SPiotr Pelplinski static void 218042dba604SPiotr Pelplinski bdev_histograms(void) 218142dba604SPiotr Pelplinski { 218242dba604SPiotr Pelplinski struct spdk_bdev *bdev; 2183dae8e892STomasz Zawadzki struct spdk_bdev_desc *desc = NULL; 218442dba604SPiotr Pelplinski struct spdk_io_channel *ch; 218542dba604SPiotr Pelplinski struct spdk_histogram_data *histogram; 218642dba604SPiotr Pelplinski uint8_t buf[4096]; 218742dba604SPiotr Pelplinski int rc; 218842dba604SPiotr Pelplinski 218942dba604SPiotr Pelplinski spdk_bdev_initialize(bdev_init_cb, NULL); 219042dba604SPiotr Pelplinski 219142dba604SPiotr Pelplinski bdev = allocate_bdev("bdev"); 219242dba604SPiotr Pelplinski 2193*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 219442dba604SPiotr Pelplinski CU_ASSERT(rc == 0); 219542dba604SPiotr Pelplinski CU_ASSERT(desc != NULL); 2196*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 219742dba604SPiotr Pelplinski 219842dba604SPiotr Pelplinski ch = spdk_bdev_get_io_channel(desc); 219942dba604SPiotr Pelplinski CU_ASSERT(ch != NULL); 220042dba604SPiotr Pelplinski 220142dba604SPiotr Pelplinski /* Enable histogram */ 220242dba604SPiotr Pelplinski g_status = -1; 220342dba604SPiotr Pelplinski spdk_bdev_histogram_enable(bdev, histogram_status_cb, NULL, true); 220442dba604SPiotr Pelplinski poll_threads(); 220542dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 220642dba604SPiotr Pelplinski CU_ASSERT(bdev->internal.histogram_enabled == true); 220742dba604SPiotr Pelplinski 220842dba604SPiotr Pelplinski /* Allocate histogram */ 220942dba604SPiotr Pelplinski histogram = spdk_histogram_data_alloc(); 221042dba604SPiotr Pelplinski SPDK_CU_ASSERT_FATAL(histogram != NULL); 221142dba604SPiotr Pelplinski 221242dba604SPiotr Pelplinski /* Check if histogram is zeroed */ 221342dba604SPiotr Pelplinski spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); 221442dba604SPiotr Pelplinski poll_threads(); 221542dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 221642dba604SPiotr Pelplinski SPDK_CU_ASSERT_FATAL(g_histogram != NULL); 221742dba604SPiotr Pelplinski 221842dba604SPiotr Pelplinski g_count = 0; 221942dba604SPiotr Pelplinski spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); 222042dba604SPiotr Pelplinski 222142dba604SPiotr Pelplinski CU_ASSERT(g_count == 0); 222242dba604SPiotr Pelplinski 22231d94a0b0SJim Harris rc = spdk_bdev_write_blocks(desc, ch, buf, 0, 1, io_done, NULL); 222442dba604SPiotr Pelplinski CU_ASSERT(rc == 0); 222542dba604SPiotr Pelplinski 222642dba604SPiotr Pelplinski spdk_delay_us(10); 222742dba604SPiotr Pelplinski stub_complete_io(1); 222842dba604SPiotr Pelplinski poll_threads(); 222942dba604SPiotr Pelplinski 22301d94a0b0SJim Harris rc = spdk_bdev_read_blocks(desc, ch, buf, 0, 1, io_done, NULL); 223142dba604SPiotr Pelplinski CU_ASSERT(rc == 0); 223242dba604SPiotr Pelplinski 223342dba604SPiotr Pelplinski spdk_delay_us(10); 223442dba604SPiotr Pelplinski stub_complete_io(1); 223542dba604SPiotr Pelplinski poll_threads(); 223642dba604SPiotr Pelplinski 223742dba604SPiotr Pelplinski /* Check if histogram gathered data from all I/O channels */ 223842dba604SPiotr Pelplinski g_histogram = NULL; 223942dba604SPiotr Pelplinski spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); 224042dba604SPiotr Pelplinski poll_threads(); 224142dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 224242dba604SPiotr Pelplinski CU_ASSERT(bdev->internal.histogram_enabled == true); 224342dba604SPiotr Pelplinski SPDK_CU_ASSERT_FATAL(g_histogram != NULL); 224442dba604SPiotr Pelplinski 224542dba604SPiotr Pelplinski g_count = 0; 224642dba604SPiotr Pelplinski spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); 224742dba604SPiotr Pelplinski CU_ASSERT(g_count == 2); 224842dba604SPiotr Pelplinski 224942dba604SPiotr Pelplinski /* Disable histogram */ 225042dba604SPiotr Pelplinski spdk_bdev_histogram_enable(bdev, histogram_status_cb, NULL, false); 225142dba604SPiotr Pelplinski poll_threads(); 225242dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 225342dba604SPiotr Pelplinski CU_ASSERT(bdev->internal.histogram_enabled == false); 225442dba604SPiotr Pelplinski 225542dba604SPiotr Pelplinski /* Try to run histogram commands on disabled bdev */ 225642dba604SPiotr Pelplinski spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); 225742dba604SPiotr Pelplinski poll_threads(); 225842dba604SPiotr Pelplinski CU_ASSERT(g_status == -EFAULT); 225942dba604SPiotr Pelplinski 226026f6c2a0SDarek Stojaczyk spdk_histogram_data_free(histogram); 226142dba604SPiotr Pelplinski spdk_put_io_channel(ch); 226242dba604SPiotr Pelplinski spdk_bdev_close(desc); 226342dba604SPiotr Pelplinski free_bdev(bdev); 226442dba604SPiotr Pelplinski spdk_bdev_finish(bdev_fini_cb, NULL); 226542dba604SPiotr Pelplinski poll_threads(); 226642dba604SPiotr Pelplinski } 226742dba604SPiotr Pelplinski 2268e2918289SKonrad Sztyber static void 22693eda8bf6SMaciej Szwed _bdev_compare(bool emulated) 227077183c9cSMaciej Szwed { 227177183c9cSMaciej Szwed struct spdk_bdev *bdev; 227277183c9cSMaciej Szwed struct spdk_bdev_desc *desc = NULL; 227377183c9cSMaciej Szwed struct spdk_io_channel *ioch; 227477183c9cSMaciej Szwed struct ut_expected_io *expected_io; 227577183c9cSMaciej Szwed uint64_t offset, num_blocks; 227677183c9cSMaciej Szwed uint32_t num_completed; 227777183c9cSMaciej Szwed char aa_buf[512]; 227877183c9cSMaciej Szwed char bb_buf[512]; 227977183c9cSMaciej Szwed struct iovec compare_iov; 22803eda8bf6SMaciej Szwed uint8_t io_type; 228177183c9cSMaciej Szwed int rc; 228277183c9cSMaciej Szwed 22833eda8bf6SMaciej Szwed if (emulated) { 22843eda8bf6SMaciej Szwed io_type = SPDK_BDEV_IO_TYPE_READ; 22853eda8bf6SMaciej Szwed } else { 22863eda8bf6SMaciej Szwed io_type = SPDK_BDEV_IO_TYPE_COMPARE; 22873eda8bf6SMaciej Szwed } 22883eda8bf6SMaciej Szwed 228977183c9cSMaciej Szwed memset(aa_buf, 0xaa, sizeof(aa_buf)); 229077183c9cSMaciej Szwed memset(bb_buf, 0xbb, sizeof(bb_buf)); 229177183c9cSMaciej Szwed 22923eda8bf6SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = !emulated; 2293bee042e4SMaciej Szwed 229477183c9cSMaciej Szwed spdk_bdev_initialize(bdev_init_cb, NULL); 229577183c9cSMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 229677183c9cSMaciej Szwed bdev = allocate_bdev("bdev"); 229777183c9cSMaciej Szwed 2298*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 229977183c9cSMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 230077183c9cSMaciej Szwed SPDK_CU_ASSERT_FATAL(desc != NULL); 2301*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 230277183c9cSMaciej Szwed ioch = spdk_bdev_get_io_channel(desc); 230377183c9cSMaciej Szwed SPDK_CU_ASSERT_FATAL(ioch != NULL); 230477183c9cSMaciej Szwed 230577183c9cSMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 230677183c9cSMaciej Szwed g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 230777183c9cSMaciej Szwed 230877183c9cSMaciej Szwed offset = 50; 230977183c9cSMaciej Szwed num_blocks = 1; 231077183c9cSMaciej Szwed compare_iov.iov_base = aa_buf; 231177183c9cSMaciej Szwed compare_iov.iov_len = sizeof(aa_buf); 231277183c9cSMaciej Szwed 23133eda8bf6SMaciej Szwed expected_io = ut_alloc_expected_io(io_type, offset, num_blocks, 0); 231477183c9cSMaciej Szwed TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 231577183c9cSMaciej Szwed 231677183c9cSMaciej Szwed g_io_done = false; 231777183c9cSMaciej Szwed g_compare_read_buf = aa_buf; 231877183c9cSMaciej Szwed g_compare_read_buf_len = sizeof(aa_buf); 231977183c9cSMaciej Szwed rc = spdk_bdev_comparev_blocks(desc, ioch, &compare_iov, 1, offset, num_blocks, io_done, NULL); 232077183c9cSMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 232177183c9cSMaciej Szwed num_completed = stub_complete_io(1); 232277183c9cSMaciej Szwed CU_ASSERT_EQUAL(num_completed, 1); 232377183c9cSMaciej Szwed CU_ASSERT(g_io_done == true); 232477183c9cSMaciej Szwed CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 232577183c9cSMaciej Szwed 23263eda8bf6SMaciej Szwed expected_io = ut_alloc_expected_io(io_type, offset, num_blocks, 0); 232777183c9cSMaciej Szwed TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 232877183c9cSMaciej Szwed 232977183c9cSMaciej Szwed g_io_done = false; 233077183c9cSMaciej Szwed g_compare_read_buf = bb_buf; 233177183c9cSMaciej Szwed g_compare_read_buf_len = sizeof(bb_buf); 233277183c9cSMaciej Szwed rc = spdk_bdev_comparev_blocks(desc, ioch, &compare_iov, 1, offset, num_blocks, io_done, NULL); 233377183c9cSMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 233477183c9cSMaciej Szwed num_completed = stub_complete_io(1); 233577183c9cSMaciej Szwed CU_ASSERT_EQUAL(num_completed, 1); 233677183c9cSMaciej Szwed CU_ASSERT(g_io_done == true); 233777183c9cSMaciej Szwed CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 233877183c9cSMaciej Szwed 233977183c9cSMaciej Szwed spdk_put_io_channel(ioch); 234077183c9cSMaciej Szwed spdk_bdev_close(desc); 234177183c9cSMaciej Szwed free_bdev(bdev); 234277183c9cSMaciej Szwed fn_table.submit_request = stub_submit_request; 234377183c9cSMaciej Szwed spdk_bdev_finish(bdev_fini_cb, NULL); 234477183c9cSMaciej Szwed poll_threads(); 234577183c9cSMaciej Szwed 2346bee042e4SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = true; 2347bee042e4SMaciej Szwed 234877183c9cSMaciej Szwed g_compare_read_buf = NULL; 234977183c9cSMaciej Szwed } 235077183c9cSMaciej Szwed 235177183c9cSMaciej Szwed static void 23523eda8bf6SMaciej Szwed bdev_compare(void) 23533eda8bf6SMaciej Szwed { 23543eda8bf6SMaciej Szwed _bdev_compare(true); 2355ca0eeaabSMaciej Szwed _bdev_compare(false); 23563eda8bf6SMaciej Szwed } 23573eda8bf6SMaciej Szwed 23583eda8bf6SMaciej Szwed static void 2359ae43c81aSJim Harris bdev_compare_and_write(void) 2360ae43c81aSJim Harris { 2361ae43c81aSJim Harris struct spdk_bdev *bdev; 2362ae43c81aSJim Harris struct spdk_bdev_desc *desc = NULL; 2363ae43c81aSJim Harris struct spdk_io_channel *ioch; 2364ae43c81aSJim Harris struct ut_expected_io *expected_io; 2365ae43c81aSJim Harris uint64_t offset, num_blocks; 2366ae43c81aSJim Harris uint32_t num_completed; 2367ae43c81aSJim Harris char aa_buf[512]; 2368ae43c81aSJim Harris char bb_buf[512]; 2369ae43c81aSJim Harris char cc_buf[512]; 2370ae43c81aSJim Harris char write_buf[512]; 2371ae43c81aSJim Harris struct iovec compare_iov; 2372ae43c81aSJim Harris struct iovec write_iov; 2373ae43c81aSJim Harris int rc; 2374ae43c81aSJim Harris 2375ae43c81aSJim Harris memset(aa_buf, 0xaa, sizeof(aa_buf)); 2376ae43c81aSJim Harris memset(bb_buf, 0xbb, sizeof(bb_buf)); 2377ae43c81aSJim Harris memset(cc_buf, 0xcc, sizeof(cc_buf)); 2378ae43c81aSJim Harris 2379bee042e4SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = false; 2380bee042e4SMaciej Szwed 2381ae43c81aSJim Harris spdk_bdev_initialize(bdev_init_cb, NULL); 2382ae43c81aSJim Harris fn_table.submit_request = stub_submit_request_get_buf; 2383ae43c81aSJim Harris bdev = allocate_bdev("bdev"); 2384ae43c81aSJim Harris 2385*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 2386ae43c81aSJim Harris CU_ASSERT_EQUAL(rc, 0); 2387ae43c81aSJim Harris SPDK_CU_ASSERT_FATAL(desc != NULL); 2388*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 2389ae43c81aSJim Harris ioch = spdk_bdev_get_io_channel(desc); 2390ae43c81aSJim Harris SPDK_CU_ASSERT_FATAL(ioch != NULL); 2391ae43c81aSJim Harris 2392ae43c81aSJim Harris fn_table.submit_request = stub_submit_request_get_buf; 2393ae43c81aSJim Harris g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 2394ae43c81aSJim Harris 2395ae43c81aSJim Harris offset = 50; 2396ae43c81aSJim Harris num_blocks = 1; 2397ae43c81aSJim Harris compare_iov.iov_base = aa_buf; 2398ae43c81aSJim Harris compare_iov.iov_len = sizeof(aa_buf); 2399ae43c81aSJim Harris write_iov.iov_base = bb_buf; 2400ae43c81aSJim Harris write_iov.iov_len = sizeof(bb_buf); 2401ae43c81aSJim Harris 2402ae43c81aSJim Harris expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, offset, num_blocks, 0); 2403ae43c81aSJim Harris TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2404ae43c81aSJim Harris expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, offset, num_blocks, 0); 2405ae43c81aSJim Harris TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2406ae43c81aSJim Harris 2407ae43c81aSJim Harris g_io_done = false; 2408ae43c81aSJim Harris g_compare_read_buf = aa_buf; 2409ae43c81aSJim Harris g_compare_read_buf_len = sizeof(aa_buf); 2410ae43c81aSJim Harris memset(write_buf, 0, sizeof(write_buf)); 2411ae43c81aSJim Harris g_compare_write_buf = write_buf; 2412ae43c81aSJim Harris g_compare_write_buf_len = sizeof(write_buf); 2413ae43c81aSJim Harris rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1, 2414ae43c81aSJim Harris offset, num_blocks, io_done, NULL); 2415a83644feSMaciej Szwed /* Trigger range locking */ 2416a83644feSMaciej Szwed poll_threads(); 2417ae43c81aSJim Harris CU_ASSERT_EQUAL(rc, 0); 2418ae43c81aSJim Harris num_completed = stub_complete_io(1); 2419ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 1); 2420ae43c81aSJim Harris CU_ASSERT(g_io_done == false); 2421ae43c81aSJim Harris num_completed = stub_complete_io(1); 2422a83644feSMaciej Szwed /* Trigger range unlocking */ 2423a83644feSMaciej Szwed poll_threads(); 2424ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 1); 2425ae43c81aSJim Harris CU_ASSERT(g_io_done == true); 2426ae43c81aSJim Harris CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 2427ae43c81aSJim Harris CU_ASSERT(memcmp(write_buf, bb_buf, sizeof(write_buf)) == 0); 2428ae43c81aSJim Harris 2429ae43c81aSJim Harris expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, offset, num_blocks, 0); 2430ae43c81aSJim Harris TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2431ae43c81aSJim Harris 2432ae43c81aSJim Harris g_io_done = false; 2433ae43c81aSJim Harris g_compare_read_buf = cc_buf; 2434ae43c81aSJim Harris g_compare_read_buf_len = sizeof(cc_buf); 2435ae43c81aSJim Harris memset(write_buf, 0, sizeof(write_buf)); 2436ae43c81aSJim Harris g_compare_write_buf = write_buf; 2437ae43c81aSJim Harris g_compare_write_buf_len = sizeof(write_buf); 2438ae43c81aSJim Harris rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1, 2439ae43c81aSJim Harris offset, num_blocks, io_done, NULL); 2440a83644feSMaciej Szwed /* Trigger range locking */ 2441a83644feSMaciej Szwed poll_threads(); 2442ae43c81aSJim Harris CU_ASSERT_EQUAL(rc, 0); 2443ae43c81aSJim Harris num_completed = stub_complete_io(1); 2444a83644feSMaciej Szwed /* Trigger range unlocking earlier because we expect error here */ 2445a83644feSMaciej Szwed poll_threads(); 2446ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 1); 2447ae43c81aSJim Harris CU_ASSERT(g_io_done == true); 2448ae43c81aSJim Harris CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 2449ae43c81aSJim Harris num_completed = stub_complete_io(1); 2450ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 0); 2451ae43c81aSJim Harris 2452ae43c81aSJim Harris spdk_put_io_channel(ioch); 2453ae43c81aSJim Harris spdk_bdev_close(desc); 2454ae43c81aSJim Harris free_bdev(bdev); 2455ae43c81aSJim Harris fn_table.submit_request = stub_submit_request; 2456ae43c81aSJim Harris spdk_bdev_finish(bdev_fini_cb, NULL); 2457ae43c81aSJim Harris poll_threads(); 2458ae43c81aSJim Harris 2459bee042e4SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = true; 2460bee042e4SMaciej Szwed 2461ae43c81aSJim Harris g_compare_read_buf = NULL; 2462ae43c81aSJim Harris g_compare_write_buf = NULL; 2463ae43c81aSJim Harris } 2464ae43c81aSJim Harris 2465ae43c81aSJim Harris static void 2466e2918289SKonrad Sztyber bdev_write_zeroes(void) 2467e2918289SKonrad Sztyber { 2468e2918289SKonrad Sztyber struct spdk_bdev *bdev; 2469e2918289SKonrad Sztyber struct spdk_bdev_desc *desc = NULL; 2470e2918289SKonrad Sztyber struct spdk_io_channel *ioch; 2471e2918289SKonrad Sztyber struct ut_expected_io *expected_io; 2472e2918289SKonrad Sztyber uint64_t offset, num_io_blocks, num_blocks; 2473e2918289SKonrad Sztyber uint32_t num_completed, num_requests; 2474e2918289SKonrad Sztyber int rc; 2475e2918289SKonrad Sztyber 2476e2918289SKonrad Sztyber spdk_bdev_initialize(bdev_init_cb, NULL); 2477e2918289SKonrad Sztyber bdev = allocate_bdev("bdev"); 2478e2918289SKonrad Sztyber 2479*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 2480e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 2481e2918289SKonrad Sztyber SPDK_CU_ASSERT_FATAL(desc != NULL); 2482*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 2483e2918289SKonrad Sztyber ioch = spdk_bdev_get_io_channel(desc); 2484e2918289SKonrad Sztyber SPDK_CU_ASSERT_FATAL(ioch != NULL); 2485e2918289SKonrad Sztyber 2486e2918289SKonrad Sztyber fn_table.submit_request = stub_submit_request; 2487e2918289SKonrad Sztyber g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 2488e2918289SKonrad Sztyber 2489e2918289SKonrad Sztyber /* First test that if the bdev supports write_zeroes, the request won't be split */ 2490e2918289SKonrad Sztyber bdev->md_len = 0; 2491e2918289SKonrad Sztyber bdev->blocklen = 4096; 2492e2918289SKonrad Sztyber num_blocks = (ZERO_BUFFER_SIZE / bdev->blocklen) * 2; 2493e2918289SKonrad Sztyber 2494e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, 0, num_blocks, 0); 2495e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2496e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 2497e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 2498e2918289SKonrad Sztyber num_completed = stub_complete_io(1); 2499e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, 1); 2500e2918289SKonrad Sztyber 2501e2918289SKonrad Sztyber /* Check that if write zeroes is not supported it'll be replaced by regular writes */ 2502e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, false); 2503e2918289SKonrad Sztyber num_io_blocks = ZERO_BUFFER_SIZE / bdev->blocklen; 2504e2918289SKonrad Sztyber num_requests = 2; 2505e2918289SKonrad Sztyber num_blocks = (ZERO_BUFFER_SIZE / bdev->blocklen) * num_requests; 2506e2918289SKonrad Sztyber 2507e2918289SKonrad Sztyber for (offset = 0; offset < num_requests; ++offset) { 2508e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 2509e2918289SKonrad Sztyber offset * num_io_blocks, num_io_blocks, 0); 2510e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2511e2918289SKonrad Sztyber } 2512e2918289SKonrad Sztyber 2513e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 2514e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 2515e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 2516e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, num_requests); 2517e2918289SKonrad Sztyber 2518e2918289SKonrad Sztyber /* Check that the splitting is correct if bdev has interleaved metadata */ 2519e2918289SKonrad Sztyber bdev->md_interleave = true; 2520e2918289SKonrad Sztyber bdev->md_len = 64; 2521e2918289SKonrad Sztyber bdev->blocklen = 4096 + 64; 2522e2918289SKonrad Sztyber num_blocks = (ZERO_BUFFER_SIZE / bdev->blocklen) * 2; 2523e2918289SKonrad Sztyber 2524e2918289SKonrad Sztyber num_requests = offset = 0; 2525e2918289SKonrad Sztyber while (offset < num_blocks) { 2526e2918289SKonrad Sztyber num_io_blocks = spdk_min(ZERO_BUFFER_SIZE / bdev->blocklen, num_blocks - offset); 2527e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 2528e2918289SKonrad Sztyber offset, num_io_blocks, 0); 2529e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2530e2918289SKonrad Sztyber offset += num_io_blocks; 2531e2918289SKonrad Sztyber num_requests++; 2532e2918289SKonrad Sztyber } 2533e2918289SKonrad Sztyber 2534e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 2535e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 2536e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 2537e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, num_requests); 2538e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 2539e2918289SKonrad Sztyber assert(num_completed == 0); 2540e2918289SKonrad Sztyber 2541e2918289SKonrad Sztyber /* Check the the same for separate metadata buffer */ 2542e2918289SKonrad Sztyber bdev->md_interleave = false; 2543e2918289SKonrad Sztyber bdev->md_len = 64; 2544e2918289SKonrad Sztyber bdev->blocklen = 4096; 2545e2918289SKonrad Sztyber 2546e2918289SKonrad Sztyber num_requests = offset = 0; 2547e2918289SKonrad Sztyber while (offset < num_blocks) { 2548e2918289SKonrad Sztyber num_io_blocks = spdk_min(ZERO_BUFFER_SIZE / (bdev->blocklen + bdev->md_len), num_blocks); 2549e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 2550e2918289SKonrad Sztyber offset, num_io_blocks, 0); 2551e2918289SKonrad Sztyber expected_io->md_buf = (char *)g_bdev_mgr.zero_buffer + num_io_blocks * bdev->blocklen; 2552e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2553e2918289SKonrad Sztyber offset += num_io_blocks; 2554e2918289SKonrad Sztyber num_requests++; 2555e2918289SKonrad Sztyber } 2556e2918289SKonrad Sztyber 2557e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 2558e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 2559e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 2560e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, num_requests); 2561e2918289SKonrad Sztyber 2562e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, true); 2563e2918289SKonrad Sztyber spdk_put_io_channel(ioch); 2564e2918289SKonrad Sztyber spdk_bdev_close(desc); 2565e2918289SKonrad Sztyber free_bdev(bdev); 2566e2918289SKonrad Sztyber spdk_bdev_finish(bdev_fini_cb, NULL); 2567e2918289SKonrad Sztyber poll_threads(); 2568e2918289SKonrad Sztyber } 2569e2918289SKonrad Sztyber 2570c141bd94SMaciej Szwed static void 2571c141bd94SMaciej Szwed bdev_open_while_hotremove(void) 2572c141bd94SMaciej Szwed { 2573c141bd94SMaciej Szwed struct spdk_bdev *bdev; 2574c141bd94SMaciej Szwed struct spdk_bdev_desc *desc[2] = {}; 2575c141bd94SMaciej Szwed int rc; 2576c141bd94SMaciej Szwed 2577c141bd94SMaciej Szwed bdev = allocate_bdev("bdev"); 2578c141bd94SMaciej Szwed 2579*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", false, bdev_ut_event_cb, NULL, &desc[0]); 2580c141bd94SMaciej Szwed CU_ASSERT(rc == 0); 2581c141bd94SMaciej Szwed SPDK_CU_ASSERT_FATAL(desc[0] != NULL); 2582*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc[0])); 2583c141bd94SMaciej Szwed 2584c141bd94SMaciej Szwed spdk_bdev_unregister(bdev, NULL, NULL); 2585c141bd94SMaciej Szwed 2586*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", false, bdev_ut_event_cb, NULL, &desc[1]); 2587c141bd94SMaciej Szwed CU_ASSERT(rc == -ENODEV); 2588c141bd94SMaciej Szwed SPDK_CU_ASSERT_FATAL(desc[1] == NULL); 2589c141bd94SMaciej Szwed 2590c141bd94SMaciej Szwed spdk_bdev_close(desc[0]); 2591c141bd94SMaciej Szwed free_bdev(bdev); 2592c141bd94SMaciej Szwed } 2593c141bd94SMaciej Szwed 259479ed1ba1SMaciej Szwed static void 259523975858SEvgeniy Kochetov bdev_close_while_hotremove(void) 259623975858SEvgeniy Kochetov { 259723975858SEvgeniy Kochetov struct spdk_bdev *bdev; 259823975858SEvgeniy Kochetov struct spdk_bdev_desc *desc = NULL; 259923975858SEvgeniy Kochetov int rc = 0; 260023975858SEvgeniy Kochetov 260123975858SEvgeniy Kochetov bdev = allocate_bdev("bdev"); 260223975858SEvgeniy Kochetov 260323975858SEvgeniy Kochetov rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb1, &desc, &desc); 260423975858SEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 2605*75dfecbbSShuhei Matsumoto SPDK_CU_ASSERT_FATAL(desc != NULL); 2606*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 260723975858SEvgeniy Kochetov 260823975858SEvgeniy Kochetov /* Simulate hot-unplug by unregistering bdev */ 260923975858SEvgeniy Kochetov g_event_type1 = 0xFF; 261023975858SEvgeniy Kochetov g_unregister_arg = NULL; 261123975858SEvgeniy Kochetov g_unregister_rc = -1; 261223975858SEvgeniy Kochetov spdk_bdev_unregister(bdev, bdev_unregister_cb, (void *)0x12345678); 261323975858SEvgeniy Kochetov /* Close device while remove event is in flight */ 261423975858SEvgeniy Kochetov spdk_bdev_close(desc); 261523975858SEvgeniy Kochetov 261623975858SEvgeniy Kochetov /* Ensure that unregister callback is delayed */ 261723975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_arg, NULL); 261823975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_rc, -1); 261923975858SEvgeniy Kochetov 262023975858SEvgeniy Kochetov poll_threads(); 262123975858SEvgeniy Kochetov 262223975858SEvgeniy Kochetov /* Event callback shall not be issued because device was closed */ 262323975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_event_type1, 0xFF); 262423975858SEvgeniy Kochetov /* Unregister callback is issued */ 262523975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_arg, (void *)0x12345678); 262623975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_rc, 0); 262723975858SEvgeniy Kochetov 262823975858SEvgeniy Kochetov free_bdev(bdev); 262923975858SEvgeniy Kochetov } 263023975858SEvgeniy Kochetov 263123975858SEvgeniy Kochetov static void 263279ed1ba1SMaciej Szwed bdev_open_ext(void) 263379ed1ba1SMaciej Szwed { 263479ed1ba1SMaciej Szwed struct spdk_bdev *bdev; 263579ed1ba1SMaciej Szwed struct spdk_bdev_desc *desc1 = NULL; 263679ed1ba1SMaciej Szwed struct spdk_bdev_desc *desc2 = NULL; 263779ed1ba1SMaciej Szwed int rc = 0; 263879ed1ba1SMaciej Szwed 263979ed1ba1SMaciej Szwed bdev = allocate_bdev("bdev"); 264079ed1ba1SMaciej Szwed 264179ed1ba1SMaciej Szwed rc = spdk_bdev_open_ext("bdev", true, NULL, NULL, &desc1); 264279ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(rc, -EINVAL); 264379ed1ba1SMaciej Szwed 264479ed1ba1SMaciej Szwed rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb1, &desc1, &desc1); 264579ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 264679ed1ba1SMaciej Szwed 264779ed1ba1SMaciej Szwed rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb2, &desc2, &desc2); 264879ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 264979ed1ba1SMaciej Szwed 265079ed1ba1SMaciej Szwed g_event_type1 = 0xFF; 265179ed1ba1SMaciej Szwed g_event_type2 = 0xFF; 265279ed1ba1SMaciej Szwed 265379ed1ba1SMaciej Szwed /* Simulate hot-unplug by unregistering bdev */ 265479ed1ba1SMaciej Szwed spdk_bdev_unregister(bdev, NULL, NULL); 265579ed1ba1SMaciej Szwed poll_threads(); 265679ed1ba1SMaciej Szwed 265779ed1ba1SMaciej Szwed /* Check if correct events have been triggered in event callback fn */ 265879ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(g_event_type1, SPDK_BDEV_EVENT_REMOVE); 265979ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(g_event_type2, SPDK_BDEV_EVENT_REMOVE); 266079ed1ba1SMaciej Szwed 266179ed1ba1SMaciej Szwed free_bdev(bdev); 266279ed1ba1SMaciej Szwed poll_threads(); 266379ed1ba1SMaciej Szwed } 266479ed1ba1SMaciej Szwed 2665f1d47d69SJin Yu struct timeout_io_cb_arg { 2666f1d47d69SJin Yu struct iovec iov; 2667f1d47d69SJin Yu uint8_t type; 2668f1d47d69SJin Yu }; 2669f1d47d69SJin Yu 2670f1d47d69SJin Yu static int 2671f1d47d69SJin Yu bdev_channel_count_submitted_io(struct spdk_bdev_channel *ch) 2672f1d47d69SJin Yu { 2673f1d47d69SJin Yu struct spdk_bdev_io *bdev_io; 2674f1d47d69SJin Yu int n = 0; 2675f1d47d69SJin Yu 2676f1d47d69SJin Yu if (!ch) { 2677f1d47d69SJin Yu return -1; 2678f1d47d69SJin Yu } 2679f1d47d69SJin Yu 2680f1d47d69SJin Yu TAILQ_FOREACH(bdev_io, &ch->io_submitted, internal.ch_link) { 2681f1d47d69SJin Yu n++; 2682f1d47d69SJin Yu } 2683f1d47d69SJin Yu 2684f1d47d69SJin Yu return n; 2685f1d47d69SJin Yu } 2686f1d47d69SJin Yu 2687f1d47d69SJin Yu static void 2688f1d47d69SJin Yu bdev_channel_io_timeout_cb(void *cb_arg, struct spdk_bdev_io *bdev_io) 2689f1d47d69SJin Yu { 2690f1d47d69SJin Yu struct timeout_io_cb_arg *ctx = cb_arg; 2691f1d47d69SJin Yu 2692f1d47d69SJin Yu ctx->type = bdev_io->type; 2693f1d47d69SJin Yu ctx->iov.iov_base = bdev_io->iov.iov_base; 2694f1d47d69SJin Yu ctx->iov.iov_len = bdev_io->iov.iov_len; 2695f1d47d69SJin Yu } 2696f1d47d69SJin Yu 2697f1d47d69SJin Yu static void 2698f1d47d69SJin Yu bdev_set_io_timeout(void) 2699f1d47d69SJin Yu { 2700f1d47d69SJin Yu struct spdk_bdev *bdev; 2701f1d47d69SJin Yu struct spdk_bdev_desc *desc = NULL; 2702f1d47d69SJin Yu struct spdk_io_channel *io_ch = NULL; 2703f1d47d69SJin Yu struct spdk_bdev_channel *bdev_ch = NULL; 2704f1d47d69SJin Yu struct timeout_io_cb_arg cb_arg; 2705f1d47d69SJin Yu 2706f1d47d69SJin Yu spdk_bdev_initialize(bdev_init_cb, NULL); 2707f1d47d69SJin Yu 2708f1d47d69SJin Yu bdev = allocate_bdev("bdev"); 2709f1d47d69SJin Yu 2710*75dfecbbSShuhei Matsumoto CU_ASSERT(spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc) == 0); 2711f1d47d69SJin Yu SPDK_CU_ASSERT_FATAL(desc != NULL); 2712*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 2713*75dfecbbSShuhei Matsumoto 2714f1d47d69SJin Yu io_ch = spdk_bdev_get_io_channel(desc); 2715f1d47d69SJin Yu CU_ASSERT(io_ch != NULL); 2716f1d47d69SJin Yu 2717f1d47d69SJin Yu bdev_ch = spdk_io_channel_get_ctx(io_ch); 2718f1d47d69SJin Yu CU_ASSERT(TAILQ_EMPTY(&bdev_ch->io_submitted)); 2719f1d47d69SJin Yu 2720f1d47d69SJin Yu /* This is the part1. 2721f1d47d69SJin Yu * We will check the bdev_ch->io_submitted list 2722f1d47d69SJin Yu * TO make sure that it can link IOs and only the user submitted IOs 2723f1d47d69SJin Yu */ 2724f1d47d69SJin Yu CU_ASSERT(spdk_bdev_read(desc, io_ch, (void *)0x1000, 0, 4096, io_done, NULL) == 0); 2725f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 2726f1d47d69SJin Yu CU_ASSERT(spdk_bdev_write(desc, io_ch, (void *)0x2000, 0, 4096, io_done, NULL) == 0); 2727f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 2); 2728f1d47d69SJin Yu stub_complete_io(1); 2729f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 2730f1d47d69SJin Yu stub_complete_io(1); 2731f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 0); 2732f1d47d69SJin Yu 2733f1d47d69SJin Yu /* Split IO */ 2734f1d47d69SJin Yu bdev->optimal_io_boundary = 16; 2735f1d47d69SJin Yu bdev->split_on_optimal_io_boundary = true; 2736f1d47d69SJin Yu 2737f1d47d69SJin Yu /* Now test that a single-vector command is split correctly. 2738f1d47d69SJin Yu * Offset 14, length 8, payload 0xF000 2739f1d47d69SJin Yu * Child - Offset 14, length 2, payload 0xF000 2740f1d47d69SJin Yu * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 2741f1d47d69SJin Yu * 2742f1d47d69SJin Yu * Set up the expected values before calling spdk_bdev_read_blocks 2743f1d47d69SJin Yu */ 2744f1d47d69SJin Yu CU_ASSERT(spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL) == 0); 2745fc3e4061SShuhei Matsumoto /* We count all submitted IOs including IO that are generated by splitting. */ 2746fc3e4061SShuhei Matsumoto CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 3); 2747f1d47d69SJin Yu stub_complete_io(1); 2748fc3e4061SShuhei Matsumoto CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 2); 2749f1d47d69SJin Yu stub_complete_io(1); 2750f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 0); 2751f1d47d69SJin Yu 2752f1d47d69SJin Yu /* Also include the reset IO */ 2753f1d47d69SJin Yu CU_ASSERT(spdk_bdev_reset(desc, io_ch, io_done, NULL) == 0); 2754f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 2755f1d47d69SJin Yu poll_threads(); 2756f1d47d69SJin Yu stub_complete_io(1); 2757f1d47d69SJin Yu poll_threads(); 2758f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 0); 2759f1d47d69SJin Yu 2760f1d47d69SJin Yu /* This is part2 2761f1d47d69SJin Yu * Test the desc timeout poller register 2762f1d47d69SJin Yu */ 2763f1d47d69SJin Yu 2764f1d47d69SJin Yu /* Successfully set the timeout */ 2765f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 30, bdev_channel_io_timeout_cb, &cb_arg) == 0); 2766f1d47d69SJin Yu CU_ASSERT(desc->io_timeout_poller != NULL); 2767f1d47d69SJin Yu CU_ASSERT(desc->timeout_in_sec == 30); 2768f1d47d69SJin Yu CU_ASSERT(desc->cb_fn == bdev_channel_io_timeout_cb); 2769f1d47d69SJin Yu CU_ASSERT(desc->cb_arg == &cb_arg); 2770f1d47d69SJin Yu 2771f1d47d69SJin Yu /* Change the timeout limit */ 2772f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 20, bdev_channel_io_timeout_cb, &cb_arg) == 0); 2773f1d47d69SJin Yu CU_ASSERT(desc->io_timeout_poller != NULL); 2774f1d47d69SJin Yu CU_ASSERT(desc->timeout_in_sec == 20); 2775f1d47d69SJin Yu CU_ASSERT(desc->cb_fn == bdev_channel_io_timeout_cb); 2776f1d47d69SJin Yu CU_ASSERT(desc->cb_arg == &cb_arg); 2777f1d47d69SJin Yu 2778f1d47d69SJin Yu /* Disable the timeout */ 2779f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 0, NULL, NULL) == 0); 2780f1d47d69SJin Yu CU_ASSERT(desc->io_timeout_poller == NULL); 2781f1d47d69SJin Yu 2782f1d47d69SJin Yu /* This the part3 2783f1d47d69SJin Yu * We will test to catch timeout IO and check whether the IO is 2784f1d47d69SJin Yu * the submitted one. 2785f1d47d69SJin Yu */ 2786f1d47d69SJin Yu memset(&cb_arg, 0, sizeof(cb_arg)); 2787f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 30, bdev_channel_io_timeout_cb, &cb_arg) == 0); 2788f1d47d69SJin Yu CU_ASSERT(spdk_bdev_write_blocks(desc, io_ch, (void *)0x1000, 0, 1, io_done, NULL) == 0); 2789f1d47d69SJin Yu 2790f1d47d69SJin Yu /* Don't reach the limit */ 2791f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 2792f1d47d69SJin Yu poll_threads(); 2793f1d47d69SJin Yu CU_ASSERT(cb_arg.type == 0); 2794f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0x0); 2795f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 0); 2796f1d47d69SJin Yu 2797f1d47d69SJin Yu /* 15 + 15 = 30 reach the limit */ 2798f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 2799f1d47d69SJin Yu poll_threads(); 2800f1d47d69SJin Yu CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_WRITE); 2801f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0x1000); 2802f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 1 * bdev->blocklen); 2803f1d47d69SJin Yu stub_complete_io(1); 2804f1d47d69SJin Yu 2805f1d47d69SJin Yu /* Use the same split IO above and check the IO */ 2806f1d47d69SJin Yu memset(&cb_arg, 0, sizeof(cb_arg)); 2807f1d47d69SJin Yu CU_ASSERT(spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL) == 0); 2808f1d47d69SJin Yu 2809f1d47d69SJin Yu /* The first child complete in time */ 2810f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 2811f1d47d69SJin Yu poll_threads(); 2812f1d47d69SJin Yu stub_complete_io(1); 2813f1d47d69SJin Yu CU_ASSERT(cb_arg.type == 0); 2814f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0x0); 2815f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 0); 2816f1d47d69SJin Yu 2817f1d47d69SJin Yu /* The second child reach the limit */ 2818f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 2819f1d47d69SJin Yu poll_threads(); 2820f1d47d69SJin Yu CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_WRITE); 2821f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0xF000); 2822f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 8 * bdev->blocklen); 2823f1d47d69SJin Yu stub_complete_io(1); 2824f1d47d69SJin Yu 2825f1d47d69SJin Yu /* Also include the reset IO */ 2826f1d47d69SJin Yu memset(&cb_arg, 0, sizeof(cb_arg)); 2827f1d47d69SJin Yu CU_ASSERT(spdk_bdev_reset(desc, io_ch, io_done, NULL) == 0); 2828f1d47d69SJin Yu spdk_delay_us(30 * spdk_get_ticks_hz()); 2829f1d47d69SJin Yu poll_threads(); 2830f1d47d69SJin Yu CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_RESET); 2831f1d47d69SJin Yu stub_complete_io(1); 2832f1d47d69SJin Yu poll_threads(); 2833f1d47d69SJin Yu 2834f1d47d69SJin Yu spdk_put_io_channel(io_ch); 2835f1d47d69SJin Yu spdk_bdev_close(desc); 2836f1d47d69SJin Yu free_bdev(bdev); 2837f1d47d69SJin Yu spdk_bdev_finish(bdev_fini_cb, NULL); 2838f1d47d69SJin Yu poll_threads(); 2839f1d47d69SJin Yu } 2840f1d47d69SJin Yu 2841b87080efSJim Harris static void 2842b87080efSJim Harris lba_range_overlap(void) 2843b87080efSJim Harris { 2844b87080efSJim Harris struct lba_range r1, r2; 2845b87080efSJim Harris 2846b87080efSJim Harris r1.offset = 100; 2847b87080efSJim Harris r1.length = 50; 2848b87080efSJim Harris 2849b87080efSJim Harris r2.offset = 0; 2850b87080efSJim Harris r2.length = 1; 2851b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 2852b87080efSJim Harris 2853b87080efSJim Harris r2.offset = 0; 2854b87080efSJim Harris r2.length = 100; 2855b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 2856b87080efSJim Harris 2857b87080efSJim Harris r2.offset = 0; 2858b87080efSJim Harris r2.length = 110; 2859b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 2860b87080efSJim Harris 2861b87080efSJim Harris r2.offset = 100; 2862b87080efSJim Harris r2.length = 10; 2863b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 2864b87080efSJim Harris 2865b87080efSJim Harris r2.offset = 110; 2866b87080efSJim Harris r2.length = 20; 2867b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 2868b87080efSJim Harris 2869b87080efSJim Harris r2.offset = 140; 2870b87080efSJim Harris r2.length = 150; 2871b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 2872b87080efSJim Harris 2873b87080efSJim Harris r2.offset = 130; 2874b87080efSJim Harris r2.length = 200; 2875b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 2876b87080efSJim Harris 2877b87080efSJim Harris r2.offset = 150; 2878b87080efSJim Harris r2.length = 100; 2879b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 2880b87080efSJim Harris 2881b87080efSJim Harris r2.offset = 110; 2882b87080efSJim Harris r2.length = 0; 2883b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 2884b87080efSJim Harris } 2885b87080efSJim Harris 2886d84a88c1SJim Harris static bool g_lock_lba_range_done; 2887d84a88c1SJim Harris static bool g_unlock_lba_range_done; 2888d84a88c1SJim Harris 2889d84a88c1SJim Harris static void 2890d84a88c1SJim Harris lock_lba_range_done(void *ctx, int status) 2891d84a88c1SJim Harris { 2892d84a88c1SJim Harris g_lock_lba_range_done = true; 2893d84a88c1SJim Harris } 2894d84a88c1SJim Harris 2895d84a88c1SJim Harris static void 2896d84a88c1SJim Harris unlock_lba_range_done(void *ctx, int status) 2897d84a88c1SJim Harris { 2898d84a88c1SJim Harris g_unlock_lba_range_done = true; 2899d84a88c1SJim Harris } 2900d84a88c1SJim Harris 2901d84a88c1SJim Harris static void 2902d84a88c1SJim Harris lock_lba_range_check_ranges(void) 2903d84a88c1SJim Harris { 2904d84a88c1SJim Harris struct spdk_bdev *bdev; 2905d84a88c1SJim Harris struct spdk_bdev_desc *desc = NULL; 2906d84a88c1SJim Harris struct spdk_io_channel *io_ch; 2907d84a88c1SJim Harris struct spdk_bdev_channel *channel; 2908d84a88c1SJim Harris struct lba_range *range; 2909d84a88c1SJim Harris int ctx1; 2910d84a88c1SJim Harris int rc; 2911d84a88c1SJim Harris 2912d84a88c1SJim Harris spdk_bdev_initialize(bdev_init_cb, NULL); 2913d84a88c1SJim Harris 2914d84a88c1SJim Harris bdev = allocate_bdev("bdev0"); 2915d84a88c1SJim Harris 2916*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 2917d84a88c1SJim Harris CU_ASSERT(rc == 0); 2918d84a88c1SJim Harris CU_ASSERT(desc != NULL); 2919*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 2920d84a88c1SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 2921d84a88c1SJim Harris CU_ASSERT(io_ch != NULL); 2922d84a88c1SJim Harris channel = spdk_io_channel_get_ctx(io_ch); 2923d84a88c1SJim Harris 2924d84a88c1SJim Harris g_lock_lba_range_done = false; 2925d84a88c1SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 2926d84a88c1SJim Harris CU_ASSERT(rc == 0); 2927d84a88c1SJim Harris poll_threads(); 2928d84a88c1SJim Harris 2929d84a88c1SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 2930d84a88c1SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 2931d84a88c1SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 2932d84a88c1SJim Harris CU_ASSERT(range->offset == 20); 2933d84a88c1SJim Harris CU_ASSERT(range->length == 10); 2934d84a88c1SJim Harris CU_ASSERT(range->owner_ch == channel); 2935d84a88c1SJim Harris 2936d84a88c1SJim Harris /* Unlocks must exactly match a lock. */ 2937d84a88c1SJim Harris g_unlock_lba_range_done = false; 2938d84a88c1SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 1, unlock_lba_range_done, &ctx1); 2939d84a88c1SJim Harris CU_ASSERT(rc == -EINVAL); 2940d84a88c1SJim Harris CU_ASSERT(g_unlock_lba_range_done == false); 2941d84a88c1SJim Harris 2942d84a88c1SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, unlock_lba_range_done, &ctx1); 2943d84a88c1SJim Harris CU_ASSERT(rc == 0); 2944d84a88c1SJim Harris spdk_delay_us(100); 2945d84a88c1SJim Harris poll_threads(); 2946d84a88c1SJim Harris 2947d84a88c1SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 2948d84a88c1SJim Harris CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 2949d84a88c1SJim Harris 2950d84a88c1SJim Harris spdk_put_io_channel(io_ch); 2951d84a88c1SJim Harris spdk_bdev_close(desc); 2952d84a88c1SJim Harris free_bdev(bdev); 2953d84a88c1SJim Harris spdk_bdev_finish(bdev_fini_cb, NULL); 2954d84a88c1SJim Harris poll_threads(); 2955d84a88c1SJim Harris } 2956d84a88c1SJim Harris 2957b90b7ce4SJim Harris static void 2958b90b7ce4SJim Harris lock_lba_range_with_io_outstanding(void) 2959b90b7ce4SJim Harris { 2960b90b7ce4SJim Harris struct spdk_bdev *bdev; 2961b90b7ce4SJim Harris struct spdk_bdev_desc *desc = NULL; 2962b90b7ce4SJim Harris struct spdk_io_channel *io_ch; 2963b90b7ce4SJim Harris struct spdk_bdev_channel *channel; 2964b90b7ce4SJim Harris struct lba_range *range; 2965b90b7ce4SJim Harris char buf[4096]; 2966b90b7ce4SJim Harris int ctx1; 2967b90b7ce4SJim Harris int rc; 2968b90b7ce4SJim Harris 2969b90b7ce4SJim Harris spdk_bdev_initialize(bdev_init_cb, NULL); 2970b90b7ce4SJim Harris 2971b90b7ce4SJim Harris bdev = allocate_bdev("bdev0"); 2972b90b7ce4SJim Harris 2973*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 2974b90b7ce4SJim Harris CU_ASSERT(rc == 0); 2975b90b7ce4SJim Harris CU_ASSERT(desc != NULL); 2976*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 2977b90b7ce4SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 2978b90b7ce4SJim Harris CU_ASSERT(io_ch != NULL); 2979b90b7ce4SJim Harris channel = spdk_io_channel_get_ctx(io_ch); 2980b90b7ce4SJim Harris 2981b90b7ce4SJim Harris g_io_done = false; 2982b90b7ce4SJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, buf, 20, 1, io_done, &ctx1); 2983b90b7ce4SJim Harris CU_ASSERT(rc == 0); 2984b90b7ce4SJim Harris 2985b90b7ce4SJim Harris g_lock_lba_range_done = false; 2986b90b7ce4SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 2987b90b7ce4SJim Harris CU_ASSERT(rc == 0); 2988b90b7ce4SJim Harris poll_threads(); 2989b90b7ce4SJim Harris 2990b90b7ce4SJim Harris /* The lock should immediately become valid, since there are no outstanding 2991b90b7ce4SJim Harris * write I/O. 2992b90b7ce4SJim Harris */ 2993b90b7ce4SJim Harris CU_ASSERT(g_io_done == false); 2994b90b7ce4SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 2995b90b7ce4SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 2996b90b7ce4SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 2997b90b7ce4SJim Harris CU_ASSERT(range->offset == 20); 2998b90b7ce4SJim Harris CU_ASSERT(range->length == 10); 2999b90b7ce4SJim Harris CU_ASSERT(range->owner_ch == channel); 3000b90b7ce4SJim Harris CU_ASSERT(range->locked_ctx == &ctx1); 3001b90b7ce4SJim Harris 3002b90b7ce4SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 3003b90b7ce4SJim Harris CU_ASSERT(rc == 0); 3004b90b7ce4SJim Harris stub_complete_io(1); 3005b90b7ce4SJim Harris spdk_delay_us(100); 3006b90b7ce4SJim Harris poll_threads(); 3007b90b7ce4SJim Harris 3008b90b7ce4SJim Harris CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 3009b90b7ce4SJim Harris 3010b90b7ce4SJim Harris /* Now try again, but with a write I/O. */ 3011b90b7ce4SJim Harris g_io_done = false; 3012b90b7ce4SJim Harris rc = spdk_bdev_write_blocks(desc, io_ch, buf, 20, 1, io_done, &ctx1); 3013b90b7ce4SJim Harris CU_ASSERT(rc == 0); 3014b90b7ce4SJim Harris 3015b90b7ce4SJim Harris g_lock_lba_range_done = false; 3016b90b7ce4SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 3017b90b7ce4SJim Harris CU_ASSERT(rc == 0); 3018b90b7ce4SJim Harris poll_threads(); 3019b90b7ce4SJim Harris 3020b90b7ce4SJim Harris /* The lock should not be fully valid yet, since a write I/O is outstanding. 3021b90b7ce4SJim Harris * But note that the range should be on the channel's locked_list, to make sure no 3022b90b7ce4SJim Harris * new write I/O are started. 3023b90b7ce4SJim Harris */ 3024b90b7ce4SJim Harris CU_ASSERT(g_io_done == false); 3025b90b7ce4SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 3026b90b7ce4SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 3027b90b7ce4SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 3028b90b7ce4SJim Harris CU_ASSERT(range->offset == 20); 3029b90b7ce4SJim Harris CU_ASSERT(range->length == 10); 3030b90b7ce4SJim Harris 3031b90b7ce4SJim Harris /* Complete the write I/O. This should make the lock valid (checked by confirming 3032b90b7ce4SJim Harris * our callback was invoked). 3033b90b7ce4SJim Harris */ 3034b90b7ce4SJim Harris stub_complete_io(1); 3035b90b7ce4SJim Harris spdk_delay_us(100); 3036b90b7ce4SJim Harris poll_threads(); 3037b90b7ce4SJim Harris CU_ASSERT(g_io_done == true); 3038b90b7ce4SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 3039b90b7ce4SJim Harris 3040b90b7ce4SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, unlock_lba_range_done, &ctx1); 3041b90b7ce4SJim Harris CU_ASSERT(rc == 0); 3042b90b7ce4SJim Harris poll_threads(); 3043b90b7ce4SJim Harris 3044b90b7ce4SJim Harris CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 3045b90b7ce4SJim Harris 3046b90b7ce4SJim Harris spdk_put_io_channel(io_ch); 3047b90b7ce4SJim Harris spdk_bdev_close(desc); 3048b90b7ce4SJim Harris free_bdev(bdev); 3049b90b7ce4SJim Harris spdk_bdev_finish(bdev_fini_cb, NULL); 3050b90b7ce4SJim Harris poll_threads(); 3051b90b7ce4SJim Harris } 3052b90b7ce4SJim Harris 30532a2b7296SJim Harris static void 30542a2b7296SJim Harris lock_lba_range_overlapped(void) 30552a2b7296SJim Harris { 30562a2b7296SJim Harris struct spdk_bdev *bdev; 30572a2b7296SJim Harris struct spdk_bdev_desc *desc = NULL; 30582a2b7296SJim Harris struct spdk_io_channel *io_ch; 30592a2b7296SJim Harris struct spdk_bdev_channel *channel; 30602a2b7296SJim Harris struct lba_range *range; 30612a2b7296SJim Harris int ctx1; 30622a2b7296SJim Harris int rc; 30632a2b7296SJim Harris 30642a2b7296SJim Harris spdk_bdev_initialize(bdev_init_cb, NULL); 30652a2b7296SJim Harris 30662a2b7296SJim Harris bdev = allocate_bdev("bdev0"); 30672a2b7296SJim Harris 3068*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 30692a2b7296SJim Harris CU_ASSERT(rc == 0); 30702a2b7296SJim Harris CU_ASSERT(desc != NULL); 3071*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 30722a2b7296SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 30732a2b7296SJim Harris CU_ASSERT(io_ch != NULL); 30742a2b7296SJim Harris channel = spdk_io_channel_get_ctx(io_ch); 30752a2b7296SJim Harris 30762a2b7296SJim Harris /* Lock range 20-29. */ 30772a2b7296SJim Harris g_lock_lba_range_done = false; 30782a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 30792a2b7296SJim Harris CU_ASSERT(rc == 0); 30802a2b7296SJim Harris poll_threads(); 30812a2b7296SJim Harris 30822a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 30832a2b7296SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 30842a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 30852a2b7296SJim Harris CU_ASSERT(range->offset == 20); 30862a2b7296SJim Harris CU_ASSERT(range->length == 10); 30872a2b7296SJim Harris 30882a2b7296SJim Harris /* Try to lock range 25-39. It should not lock immediately, since it overlaps with 30892a2b7296SJim Harris * 20-29. 30902a2b7296SJim Harris */ 30912a2b7296SJim Harris g_lock_lba_range_done = false; 30922a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 25, 15, lock_lba_range_done, &ctx1); 30932a2b7296SJim Harris CU_ASSERT(rc == 0); 30942a2b7296SJim Harris poll_threads(); 30952a2b7296SJim Harris 30962a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 30972a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.pending_locked_ranges); 30982a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 30992a2b7296SJim Harris CU_ASSERT(range->offset == 25); 31002a2b7296SJim Harris CU_ASSERT(range->length == 15); 31012a2b7296SJim Harris 31022a2b7296SJim Harris /* Unlock 20-29. This should result in range 25-39 now getting locked since it 31032a2b7296SJim Harris * no longer overlaps with an active lock. 31042a2b7296SJim Harris */ 31052a2b7296SJim Harris g_unlock_lba_range_done = false; 31062a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, unlock_lba_range_done, &ctx1); 31072a2b7296SJim Harris CU_ASSERT(rc == 0); 31082a2b7296SJim Harris poll_threads(); 31092a2b7296SJim Harris 31102a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 31112a2b7296SJim Harris CU_ASSERT(TAILQ_EMPTY(&bdev->internal.pending_locked_ranges)); 31122a2b7296SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 31132a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 31142a2b7296SJim Harris CU_ASSERT(range->offset == 25); 31152a2b7296SJim Harris CU_ASSERT(range->length == 15); 31162a2b7296SJim Harris 31172a2b7296SJim Harris /* Lock 40-59. This should immediately lock since it does not overlap with the 31182a2b7296SJim Harris * currently active 25-39 lock. 31192a2b7296SJim Harris */ 31202a2b7296SJim Harris g_lock_lba_range_done = false; 31212a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 40, 20, lock_lba_range_done, &ctx1); 31222a2b7296SJim Harris CU_ASSERT(rc == 0); 31232a2b7296SJim Harris poll_threads(); 31242a2b7296SJim Harris 31252a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 31262a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.locked_ranges); 31272a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 31282a2b7296SJim Harris range = TAILQ_NEXT(range, tailq); 31292a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 31302a2b7296SJim Harris CU_ASSERT(range->offset == 40); 31312a2b7296SJim Harris CU_ASSERT(range->length == 20); 31322a2b7296SJim Harris 31332a2b7296SJim Harris /* Try to lock 35-44. Note that this overlaps with both 25-39 and 40-59. */ 31342a2b7296SJim Harris g_lock_lba_range_done = false; 31352a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 35, 10, lock_lba_range_done, &ctx1); 31362a2b7296SJim Harris CU_ASSERT(rc == 0); 31372a2b7296SJim Harris poll_threads(); 31382a2b7296SJim Harris 31392a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 31402a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.pending_locked_ranges); 31412a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 31422a2b7296SJim Harris CU_ASSERT(range->offset == 35); 31432a2b7296SJim Harris CU_ASSERT(range->length == 10); 31442a2b7296SJim Harris 31452a2b7296SJim Harris /* Unlock 25-39. Make sure that 35-44 is still in the pending list, since 31462a2b7296SJim Harris * the 40-59 lock is still active. 31472a2b7296SJim Harris */ 31482a2b7296SJim Harris g_unlock_lba_range_done = false; 31492a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 25, 15, unlock_lba_range_done, &ctx1); 31502a2b7296SJim Harris CU_ASSERT(rc == 0); 31512a2b7296SJim Harris poll_threads(); 31522a2b7296SJim Harris 31532a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 31542a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 31552a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.pending_locked_ranges); 31562a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 31572a2b7296SJim Harris CU_ASSERT(range->offset == 35); 31582a2b7296SJim Harris CU_ASSERT(range->length == 10); 31592a2b7296SJim Harris 31602a2b7296SJim Harris /* Unlock 40-59. This should result in 35-44 now getting locked, since there are 31612a2b7296SJim Harris * no longer any active overlapping locks. 31622a2b7296SJim Harris */ 31632a2b7296SJim Harris g_unlock_lba_range_done = false; 31642a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 40, 20, unlock_lba_range_done, &ctx1); 31652a2b7296SJim Harris CU_ASSERT(rc == 0); 31662a2b7296SJim Harris poll_threads(); 31672a2b7296SJim Harris 31682a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 31692a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 31702a2b7296SJim Harris CU_ASSERT(TAILQ_EMPTY(&bdev->internal.pending_locked_ranges)); 31712a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.locked_ranges); 31722a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 31732a2b7296SJim Harris CU_ASSERT(range->offset == 35); 31742a2b7296SJim Harris CU_ASSERT(range->length == 10); 31752a2b7296SJim Harris 31762a2b7296SJim Harris /* Finally, unlock 35-44. */ 31772a2b7296SJim Harris g_unlock_lba_range_done = false; 31782a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 35, 10, unlock_lba_range_done, &ctx1); 31792a2b7296SJim Harris CU_ASSERT(rc == 0); 31802a2b7296SJim Harris poll_threads(); 31812a2b7296SJim Harris 31822a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 31832a2b7296SJim Harris CU_ASSERT(TAILQ_EMPTY(&bdev->internal.locked_ranges)); 31842a2b7296SJim Harris 31852a2b7296SJim Harris spdk_put_io_channel(io_ch); 31862a2b7296SJim Harris spdk_bdev_close(desc); 31872a2b7296SJim Harris free_bdev(bdev); 31882a2b7296SJim Harris spdk_bdev_finish(bdev_fini_cb, NULL); 31892a2b7296SJim Harris poll_threads(); 31902a2b7296SJim Harris } 31912a2b7296SJim Harris 31927cd20dd3SShuhei Matsumoto static void 31937cd20dd3SShuhei Matsumoto abort_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 31947cd20dd3SShuhei Matsumoto { 31957cd20dd3SShuhei Matsumoto g_abort_done = true; 31967cd20dd3SShuhei Matsumoto g_abort_status = bdev_io->internal.status; 31977cd20dd3SShuhei Matsumoto spdk_bdev_free_io(bdev_io); 31987cd20dd3SShuhei Matsumoto } 31997cd20dd3SShuhei Matsumoto 32007cd20dd3SShuhei Matsumoto static void 32017cd20dd3SShuhei Matsumoto bdev_io_abort(void) 32027cd20dd3SShuhei Matsumoto { 32037cd20dd3SShuhei Matsumoto struct spdk_bdev *bdev; 32047cd20dd3SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 32057cd20dd3SShuhei Matsumoto struct spdk_io_channel *io_ch; 320697a5ea57SShuhei Matsumoto struct spdk_bdev_channel *channel; 320797a5ea57SShuhei Matsumoto struct spdk_bdev_mgmt_channel *mgmt_ch; 32087cd20dd3SShuhei Matsumoto struct spdk_bdev_opts bdev_opts = { 320997a5ea57SShuhei Matsumoto .bdev_io_pool_size = 7, 32107cd20dd3SShuhei Matsumoto .bdev_io_cache_size = 2, 32117cd20dd3SShuhei Matsumoto }; 321297a5ea57SShuhei Matsumoto struct iovec iov[BDEV_IO_NUM_CHILD_IOV * 2]; 321397a5ea57SShuhei Matsumoto uint64_t io_ctx1 = 0, io_ctx2 = 0, i; 32147cd20dd3SShuhei Matsumoto int rc; 32157cd20dd3SShuhei Matsumoto 32167cd20dd3SShuhei Matsumoto rc = spdk_bdev_set_opts(&bdev_opts); 32177cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 32187cd20dd3SShuhei Matsumoto spdk_bdev_initialize(bdev_init_cb, NULL); 32197cd20dd3SShuhei Matsumoto 32207cd20dd3SShuhei Matsumoto bdev = allocate_bdev("bdev0"); 32217cd20dd3SShuhei Matsumoto 3222*75dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 32237cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 32247cd20dd3SShuhei Matsumoto CU_ASSERT(desc != NULL); 3225*75dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 32267cd20dd3SShuhei Matsumoto io_ch = spdk_bdev_get_io_channel(desc); 32277cd20dd3SShuhei Matsumoto CU_ASSERT(io_ch != NULL); 322897a5ea57SShuhei Matsumoto channel = spdk_io_channel_get_ctx(io_ch); 322997a5ea57SShuhei Matsumoto mgmt_ch = channel->shared_resource->mgmt_ch; 32307cd20dd3SShuhei Matsumoto 32317cd20dd3SShuhei Matsumoto g_abort_done = false; 32327cd20dd3SShuhei Matsumoto 32337cd20dd3SShuhei Matsumoto ut_enable_io_type(SPDK_BDEV_IO_TYPE_ABORT, false); 32347cd20dd3SShuhei Matsumoto 32357cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 32367cd20dd3SShuhei Matsumoto CU_ASSERT(rc == -ENOTSUP); 32377cd20dd3SShuhei Matsumoto 32387cd20dd3SShuhei Matsumoto ut_enable_io_type(SPDK_BDEV_IO_TYPE_ABORT, true); 32397cd20dd3SShuhei Matsumoto 32407cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx2, abort_done, NULL); 32417cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 32427cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 32437cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_FAILED); 32447cd20dd3SShuhei Matsumoto 32457cd20dd3SShuhei Matsumoto /* Test the case that the target I/O was successfully aborted. */ 32467cd20dd3SShuhei Matsumoto g_io_done = false; 32477cd20dd3SShuhei Matsumoto 32487cd20dd3SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, &io_ctx1); 32497cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 32507cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == false); 32517cd20dd3SShuhei Matsumoto 32527cd20dd3SShuhei Matsumoto g_abort_done = false; 32537cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 32547cd20dd3SShuhei Matsumoto 32557cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 32567cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 32577cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == true); 32587cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 32597cd20dd3SShuhei Matsumoto stub_complete_io(1); 32607cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 32617cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 32627cd20dd3SShuhei Matsumoto 32637cd20dd3SShuhei Matsumoto /* Test the case that the target I/O was not aborted because it completed 32647cd20dd3SShuhei Matsumoto * in the middle of execution of the abort. 32657cd20dd3SShuhei Matsumoto */ 32667cd20dd3SShuhei Matsumoto g_io_done = false; 32677cd20dd3SShuhei Matsumoto 32687cd20dd3SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, &io_ctx1); 32697cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 32707cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == false); 32717cd20dd3SShuhei Matsumoto 32727cd20dd3SShuhei Matsumoto g_abort_done = false; 32737cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 32747cd20dd3SShuhei Matsumoto 32757cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 32767cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 32777cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == false); 32787cd20dd3SShuhei Matsumoto 32797cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 32807cd20dd3SShuhei Matsumoto stub_complete_io(1); 32817cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == true); 32827cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 32837cd20dd3SShuhei Matsumoto 32847cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 32857cd20dd3SShuhei Matsumoto stub_complete_io(1); 32867cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 32877cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 32887cd20dd3SShuhei Matsumoto 32897cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 32907cd20dd3SShuhei Matsumoto 329197a5ea57SShuhei Matsumoto bdev->optimal_io_boundary = 16; 329297a5ea57SShuhei Matsumoto bdev->split_on_optimal_io_boundary = true; 329397a5ea57SShuhei Matsumoto 329497a5ea57SShuhei Matsumoto /* Test that a single-vector command which is split is aborted correctly. 329597a5ea57SShuhei Matsumoto * Offset 14, length 8, payload 0xF000 329697a5ea57SShuhei Matsumoto * Child - Offset 14, length 2, payload 0xF000 329797a5ea57SShuhei Matsumoto * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 329897a5ea57SShuhei Matsumoto */ 329997a5ea57SShuhei Matsumoto g_io_done = false; 330097a5ea57SShuhei Matsumoto 330197a5ea57SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, &io_ctx1); 330297a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 330397a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == false); 330497a5ea57SShuhei Matsumoto 330597a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 330697a5ea57SShuhei Matsumoto 330797a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 330897a5ea57SShuhei Matsumoto 330997a5ea57SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 331097a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 331197a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == true); 331297a5ea57SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 331397a5ea57SShuhei Matsumoto stub_complete_io(2); 331497a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 331597a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 331697a5ea57SShuhei Matsumoto 331797a5ea57SShuhei Matsumoto /* Test that a multi-vector command that needs to be split by strip and then 331897a5ea57SShuhei Matsumoto * needs to be split is aborted correctly. Abort is requested before the second 331997a5ea57SShuhei Matsumoto * child I/O was submitted. The parent I/O should complete with failure without 332097a5ea57SShuhei Matsumoto * submitting the second child I/O. 332197a5ea57SShuhei Matsumoto */ 332297a5ea57SShuhei Matsumoto for (i = 0; i < BDEV_IO_NUM_CHILD_IOV * 2; i++) { 332397a5ea57SShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 332497a5ea57SShuhei Matsumoto iov[i].iov_len = 512; 332597a5ea57SShuhei Matsumoto } 332697a5ea57SShuhei Matsumoto 332797a5ea57SShuhei Matsumoto bdev->optimal_io_boundary = BDEV_IO_NUM_CHILD_IOV; 332897a5ea57SShuhei Matsumoto g_io_done = false; 332997a5ea57SShuhei Matsumoto rc = spdk_bdev_readv_blocks(desc, io_ch, iov, BDEV_IO_NUM_CHILD_IOV * 2, 0, 333097a5ea57SShuhei Matsumoto BDEV_IO_NUM_CHILD_IOV * 2, io_done, &io_ctx1); 333197a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 333297a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == false); 333397a5ea57SShuhei Matsumoto 333497a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 333597a5ea57SShuhei Matsumoto 333697a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 333797a5ea57SShuhei Matsumoto 333897a5ea57SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 333997a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 334097a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == true); 334197a5ea57SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 334297a5ea57SShuhei Matsumoto stub_complete_io(1); 334397a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 334497a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 334597a5ea57SShuhei Matsumoto 334697a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 334797a5ea57SShuhei Matsumoto 334897a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 334997a5ea57SShuhei Matsumoto 335097a5ea57SShuhei Matsumoto bdev->optimal_io_boundary = 16; 335197a5ea57SShuhei Matsumoto g_io_done = false; 335297a5ea57SShuhei Matsumoto 335397a5ea57SShuhei Matsumoto /* Test that a ingle-vector command which is split is aborted correctly. 335497a5ea57SShuhei Matsumoto * Differently from the above, the child abort request will be submitted 335597a5ea57SShuhei Matsumoto * sequentially due to the capacity of spdk_bdev_io. 335697a5ea57SShuhei Matsumoto */ 335797a5ea57SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 50, io_done, &io_ctx1); 335897a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 335997a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == false); 336097a5ea57SShuhei Matsumoto 336197a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 336297a5ea57SShuhei Matsumoto 336397a5ea57SShuhei Matsumoto g_abort_done = false; 336497a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 336597a5ea57SShuhei Matsumoto 336697a5ea57SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 336797a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 336897a5ea57SShuhei Matsumoto CU_ASSERT(!TAILQ_EMPTY(&mgmt_ch->io_wait_queue)); 336997a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 337097a5ea57SShuhei Matsumoto 337197a5ea57SShuhei Matsumoto stub_complete_io(1); 337297a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == true); 337397a5ea57SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 337497a5ea57SShuhei Matsumoto stub_complete_io(3); 337597a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 337697a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 337797a5ea57SShuhei Matsumoto 337897a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 337997a5ea57SShuhei Matsumoto 338097a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 338197a5ea57SShuhei Matsumoto 33827cd20dd3SShuhei Matsumoto spdk_put_io_channel(io_ch); 33837cd20dd3SShuhei Matsumoto spdk_bdev_close(desc); 33847cd20dd3SShuhei Matsumoto free_bdev(bdev); 33857cd20dd3SShuhei Matsumoto spdk_bdev_finish(bdev_fini_cb, NULL); 33867cd20dd3SShuhei Matsumoto poll_threads(); 33877cd20dd3SShuhei Matsumoto } 33887cd20dd3SShuhei Matsumoto 33894ee51dcbSJim Harris int 33904ee51dcbSJim Harris main(int argc, char **argv) 33914ee51dcbSJim Harris { 33924ee51dcbSJim Harris CU_pSuite suite = NULL; 33934ee51dcbSJim Harris unsigned int num_failures; 33944ee51dcbSJim Harris 339578b696bcSVitaliy Mysak CU_set_error_action(CUEA_ABORT); 339678b696bcSVitaliy Mysak CU_initialize_registry(); 33974ee51dcbSJim Harris 33984ee51dcbSJim Harris suite = CU_add_suite("bdev", null_init, null_clean); 33994ee51dcbSJim Harris 3400dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bytes_to_blocks_test); 3401dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, num_blocks_test); 3402dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, io_valid_test); 3403dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, open_write_test); 3404dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, alias_add_del_test); 3405dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, get_device_stat_test); 3406dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_types_test); 3407dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_wait_test); 3408dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_spans_boundary_test); 3409dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_split_test); 3410dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_split_with_io_wait); 3411dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_alignment_with_boundary); 3412dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_alignment); 3413dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_histograms); 3414dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_write_zeroes); 3415dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_compare_and_write); 3416dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_compare); 3417dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_open_while_hotremove); 3418dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_close_while_hotremove); 3419dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_open_ext); 3420dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_set_io_timeout); 3421dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lba_range_overlap); 3422dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lock_lba_range_check_ranges); 3423dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lock_lba_range_with_io_outstanding); 3424dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lock_lba_range_overlapped); 34257cd20dd3SShuhei Matsumoto CU_ADD_TEST(suite, bdev_io_abort); 34264ee51dcbSJim Harris 3427972b3ae3SShuhei Matsumoto allocate_cores(1); 3428270a25dfSBen Walker allocate_threads(1); 3429270a25dfSBen Walker set_thread(0); 3430270a25dfSBen Walker 34314ee51dcbSJim Harris CU_basic_set_mode(CU_BRM_VERBOSE); 34324ee51dcbSJim Harris CU_basic_run_tests(); 34334ee51dcbSJim Harris num_failures = CU_get_number_of_failures(); 34344ee51dcbSJim Harris CU_cleanup_registry(); 3435270a25dfSBen Walker 3436270a25dfSBen Walker free_threads(); 3437972b3ae3SShuhei Matsumoto free_cores(); 3438270a25dfSBen Walker 34394ee51dcbSJim Harris return num_failures; 34404ee51dcbSJim Harris } 3441