1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2017 Intel Corporation. All rights reserved. 3437e54f7SEvgeniy Kochetov * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved. 44bb902a6SMike Gerdts * Copyright (c) 2021-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 54ee51dcbSJim Harris */ 64ee51dcbSJim Harris 7ae431e31SKonrad Sztyber #include "spdk_internal/cunit.h" 84ee51dcbSJim Harris 9270a25dfSBen Walker #include "common/lib/ut_multithread.c" 105ffa5c00SPawel Wodkowski #include "unit/lib/json_mock.c" 11229f6494SDaniel Verkamp 12c4fee1e9SPawel Wodkowski #include "spdk/config.h" 13229f6494SDaniel Verkamp /* HACK: disable VTune integration so the unit test doesn't need VTune headers and libs to build */ 14229f6494SDaniel Verkamp #undef SPDK_CONFIG_VTUNE 15229f6494SDaniel Verkamp 16d8c3ff5fSJim Harris #include "bdev/bdev.c" 174ee51dcbSJim Harris 18*ff173863SShuhei Matsumoto #include "common/lib/bdev/common_stubs.h" 191299439fSAlexey Marchuk 201299439fSAlexey Marchuk static bool g_memory_domain_pull_data_called; 211299439fSAlexey Marchuk static bool g_memory_domain_push_data_called; 2280b22cf3SKonrad Sztyber static int g_accel_io_device; 231299439fSAlexey Marchuk 241299439fSAlexey Marchuk DEFINE_RETURN_MOCK(spdk_memory_domain_pull_data, int); 251299439fSAlexey Marchuk int 261299439fSAlexey Marchuk spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx, 271299439fSAlexey Marchuk struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt, 281299439fSAlexey Marchuk spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) 291299439fSAlexey Marchuk { 301299439fSAlexey Marchuk g_memory_domain_pull_data_called = true; 311299439fSAlexey Marchuk HANDLE_RETURN_MOCK(spdk_memory_domain_pull_data); 321299439fSAlexey Marchuk cpl_cb(cpl_cb_arg, 0); 331299439fSAlexey Marchuk return 0; 341299439fSAlexey Marchuk } 351299439fSAlexey Marchuk 361299439fSAlexey Marchuk DEFINE_RETURN_MOCK(spdk_memory_domain_push_data, int); 371299439fSAlexey Marchuk int 381299439fSAlexey Marchuk spdk_memory_domain_push_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx, 391299439fSAlexey Marchuk struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt, 401299439fSAlexey Marchuk spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) 411299439fSAlexey Marchuk { 421299439fSAlexey Marchuk g_memory_domain_push_data_called = true; 431299439fSAlexey Marchuk HANDLE_RETURN_MOCK(spdk_memory_domain_push_data); 441299439fSAlexey Marchuk cpl_cb(cpl_cb_arg, 0); 451299439fSAlexey Marchuk return 0; 461299439fSAlexey Marchuk } 471d83a09dSPiotr Pelplinski 4880b22cf3SKonrad Sztyber struct spdk_io_channel * 4980b22cf3SKonrad Sztyber spdk_accel_get_io_channel(void) 5080b22cf3SKonrad Sztyber { 5180b22cf3SKonrad Sztyber return spdk_get_io_channel(&g_accel_io_device); 5280b22cf3SKonrad Sztyber } 5380b22cf3SKonrad Sztyber 5442dba604SPiotr Pelplinski int g_status; 5542dba604SPiotr Pelplinski int g_count; 5679ed1ba1SMaciej Szwed enum spdk_bdev_event_type g_event_type1; 5779ed1ba1SMaciej Szwed enum spdk_bdev_event_type g_event_type2; 587bcd316dSGangCao enum spdk_bdev_event_type g_event_type3; 597bcd316dSGangCao enum spdk_bdev_event_type g_event_type4; 6042dba604SPiotr Pelplinski struct spdk_histogram_data *g_histogram; 6123975858SEvgeniy Kochetov void *g_unregister_arg; 6223975858SEvgeniy Kochetov int g_unregister_rc; 6342dba604SPiotr Pelplinski 644ee51dcbSJim Harris void 654ee51dcbSJim Harris spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io, 664ee51dcbSJim Harris int *sc, int *sk, int *asc, int *ascq) 674ee51dcbSJim Harris { 684ee51dcbSJim Harris } 694ee51dcbSJim Harris 704ee51dcbSJim Harris static int 7180b22cf3SKonrad Sztyber ut_accel_ch_create_cb(void *io_device, void *ctx) 724ee51dcbSJim Harris { 734ee51dcbSJim Harris return 0; 744ee51dcbSJim Harris } 754ee51dcbSJim Harris 7680b22cf3SKonrad Sztyber static void 7780b22cf3SKonrad Sztyber ut_accel_ch_destroy_cb(void *io_device, void *ctx) 784ee51dcbSJim Harris { 7980b22cf3SKonrad Sztyber } 8080b22cf3SKonrad Sztyber 8180b22cf3SKonrad Sztyber static int 8280b22cf3SKonrad Sztyber ut_bdev_setup(void) 8380b22cf3SKonrad Sztyber { 8480b22cf3SKonrad Sztyber spdk_io_device_register(&g_accel_io_device, ut_accel_ch_create_cb, 8580b22cf3SKonrad Sztyber ut_accel_ch_destroy_cb, 0, NULL); 8680b22cf3SKonrad Sztyber return 0; 8780b22cf3SKonrad Sztyber } 8880b22cf3SKonrad Sztyber 8980b22cf3SKonrad Sztyber static int 9080b22cf3SKonrad Sztyber ut_bdev_teardown(void) 9180b22cf3SKonrad Sztyber { 9280b22cf3SKonrad Sztyber spdk_io_device_unregister(&g_accel_io_device, NULL); 9380b22cf3SKonrad Sztyber 944ee51dcbSJim Harris return 0; 954ee51dcbSJim Harris } 964ee51dcbSJim Harris 9757d174ffSJim Harris static int 9857d174ffSJim Harris stub_destruct(void *ctx) 994ee51dcbSJim Harris { 10057d174ffSJim Harris return 0; 10157d174ffSJim Harris } 10257d174ffSJim Harris 1033c7894ffSShuhei Matsumoto struct ut_expected_io { 1043c7894ffSShuhei Matsumoto uint8_t type; 1053c7894ffSShuhei Matsumoto uint64_t offset; 1066c8702acSEvgeniy Kochetov uint64_t src_offset; 1073c7894ffSShuhei Matsumoto uint64_t length; 1083c7894ffSShuhei Matsumoto int iovcnt; 109b45556e2SChangpeng Liu struct iovec iov[SPDK_BDEV_IO_NUM_CHILD_IOV]; 110e2918289SKonrad Sztyber void *md_buf; 1113c7894ffSShuhei Matsumoto TAILQ_ENTRY(ut_expected_io) link; 1123c7894ffSShuhei Matsumoto }; 1133c7894ffSShuhei Matsumoto 114dc996557SBen Walker struct bdev_ut_io { 115dc996557SBen Walker TAILQ_ENTRY(bdev_ut_io) link; 116dc996557SBen Walker }; 117dc996557SBen Walker 11832d7c91cSJim Harris struct bdev_ut_channel { 119dc996557SBen Walker TAILQ_HEAD(, bdev_ut_io) outstanding_io; 12032d7c91cSJim Harris uint32_t outstanding_io_count; 1213c7894ffSShuhei Matsumoto TAILQ_HEAD(, ut_expected_io) expected_io; 12232d7c91cSJim Harris }; 12332d7c91cSJim Harris 1244bd97621SJim Harris static bool g_io_done; 125dadd2a6dSPiotr Pelplinski static struct spdk_bdev_io *g_bdev_io; 1260df515a8SShuhei Matsumoto static enum spdk_bdev_io_status g_io_status; 127c55c85f8SChangpeng Liu static enum spdk_bdev_io_status g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 12832d7c91cSJim Harris static uint32_t g_bdev_ut_io_device; 12932d7c91cSJim Harris static struct bdev_ut_channel *g_bdev_ut_channel; 130ae43c81aSJim Harris static void *g_compare_read_buf; 131ae43c81aSJim Harris static uint32_t g_compare_read_buf_len; 132ae43c81aSJim Harris static void *g_compare_write_buf; 133ae43c81aSJim Harris static uint32_t g_compare_write_buf_len; 1340bd6b7f2SJonas Pfefferle static void *g_compare_md_buf; 1357cd20dd3SShuhei Matsumoto static bool g_abort_done; 1367cd20dd3SShuhei Matsumoto static enum spdk_bdev_io_status g_abort_status; 1376127461cSmatthewb static void *g_zcopy_read_buf; 1386127461cSmatthewb static uint32_t g_zcopy_read_buf_len; 1396127461cSmatthewb static void *g_zcopy_write_buf; 1406127461cSmatthewb static uint32_t g_zcopy_write_buf_len; 1416127461cSmatthewb static struct spdk_bdev_io *g_zcopy_bdev_io; 1426defafc9SDamiano static uint64_t g_seek_data_offset; 1436defafc9SDamiano static uint64_t g_seek_hole_offset; 1446defafc9SDamiano static uint64_t g_seek_offset; 14532d7c91cSJim Harris 1463c7894ffSShuhei Matsumoto static struct ut_expected_io * 1473c7894ffSShuhei Matsumoto ut_alloc_expected_io(uint8_t type, uint64_t offset, uint64_t length, int iovcnt) 1483c7894ffSShuhei Matsumoto { 1493c7894ffSShuhei Matsumoto struct ut_expected_io *expected_io; 1503c7894ffSShuhei Matsumoto 1513c7894ffSShuhei Matsumoto expected_io = calloc(1, sizeof(*expected_io)); 1523c7894ffSShuhei Matsumoto SPDK_CU_ASSERT_FATAL(expected_io != NULL); 1533c7894ffSShuhei Matsumoto 1543c7894ffSShuhei Matsumoto expected_io->type = type; 1553c7894ffSShuhei Matsumoto expected_io->offset = offset; 1563c7894ffSShuhei Matsumoto expected_io->length = length; 1573c7894ffSShuhei Matsumoto expected_io->iovcnt = iovcnt; 1583c7894ffSShuhei Matsumoto 1593c7894ffSShuhei Matsumoto return expected_io; 1603c7894ffSShuhei Matsumoto } 1613c7894ffSShuhei Matsumoto 1626c8702acSEvgeniy Kochetov static struct ut_expected_io * 1636c8702acSEvgeniy Kochetov ut_alloc_expected_copy_io(uint8_t type, uint64_t offset, uint64_t src_offset, uint64_t length) 1646c8702acSEvgeniy Kochetov { 1656c8702acSEvgeniy Kochetov struct ut_expected_io *expected_io; 1666c8702acSEvgeniy Kochetov 1676c8702acSEvgeniy Kochetov expected_io = calloc(1, sizeof(*expected_io)); 1686c8702acSEvgeniy Kochetov SPDK_CU_ASSERT_FATAL(expected_io != NULL); 1696c8702acSEvgeniy Kochetov 1706c8702acSEvgeniy Kochetov expected_io->type = type; 1716c8702acSEvgeniy Kochetov expected_io->offset = offset; 1726c8702acSEvgeniy Kochetov expected_io->src_offset = src_offset; 1736c8702acSEvgeniy Kochetov expected_io->length = length; 1746c8702acSEvgeniy Kochetov 1756c8702acSEvgeniy Kochetov return expected_io; 1766c8702acSEvgeniy Kochetov } 1776c8702acSEvgeniy Kochetov 1783c7894ffSShuhei Matsumoto static void 1793c7894ffSShuhei Matsumoto ut_expected_io_set_iov(struct ut_expected_io *expected_io, int pos, void *base, size_t len) 1803c7894ffSShuhei Matsumoto { 1813c7894ffSShuhei Matsumoto expected_io->iov[pos].iov_base = base; 1823c7894ffSShuhei Matsumoto expected_io->iov[pos].iov_len = len; 1833c7894ffSShuhei Matsumoto } 1843c7894ffSShuhei Matsumoto 18532d7c91cSJim Harris static void 18632d7c91cSJim Harris stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 18732d7c91cSJim Harris { 18832d7c91cSJim Harris struct bdev_ut_channel *ch = spdk_io_channel_get_ctx(_ch); 1893c7894ffSShuhei Matsumoto struct ut_expected_io *expected_io; 1904bd97621SJim Harris struct iovec *iov, *expected_iov; 1917cd20dd3SShuhei Matsumoto struct spdk_bdev_io *bio_to_abort; 192dc996557SBen Walker struct bdev_ut_io *bio; 1934bd97621SJim Harris int i; 19432d7c91cSJim Harris 195dadd2a6dSPiotr Pelplinski g_bdev_io = bdev_io; 196dadd2a6dSPiotr Pelplinski 197ae43c81aSJim Harris if (g_compare_read_buf && bdev_io->type == SPDK_BDEV_IO_TYPE_READ) { 198ae43c81aSJim Harris uint32_t len = bdev_io->u.bdev.iovs[0].iov_len; 199ae43c81aSJim Harris 200ae43c81aSJim Harris CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 201ae43c81aSJim Harris CU_ASSERT(g_compare_read_buf_len == len); 202ae43c81aSJim Harris memcpy(bdev_io->u.bdev.iovs[0].iov_base, g_compare_read_buf, len); 2030bd6b7f2SJonas Pfefferle if (bdev_io->bdev->md_len && bdev_io->u.bdev.md_buf && g_compare_md_buf) { 2040bd6b7f2SJonas Pfefferle memcpy(bdev_io->u.bdev.md_buf, g_compare_md_buf, 2050bd6b7f2SJonas Pfefferle bdev_io->bdev->md_len * bdev_io->u.bdev.num_blocks); 2060bd6b7f2SJonas Pfefferle } 207ae43c81aSJim Harris } 208ae43c81aSJim Harris 209ae43c81aSJim Harris if (g_compare_write_buf && bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) { 210ae43c81aSJim Harris uint32_t len = bdev_io->u.bdev.iovs[0].iov_len; 211ae43c81aSJim Harris 212ae43c81aSJim Harris CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 213ae43c81aSJim Harris CU_ASSERT(g_compare_write_buf_len == len); 214ae43c81aSJim Harris memcpy(g_compare_write_buf, bdev_io->u.bdev.iovs[0].iov_base, len); 215ae43c81aSJim Harris } 216ae43c81aSJim Harris 217ca0eeaabSMaciej Szwed if (g_compare_read_buf && bdev_io->type == SPDK_BDEV_IO_TYPE_COMPARE) { 218ca0eeaabSMaciej Szwed uint32_t len = bdev_io->u.bdev.iovs[0].iov_len; 219ca0eeaabSMaciej Szwed 220ca0eeaabSMaciej Szwed CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 221ca0eeaabSMaciej Szwed CU_ASSERT(g_compare_read_buf_len == len); 222ca0eeaabSMaciej Szwed if (memcmp(bdev_io->u.bdev.iovs[0].iov_base, g_compare_read_buf, len)) { 223ca0eeaabSMaciej Szwed g_io_exp_status = SPDK_BDEV_IO_STATUS_MISCOMPARE; 224ca0eeaabSMaciej Szwed } 2250bd6b7f2SJonas Pfefferle if (bdev_io->u.bdev.md_buf && 2260bd6b7f2SJonas Pfefferle memcmp(bdev_io->u.bdev.md_buf, g_compare_md_buf, 2270bd6b7f2SJonas Pfefferle bdev_io->bdev->md_len * bdev_io->u.bdev.num_blocks)) { 2280bd6b7f2SJonas Pfefferle g_io_exp_status = SPDK_BDEV_IO_STATUS_MISCOMPARE; 2290bd6b7f2SJonas Pfefferle } 230ca0eeaabSMaciej Szwed } 231ca0eeaabSMaciej Szwed 2327cd20dd3SShuhei Matsumoto if (bdev_io->type == SPDK_BDEV_IO_TYPE_ABORT) { 2337cd20dd3SShuhei Matsumoto if (g_io_exp_status == SPDK_BDEV_IO_STATUS_SUCCESS) { 234dc996557SBen Walker TAILQ_FOREACH(bio, &ch->outstanding_io, link) { 235dc996557SBen Walker bio_to_abort = spdk_bdev_io_from_ctx(bio); 2367cd20dd3SShuhei Matsumoto if (bio_to_abort == bdev_io->u.abort.bio_to_abort) { 237dc996557SBen Walker TAILQ_REMOVE(&ch->outstanding_io, bio, link); 2387cd20dd3SShuhei Matsumoto ch->outstanding_io_count--; 2397cd20dd3SShuhei Matsumoto spdk_bdev_io_complete(bio_to_abort, SPDK_BDEV_IO_STATUS_FAILED); 2407cd20dd3SShuhei Matsumoto break; 2417cd20dd3SShuhei Matsumoto } 2427cd20dd3SShuhei Matsumoto } 2437cd20dd3SShuhei Matsumoto } 2447cd20dd3SShuhei Matsumoto } 2457cd20dd3SShuhei Matsumoto 2466127461cSmatthewb if (bdev_io->type == SPDK_BDEV_IO_TYPE_ZCOPY) { 2476127461cSmatthewb if (bdev_io->u.bdev.zcopy.start) { 2486127461cSmatthewb g_zcopy_bdev_io = bdev_io; 2496127461cSmatthewb if (bdev_io->u.bdev.zcopy.populate) { 2506127461cSmatthewb /* Start of a read */ 2516127461cSmatthewb CU_ASSERT(g_zcopy_read_buf != NULL); 2526127461cSmatthewb CU_ASSERT(g_zcopy_read_buf_len > 0); 2536127461cSmatthewb bdev_io->u.bdev.iovs[0].iov_base = g_zcopy_read_buf; 2546127461cSmatthewb bdev_io->u.bdev.iovs[0].iov_len = g_zcopy_read_buf_len; 2556127461cSmatthewb bdev_io->u.bdev.iovcnt = 1; 2566127461cSmatthewb } else { 2576127461cSmatthewb /* Start of a write */ 2586127461cSmatthewb CU_ASSERT(g_zcopy_write_buf != NULL); 2596127461cSmatthewb CU_ASSERT(g_zcopy_write_buf_len > 0); 2606127461cSmatthewb bdev_io->u.bdev.iovs[0].iov_base = g_zcopy_write_buf; 2616127461cSmatthewb bdev_io->u.bdev.iovs[0].iov_len = g_zcopy_write_buf_len; 2626127461cSmatthewb bdev_io->u.bdev.iovcnt = 1; 2636127461cSmatthewb } 2646127461cSmatthewb } else { 2656127461cSmatthewb if (bdev_io->u.bdev.zcopy.commit) { 2666127461cSmatthewb /* End of write */ 2676127461cSmatthewb CU_ASSERT(bdev_io->u.bdev.iovs[0].iov_base == g_zcopy_write_buf); 2686127461cSmatthewb CU_ASSERT(bdev_io->u.bdev.iovs[0].iov_len == g_zcopy_write_buf_len); 2696127461cSmatthewb CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 2706127461cSmatthewb g_zcopy_write_buf = NULL; 2716127461cSmatthewb g_zcopy_write_buf_len = 0; 2726127461cSmatthewb } else { 2736127461cSmatthewb /* End of read */ 2746127461cSmatthewb CU_ASSERT(bdev_io->u.bdev.iovs[0].iov_base == g_zcopy_read_buf); 2756127461cSmatthewb CU_ASSERT(bdev_io->u.bdev.iovs[0].iov_len == g_zcopy_read_buf_len); 2766127461cSmatthewb CU_ASSERT(bdev_io->u.bdev.iovcnt == 1); 2776127461cSmatthewb g_zcopy_read_buf = NULL; 2786127461cSmatthewb g_zcopy_read_buf_len = 0; 2796127461cSmatthewb } 2806127461cSmatthewb } 2816127461cSmatthewb } 2826127461cSmatthewb 2836defafc9SDamiano if (bdev_io->type == SPDK_BDEV_IO_TYPE_SEEK_DATA) { 2846defafc9SDamiano bdev_io->u.bdev.seek.offset = g_seek_data_offset; 2856defafc9SDamiano } 2866defafc9SDamiano 2876defafc9SDamiano if (bdev_io->type == SPDK_BDEV_IO_TYPE_SEEK_HOLE) { 2886defafc9SDamiano bdev_io->u.bdev.seek.offset = g_seek_hole_offset; 2896defafc9SDamiano } 2906defafc9SDamiano 291dc996557SBen Walker TAILQ_INSERT_TAIL(&ch->outstanding_io, (struct bdev_ut_io *)bdev_io->driver_ctx, link); 29232d7c91cSJim Harris ch->outstanding_io_count++; 2934bd97621SJim Harris 2943c7894ffSShuhei Matsumoto expected_io = TAILQ_FIRST(&ch->expected_io); 2953c7894ffSShuhei Matsumoto if (expected_io == NULL) { 2963c7894ffSShuhei Matsumoto return; 2973c7894ffSShuhei Matsumoto } 2983c7894ffSShuhei Matsumoto TAILQ_REMOVE(&ch->expected_io, expected_io, link); 2993c7894ffSShuhei Matsumoto 3003c7894ffSShuhei Matsumoto if (expected_io->type != SPDK_BDEV_IO_TYPE_INVALID) { 3013c7894ffSShuhei Matsumoto CU_ASSERT(bdev_io->type == expected_io->type); 3024bd97621SJim Harris } 3034bd97621SJim Harris 304e2918289SKonrad Sztyber if (expected_io->md_buf != NULL) { 305e2918289SKonrad Sztyber CU_ASSERT(expected_io->md_buf == bdev_io->u.bdev.md_buf); 306442e13c0SJonas Pfefferle } 307442e13c0SJonas Pfefferle 3083c7894ffSShuhei Matsumoto if (expected_io->length == 0) { 3093c7894ffSShuhei Matsumoto free(expected_io); 3104bd97621SJim Harris return; 3114bd97621SJim Harris } 3124bd97621SJim Harris 3133c7894ffSShuhei Matsumoto CU_ASSERT(expected_io->offset == bdev_io->u.bdev.offset_blocks); 314c26697bfSSlawomir Ptak CU_ASSERT(expected_io->length == bdev_io->u.bdev.num_blocks); 3156c8702acSEvgeniy Kochetov if (expected_io->type == SPDK_BDEV_IO_TYPE_COPY) { 3166c8702acSEvgeniy Kochetov CU_ASSERT(expected_io->src_offset == bdev_io->u.bdev.copy.src_offset_blocks); 3176c8702acSEvgeniy Kochetov } 3184bd97621SJim Harris 3193c7894ffSShuhei Matsumoto if (expected_io->iovcnt == 0) { 3203c7894ffSShuhei Matsumoto free(expected_io); 3216c8702acSEvgeniy Kochetov /* UNMAP, WRITE_ZEROES, FLUSH and COPY don't have iovs, so we can just return now. */ 3224bd97621SJim Harris return; 3234bd97621SJim Harris } 3244bd97621SJim Harris 3253c7894ffSShuhei Matsumoto CU_ASSERT(expected_io->iovcnt == bdev_io->u.bdev.iovcnt); 3263c7894ffSShuhei Matsumoto for (i = 0; i < expected_io->iovcnt; i++) { 3273c7894ffSShuhei Matsumoto expected_iov = &expected_io->iov[i]; 3287fee8002SBen Walker if (bdev_io->internal.f.has_bounce_buf == false) { 329c03985a0SAlexey Marchuk iov = &bdev_io->u.bdev.iovs[i]; 330c03985a0SAlexey Marchuk } else { 3317fee8002SBen Walker iov = bdev_io->internal.bounce_buf.orig_iovs; 332c03985a0SAlexey Marchuk } 3334bd97621SJim Harris CU_ASSERT(iov->iov_len == expected_iov->iov_len); 3344bd97621SJim Harris CU_ASSERT(iov->iov_base == expected_iov->iov_base); 3354bd97621SJim Harris } 3363c7894ffSShuhei Matsumoto 3373c7894ffSShuhei Matsumoto free(expected_io); 33832d7c91cSJim Harris } 33932d7c91cSJim Harris 340dadd2a6dSPiotr Pelplinski static void 34180da9548SMaciej Szwed stub_submit_request_get_buf_cb(struct spdk_io_channel *_ch, 3424b92ffb3SShuhei Matsumoto struct spdk_bdev_io *bdev_io, bool success) 3434b92ffb3SShuhei Matsumoto { 3444b92ffb3SShuhei Matsumoto CU_ASSERT(success == true); 3454b92ffb3SShuhei Matsumoto 3464b92ffb3SShuhei Matsumoto stub_submit_request(_ch, bdev_io); 3474b92ffb3SShuhei Matsumoto } 3484b92ffb3SShuhei Matsumoto 3494b92ffb3SShuhei Matsumoto static void 35080da9548SMaciej Szwed stub_submit_request_get_buf(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 351dadd2a6dSPiotr Pelplinski { 35280da9548SMaciej Szwed spdk_bdev_io_get_buf(bdev_io, stub_submit_request_get_buf_cb, 353dadd2a6dSPiotr Pelplinski bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); 354dadd2a6dSPiotr Pelplinski } 355dadd2a6dSPiotr Pelplinski 35632d7c91cSJim Harris static uint32_t 35732d7c91cSJim Harris stub_complete_io(uint32_t num_to_complete) 35832d7c91cSJim Harris { 35932d7c91cSJim Harris struct bdev_ut_channel *ch = g_bdev_ut_channel; 360dc996557SBen Walker struct bdev_ut_io *bio; 36132d7c91cSJim Harris struct spdk_bdev_io *bdev_io; 362c55c85f8SChangpeng Liu static enum spdk_bdev_io_status io_status; 36332d7c91cSJim Harris uint32_t num_completed = 0; 36432d7c91cSJim Harris 36532d7c91cSJim Harris while (num_completed < num_to_complete) { 36632d7c91cSJim Harris if (TAILQ_EMPTY(&ch->outstanding_io)) { 36732d7c91cSJim Harris break; 36832d7c91cSJim Harris } 369dc996557SBen Walker bio = TAILQ_FIRST(&ch->outstanding_io); 370dc996557SBen Walker TAILQ_REMOVE(&ch->outstanding_io, bio, link); 371dc996557SBen Walker bdev_io = spdk_bdev_io_from_ctx(bio); 37232d7c91cSJim Harris ch->outstanding_io_count--; 373c55c85f8SChangpeng Liu io_status = g_io_exp_status == SPDK_BDEV_IO_STATUS_SUCCESS ? SPDK_BDEV_IO_STATUS_SUCCESS : 374c55c85f8SChangpeng Liu g_io_exp_status; 375c55c85f8SChangpeng Liu spdk_bdev_io_complete(bdev_io, io_status); 37632d7c91cSJim Harris num_completed++; 37732d7c91cSJim Harris } 37832d7c91cSJim Harris 37932d7c91cSJim Harris return num_completed; 38032d7c91cSJim Harris } 38132d7c91cSJim Harris 38232d7c91cSJim Harris static struct spdk_io_channel * 38332d7c91cSJim Harris bdev_ut_get_io_channel(void *ctx) 38432d7c91cSJim Harris { 38532d7c91cSJim Harris return spdk_get_io_channel(&g_bdev_ut_io_device); 38632d7c91cSJim Harris } 38732d7c91cSJim Harris 388e2918289SKonrad Sztyber static bool g_io_types_supported[SPDK_BDEV_NUM_IO_TYPES] = { 389e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_READ] = true, 390e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_WRITE] = true, 391bee042e4SMaciej Szwed [SPDK_BDEV_IO_TYPE_COMPARE] = true, 392e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_UNMAP] = true, 393e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_FLUSH] = true, 394e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_RESET] = true, 395e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_NVME_ADMIN] = true, 396e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_NVME_IO] = true, 397e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_NVME_IO_MD] = true, 398e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_WRITE_ZEROES] = true, 399e2918289SKonrad Sztyber [SPDK_BDEV_IO_TYPE_ZCOPY] = true, 4007cd20dd3SShuhei Matsumoto [SPDK_BDEV_IO_TYPE_ABORT] = true, 4016defafc9SDamiano [SPDK_BDEV_IO_TYPE_SEEK_HOLE] = true, 4026defafc9SDamiano [SPDK_BDEV_IO_TYPE_SEEK_DATA] = true, 4036c8702acSEvgeniy Kochetov [SPDK_BDEV_IO_TYPE_COPY] = true, 404e2918289SKonrad Sztyber }; 405e2918289SKonrad Sztyber 406e2918289SKonrad Sztyber static void 407e2918289SKonrad Sztyber ut_enable_io_type(enum spdk_bdev_io_type io_type, bool enable) 408e2918289SKonrad Sztyber { 409e2918289SKonrad Sztyber g_io_types_supported[io_type] = enable; 410e2918289SKonrad Sztyber } 411e2918289SKonrad Sztyber 412e2918289SKonrad Sztyber static bool 413e2918289SKonrad Sztyber stub_io_type_supported(void *_bdev, enum spdk_bdev_io_type io_type) 414e2918289SKonrad Sztyber { 415e2918289SKonrad Sztyber return g_io_types_supported[io_type]; 416e2918289SKonrad Sztyber } 4174bd97621SJim Harris 41857d174ffSJim Harris static struct spdk_bdev_fn_table fn_table = { 41957d174ffSJim Harris .destruct = stub_destruct, 42032d7c91cSJim Harris .submit_request = stub_submit_request, 42132d7c91cSJim Harris .get_io_channel = bdev_ut_get_io_channel, 4224bd97621SJim Harris .io_type_supported = stub_io_type_supported, 42357d174ffSJim Harris }; 42457d174ffSJim Harris 42532d7c91cSJim Harris static int 42632d7c91cSJim Harris bdev_ut_create_ch(void *io_device, void *ctx_buf) 42732d7c91cSJim Harris { 42832d7c91cSJim Harris struct bdev_ut_channel *ch = ctx_buf; 42932d7c91cSJim Harris 43032d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel == NULL); 43132d7c91cSJim Harris g_bdev_ut_channel = ch; 43232d7c91cSJim Harris 43332d7c91cSJim Harris TAILQ_INIT(&ch->outstanding_io); 43432d7c91cSJim Harris ch->outstanding_io_count = 0; 4353c7894ffSShuhei Matsumoto TAILQ_INIT(&ch->expected_io); 43632d7c91cSJim Harris return 0; 43732d7c91cSJim Harris } 43832d7c91cSJim Harris 43932d7c91cSJim Harris static void 44032d7c91cSJim Harris bdev_ut_destroy_ch(void *io_device, void *ctx_buf) 44132d7c91cSJim Harris { 44232d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel != NULL); 44332d7c91cSJim Harris g_bdev_ut_channel = NULL; 44432d7c91cSJim Harris } 44532d7c91cSJim Harris 446d83a3489STomasz Zawadzki struct spdk_bdev_module bdev_ut_if; 447d83a3489STomasz Zawadzki 44832d7c91cSJim Harris static int 44932d7c91cSJim Harris bdev_ut_module_init(void) 45032d7c91cSJim Harris { 45132d7c91cSJim Harris spdk_io_device_register(&g_bdev_ut_io_device, bdev_ut_create_ch, bdev_ut_destroy_ch, 452c9402000SBen Walker sizeof(struct bdev_ut_channel), NULL); 453d83a3489STomasz Zawadzki spdk_bdev_module_init_done(&bdev_ut_if); 45432d7c91cSJim Harris return 0; 45532d7c91cSJim Harris } 45632d7c91cSJim Harris 45732d7c91cSJim Harris static void 45832d7c91cSJim Harris bdev_ut_module_fini(void) 45932d7c91cSJim Harris { 4608ef7818aSJim Harris spdk_io_device_unregister(&g_bdev_ut_io_device, NULL); 46132d7c91cSJim Harris } 46232d7c91cSJim Harris 46319100ed5SDaniel Verkamp struct spdk_bdev_module bdev_ut_if = { 4644d367354SPawel Wodkowski .name = "bdev_ut", 46532d7c91cSJim Harris .module_init = bdev_ut_module_init, 46632d7c91cSJim Harris .module_fini = bdev_ut_module_fini, 467d83a3489STomasz Zawadzki .async_init = true, 4684d367354SPawel Wodkowski }; 4694d367354SPawel Wodkowski 470ae215731SMike Gerdts static void vbdev_ut_examine_config(struct spdk_bdev *bdev); 471ae215731SMike Gerdts static void vbdev_ut_examine_disk(struct spdk_bdev *bdev); 4724d367354SPawel Wodkowski 47332d7c91cSJim Harris static int 47432d7c91cSJim Harris vbdev_ut_module_init(void) 47532d7c91cSJim Harris { 47632d7c91cSJim Harris return 0; 47732d7c91cSJim Harris } 47832d7c91cSJim Harris 47932d7c91cSJim Harris static void 48032d7c91cSJim Harris vbdev_ut_module_fini(void) 48132d7c91cSJim Harris { 48232d7c91cSJim Harris } 48332d7c91cSJim Harris 484dc996557SBen Walker static int 485dc996557SBen Walker vbdev_ut_get_ctx_size(void) 486dc996557SBen Walker { 487dc996557SBen Walker return sizeof(struct bdev_ut_io); 488dc996557SBen Walker } 489dc996557SBen Walker 49019100ed5SDaniel Verkamp struct spdk_bdev_module vbdev_ut_if = { 4914d367354SPawel Wodkowski .name = "vbdev_ut", 49232d7c91cSJim Harris .module_init = vbdev_ut_module_init, 49332d7c91cSJim Harris .module_fini = vbdev_ut_module_fini, 494ae215731SMike Gerdts .examine_config = vbdev_ut_examine_config, 495ae215731SMike Gerdts .examine_disk = vbdev_ut_examine_disk, 496dc996557SBen Walker .get_ctx_size = vbdev_ut_get_ctx_size, 4974d367354SPawel Wodkowski }; 4984d367354SPawel Wodkowski 499df6b55fdSgila SPDK_BDEV_MODULE_REGISTER(bdev_ut, &bdev_ut_if) 500df6b55fdSgila SPDK_BDEV_MODULE_REGISTER(vbdev_ut, &vbdev_ut_if) 5014d367354SPawel Wodkowski 502ae215731SMike Gerdts struct ut_examine_ctx { 503ae215731SMike Gerdts void (*examine_config)(struct spdk_bdev *bdev); 504ae215731SMike Gerdts void (*examine_disk)(struct spdk_bdev *bdev); 505ae215731SMike Gerdts uint32_t examine_config_count; 506ae215731SMike Gerdts uint32_t examine_disk_count; 507ae215731SMike Gerdts }; 508ae215731SMike Gerdts 509e075a3dcSJim Harris static void 510ae215731SMike Gerdts vbdev_ut_examine_config(struct spdk_bdev *bdev) 511e075a3dcSJim Harris { 512ae215731SMike Gerdts struct ut_examine_ctx *ctx = bdev->ctxt; 513ae215731SMike Gerdts 514ae215731SMike Gerdts if (ctx != NULL) { 515ae215731SMike Gerdts ctx->examine_config_count++; 516ae215731SMike Gerdts if (ctx->examine_config != NULL) { 517ae215731SMike Gerdts ctx->examine_config(bdev); 518ae215731SMike Gerdts } 519ae215731SMike Gerdts } 520ae215731SMike Gerdts 521ae215731SMike Gerdts spdk_bdev_module_examine_done(&vbdev_ut_if); 522ae215731SMike Gerdts } 523ae215731SMike Gerdts 524ae215731SMike Gerdts static void 525ae215731SMike Gerdts vbdev_ut_examine_disk(struct spdk_bdev *bdev) 526ae215731SMike Gerdts { 527ae215731SMike Gerdts struct ut_examine_ctx *ctx = bdev->ctxt; 528ae215731SMike Gerdts 529ae215731SMike Gerdts if (ctx != NULL) { 530ae215731SMike Gerdts ctx->examine_disk_count++; 531ae215731SMike Gerdts if (ctx->examine_disk != NULL) { 532ae215731SMike Gerdts ctx->examine_disk(bdev); 533ae215731SMike Gerdts } 534ae215731SMike Gerdts } 535ae215731SMike Gerdts 5364d367354SPawel Wodkowski spdk_bdev_module_examine_done(&vbdev_ut_if); 537e075a3dcSJim Harris } 538e075a3dcSJim Harris 539cec70a60SShuhei Matsumoto static void 540cec70a60SShuhei Matsumoto bdev_init_cb(void *arg, int rc) 541cec70a60SShuhei Matsumoto { 542cec70a60SShuhei Matsumoto CU_ASSERT(rc == 0); 543cec70a60SShuhei Matsumoto } 544cec70a60SShuhei Matsumoto 545cec70a60SShuhei Matsumoto static void 546cec70a60SShuhei Matsumoto bdev_fini_cb(void *arg) 547cec70a60SShuhei Matsumoto { 548cec70a60SShuhei Matsumoto } 549cec70a60SShuhei Matsumoto 550cec70a60SShuhei Matsumoto static void 551cec70a60SShuhei Matsumoto ut_init_bdev(struct spdk_bdev_opts *opts) 552cec70a60SShuhei Matsumoto { 553cec70a60SShuhei Matsumoto int rc; 554cec70a60SShuhei Matsumoto 555cec70a60SShuhei Matsumoto if (opts != NULL) { 556cec70a60SShuhei Matsumoto rc = spdk_bdev_set_opts(opts); 557cec70a60SShuhei Matsumoto CU_ASSERT(rc == 0); 558cec70a60SShuhei Matsumoto } 559cec70a60SShuhei Matsumoto rc = spdk_iobuf_initialize(); 560cec70a60SShuhei Matsumoto CU_ASSERT(rc == 0); 561cec70a60SShuhei Matsumoto spdk_bdev_initialize(bdev_init_cb, NULL); 562cec70a60SShuhei Matsumoto poll_threads(); 563cec70a60SShuhei Matsumoto } 564cec70a60SShuhei Matsumoto 565cec70a60SShuhei Matsumoto static void 566cec70a60SShuhei Matsumoto ut_fini_bdev(void) 567cec70a60SShuhei Matsumoto { 568cec70a60SShuhei Matsumoto spdk_bdev_finish(bdev_fini_cb, NULL); 569cec70a60SShuhei Matsumoto spdk_iobuf_finish(bdev_fini_cb, NULL); 570cec70a60SShuhei Matsumoto poll_threads(); 571cec70a60SShuhei Matsumoto } 572cec70a60SShuhei Matsumoto 57357d174ffSJim Harris static struct spdk_bdev * 574ae215731SMike Gerdts allocate_bdev_ctx(char *name, void *ctx) 57557d174ffSJim Harris { 57657d174ffSJim Harris struct spdk_bdev *bdev; 577b9afa3c7SSebastian Basierski int rc; 57857d174ffSJim Harris 57957d174ffSJim Harris bdev = calloc(1, sizeof(*bdev)); 58057d174ffSJim Harris SPDK_CU_ASSERT_FATAL(bdev != NULL); 58157d174ffSJim Harris 582ae215731SMike Gerdts bdev->ctxt = ctx; 58357d174ffSJim Harris bdev->name = name; 58457d174ffSJim Harris bdev->fn_table = &fn_table; 5854d367354SPawel Wodkowski bdev->module = &bdev_ut_if; 5865616c1edSShuhei Matsumoto bdev->blockcnt = 1024; 5874bd97621SJim Harris bdev->blocklen = 512; 58857d174ffSJim Harris 589a1c7ae2dSKrzysztof Karas spdk_uuid_generate(&bdev->uuid); 590a1c7ae2dSKrzysztof Karas 591b9afa3c7SSebastian Basierski rc = spdk_bdev_register(bdev); 592d0038b70SNathan Claudel poll_threads(); 593b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 59457d174ffSJim Harris 59557d174ffSJim Harris return bdev; 59657d174ffSJim Harris } 59757d174ffSJim Harris 59857d174ffSJim Harris static struct spdk_bdev * 599ae215731SMike Gerdts allocate_bdev(char *name) 600ae215731SMike Gerdts { 601ae215731SMike Gerdts return allocate_bdev_ctx(name, NULL); 602ae215731SMike Gerdts } 603ae215731SMike Gerdts 604ae215731SMike Gerdts static struct spdk_bdev * 605bfd1e46eSJim Harris allocate_vbdev(char *name) 60657d174ffSJim Harris { 60757d174ffSJim Harris struct spdk_bdev *bdev; 608b9afa3c7SSebastian Basierski int rc; 60957d174ffSJim Harris 61057d174ffSJim Harris bdev = calloc(1, sizeof(*bdev)); 61157d174ffSJim Harris SPDK_CU_ASSERT_FATAL(bdev != NULL); 61257d174ffSJim Harris 61357d174ffSJim Harris bdev->name = name; 61457d174ffSJim Harris bdev->fn_table = &fn_table; 6154d367354SPawel Wodkowski bdev->module = &vbdev_ut_if; 616cec70a60SShuhei Matsumoto bdev->blockcnt = 1024; 617cec70a60SShuhei Matsumoto bdev->blocklen = 512; 61857d174ffSJim Harris 619bfd1e46eSJim Harris rc = spdk_bdev_register(bdev); 620d0038b70SNathan Claudel poll_threads(); 621b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 62257d174ffSJim Harris 62357d174ffSJim Harris return bdev; 62457d174ffSJim Harris } 62557d174ffSJim Harris 62657d174ffSJim Harris static void 62757d174ffSJim Harris free_bdev(struct spdk_bdev *bdev) 62857d174ffSJim Harris { 6292baeea7dSMaciej Szwed spdk_bdev_unregister(bdev, NULL, NULL); 630270a25dfSBen Walker poll_threads(); 6314473942fSPawel Wodkowski memset(bdev, 0xFF, sizeof(*bdev)); 63257d174ffSJim Harris free(bdev); 63357d174ffSJim Harris } 63457d174ffSJim Harris 63557d174ffSJim Harris static void 63657d174ffSJim Harris free_vbdev(struct spdk_bdev *bdev) 63757d174ffSJim Harris { 638b6aaba08STomasz Zawadzki spdk_bdev_unregister(bdev, NULL, NULL); 639270a25dfSBen Walker poll_threads(); 6404473942fSPawel Wodkowski memset(bdev, 0xFF, sizeof(*bdev)); 64157d174ffSJim Harris free(bdev); 64257d174ffSJim Harris } 64357d174ffSJim Harris 64457d174ffSJim Harris static void 64564ccd4b9SYanbo Zhou get_device_stat_cb(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, void *cb_arg, int rc) 64664ccd4b9SYanbo Zhou { 64764ccd4b9SYanbo Zhou const char *bdev_name; 64864ccd4b9SYanbo Zhou 64964ccd4b9SYanbo Zhou CU_ASSERT(bdev != NULL); 65064ccd4b9SYanbo Zhou CU_ASSERT(rc == 0); 65164ccd4b9SYanbo Zhou bdev_name = spdk_bdev_get_name(bdev); 65264ccd4b9SYanbo Zhou CU_ASSERT_STRING_EQUAL(bdev_name, "bdev0"); 65364ccd4b9SYanbo Zhou 65464ccd4b9SYanbo Zhou free(stat); 655270a25dfSBen Walker 656270a25dfSBen Walker *(bool *)cb_arg = true; 65764ccd4b9SYanbo Zhou } 65864ccd4b9SYanbo Zhou 65964ccd4b9SYanbo Zhou static void 66023975858SEvgeniy Kochetov bdev_unregister_cb(void *cb_arg, int rc) 66123975858SEvgeniy Kochetov { 66223975858SEvgeniy Kochetov g_unregister_arg = cb_arg; 66323975858SEvgeniy Kochetov g_unregister_rc = rc; 66423975858SEvgeniy Kochetov } 66523975858SEvgeniy Kochetov 66623975858SEvgeniy Kochetov static void 66775dfecbbSShuhei Matsumoto bdev_ut_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 66875dfecbbSShuhei Matsumoto { 66975dfecbbSShuhei Matsumoto } 67075dfecbbSShuhei Matsumoto 67175dfecbbSShuhei Matsumoto static void 672437e54f7SEvgeniy Kochetov bdev_open_cb1(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 673437e54f7SEvgeniy Kochetov { 674437e54f7SEvgeniy Kochetov struct spdk_bdev_desc *desc = *(struct spdk_bdev_desc **)event_ctx; 675437e54f7SEvgeniy Kochetov 676437e54f7SEvgeniy Kochetov g_event_type1 = type; 6779522ed36SEvgeniy Kochetov if (SPDK_BDEV_EVENT_REMOVE == type) { 678437e54f7SEvgeniy Kochetov spdk_bdev_close(desc); 679437e54f7SEvgeniy Kochetov } 6809522ed36SEvgeniy Kochetov } 681437e54f7SEvgeniy Kochetov 682437e54f7SEvgeniy Kochetov static void 683437e54f7SEvgeniy Kochetov bdev_open_cb2(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 684437e54f7SEvgeniy Kochetov { 685437e54f7SEvgeniy Kochetov struct spdk_bdev_desc *desc = *(struct spdk_bdev_desc **)event_ctx; 686437e54f7SEvgeniy Kochetov 687437e54f7SEvgeniy Kochetov g_event_type2 = type; 6889522ed36SEvgeniy Kochetov if (SPDK_BDEV_EVENT_REMOVE == type) { 689437e54f7SEvgeniy Kochetov spdk_bdev_close(desc); 690437e54f7SEvgeniy Kochetov } 6919522ed36SEvgeniy Kochetov } 692437e54f7SEvgeniy Kochetov 693437e54f7SEvgeniy Kochetov static void 6947bcd316dSGangCao bdev_open_cb3(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 6957bcd316dSGangCao { 6967bcd316dSGangCao g_event_type3 = type; 6977bcd316dSGangCao } 6987bcd316dSGangCao 6997bcd316dSGangCao static void 7007bcd316dSGangCao bdev_open_cb4(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 7017bcd316dSGangCao { 7027bcd316dSGangCao g_event_type4 = type; 7037bcd316dSGangCao } 7047bcd316dSGangCao 7057bcd316dSGangCao static void 7066defafc9SDamiano bdev_seek_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 7076defafc9SDamiano { 7086defafc9SDamiano g_seek_offset = spdk_bdev_io_get_seek_offset(bdev_io); 7096defafc9SDamiano spdk_bdev_free_io(bdev_io); 7106defafc9SDamiano } 7116defafc9SDamiano 7126defafc9SDamiano static void 71364ccd4b9SYanbo Zhou get_device_stat_test(void) 71464ccd4b9SYanbo Zhou { 71564ccd4b9SYanbo Zhou struct spdk_bdev *bdev; 71664ccd4b9SYanbo Zhou struct spdk_bdev_io_stat *stat; 717270a25dfSBen Walker bool done; 71864ccd4b9SYanbo Zhou 71964ccd4b9SYanbo Zhou bdev = allocate_bdev("bdev0"); 72064ccd4b9SYanbo Zhou stat = calloc(1, sizeof(struct spdk_bdev_io_stat)); 72164ccd4b9SYanbo Zhou if (stat == NULL) { 72264ccd4b9SYanbo Zhou free_bdev(bdev); 72364ccd4b9SYanbo Zhou return; 72464ccd4b9SYanbo Zhou } 725270a25dfSBen Walker 726270a25dfSBen Walker done = false; 72763e0c25dSVasilii Ivanov spdk_bdev_get_device_stat(bdev, stat, SPDK_BDEV_RESET_STAT_NONE, get_device_stat_cb, &done); 728270a25dfSBen Walker while (!done) { poll_threads(); } 729270a25dfSBen Walker 730c83ffe32STomasz Zawadzki free_bdev(bdev); 73164ccd4b9SYanbo Zhou } 73264ccd4b9SYanbo Zhou 73364ccd4b9SYanbo Zhou static void 73457d174ffSJim Harris open_write_test(void) 73557d174ffSJim Harris { 7364473942fSPawel Wodkowski struct spdk_bdev *bdev[9]; 7374473942fSPawel Wodkowski struct spdk_bdev_desc *desc[9] = {}; 73857d174ffSJim Harris int rc; 73957d174ffSJim Harris 740cec70a60SShuhei Matsumoto ut_init_bdev(NULL); 741cec70a60SShuhei Matsumoto 74257d174ffSJim Harris /* 74357d174ffSJim Harris * Create a tree of bdevs to test various open w/ write cases. 74457d174ffSJim Harris * 7454473942fSPawel Wodkowski * bdev0 through bdev3 are physical block devices, such as NVMe 74657d174ffSJim Harris * namespaces or Ceph block devices. 74757d174ffSJim Harris * 7484473942fSPawel Wodkowski * bdev4 is a virtual bdev with multiple base bdevs. This models 74957d174ffSJim Harris * caching or RAID use cases. 75057d174ffSJim Harris * 7514473942fSPawel Wodkowski * bdev5 through bdev7 are all virtual bdevs with the same base 7524473942fSPawel Wodkowski * bdev (except bdev7). This models partitioning or logical volume 7534473942fSPawel Wodkowski * use cases. 75457d174ffSJim Harris * 7554473942fSPawel Wodkowski * bdev7 is a virtual bdev with multiple base bdevs. One of base bdevs 7564473942fSPawel Wodkowski * (bdev2) is shared with other virtual bdevs: bdev5 and bdev6. This 7574473942fSPawel Wodkowski * models caching, RAID, partitioning or logical volumes use cases. 7584473942fSPawel Wodkowski * 7594473942fSPawel Wodkowski * bdev8 is a virtual bdev with multiple base bdevs, but these 76057d174ffSJim Harris * base bdevs are themselves virtual bdevs. 76157d174ffSJim Harris * 7624473942fSPawel Wodkowski * bdev8 76357d174ffSJim Harris * | 76457d174ffSJim Harris * +----------+ 76557d174ffSJim Harris * | | 7664473942fSPawel Wodkowski * bdev4 bdev5 bdev6 bdev7 76757d174ffSJim Harris * | | | | 7684473942fSPawel Wodkowski * +---+---+ +---+ + +---+---+ 7694473942fSPawel Wodkowski * | | \ | / \ 7704473942fSPawel Wodkowski * bdev0 bdev1 bdev2 bdev3 77157d174ffSJim Harris */ 77257d174ffSJim Harris 77357d174ffSJim Harris bdev[0] = allocate_bdev("bdev0"); 7744d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, &bdev_ut_if); 7754fc7e666SJim Harris CU_ASSERT(rc == 0); 7764fc7e666SJim Harris 77757d174ffSJim Harris bdev[1] = allocate_bdev("bdev1"); 7784d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if); 7794fc7e666SJim Harris CU_ASSERT(rc == 0); 7804fc7e666SJim Harris 78157d174ffSJim Harris bdev[2] = allocate_bdev("bdev2"); 7824d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, &bdev_ut_if); 7834fc7e666SJim Harris CU_ASSERT(rc == 0); 78457d174ffSJim Harris 7854473942fSPawel Wodkowski bdev[3] = allocate_bdev("bdev3"); 7864d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if); 7874fc7e666SJim Harris CU_ASSERT(rc == 0); 78857d174ffSJim Harris 789bfd1e46eSJim Harris bdev[4] = allocate_vbdev("bdev4"); 7904d367354SPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, &bdev_ut_if); 7914fc7e666SJim Harris CU_ASSERT(rc == 0); 7924fc7e666SJim Harris 793bfd1e46eSJim Harris bdev[5] = allocate_vbdev("bdev5"); 7944473942fSPawel Wodkowski rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if); 7954473942fSPawel Wodkowski CU_ASSERT(rc == 0); 7964473942fSPawel Wodkowski 797bfd1e46eSJim Harris bdev[6] = allocate_vbdev("bdev6"); 79857d174ffSJim Harris 799bfd1e46eSJim Harris bdev[7] = allocate_vbdev("bdev7"); 8004473942fSPawel Wodkowski 801bfd1e46eSJim Harris bdev[8] = allocate_vbdev("bdev8"); 8024473942fSPawel Wodkowski 80357d174ffSJim Harris /* Open bdev0 read-only. This should succeed. */ 80475dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc[0]); 80557d174ffSJim Harris CU_ASSERT(rc == 0); 8061196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[0] != NULL); 80775dfecbbSShuhei Matsumoto CU_ASSERT(bdev[0] == spdk_bdev_desc_get_bdev(desc[0])); 80857d174ffSJim Harris spdk_bdev_close(desc[0]); 80957d174ffSJim Harris 8104fc7e666SJim Harris /* 8114fc7e666SJim Harris * Open bdev1 read/write. This should fail since bdev1 has been claimed 8124fc7e666SJim Harris * by a vbdev module. 8134fc7e666SJim Harris */ 81475dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev1", true, bdev_ut_event_cb, NULL, &desc[1]); 8154fc7e666SJim Harris CU_ASSERT(rc == -EPERM); 81657d174ffSJim Harris 81757d174ffSJim Harris /* 8184473942fSPawel Wodkowski * Open bdev4 read/write. This should fail since bdev3 has been claimed 8194fc7e666SJim Harris * by a vbdev module. 82057d174ffSJim Harris */ 82175dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev4", true, bdev_ut_event_cb, NULL, &desc[4]); 82257d174ffSJim Harris CU_ASSERT(rc == -EPERM); 82357d174ffSJim Harris 82457d174ffSJim Harris /* Open bdev4 read-only. This should succeed. */ 82575dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev4", false, bdev_ut_event_cb, NULL, &desc[4]); 82657d174ffSJim Harris CU_ASSERT(rc == 0); 8271196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[4] != NULL); 82875dfecbbSShuhei Matsumoto CU_ASSERT(bdev[4] == spdk_bdev_desc_get_bdev(desc[4])); 82957d174ffSJim Harris spdk_bdev_close(desc[4]); 83057d174ffSJim Harris 8314473942fSPawel Wodkowski /* 8324473942fSPawel Wodkowski * Open bdev8 read/write. This should succeed since it is a leaf 8334473942fSPawel Wodkowski * bdev. 8344473942fSPawel Wodkowski */ 83575dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev8", true, bdev_ut_event_cb, NULL, &desc[8]); 8364473942fSPawel Wodkowski CU_ASSERT(rc == 0); 8371196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[8] != NULL); 83875dfecbbSShuhei Matsumoto CU_ASSERT(bdev[8] == spdk_bdev_desc_get_bdev(desc[8])); 8394473942fSPawel Wodkowski spdk_bdev_close(desc[8]); 84057d174ffSJim Harris 8414473942fSPawel Wodkowski /* 8424473942fSPawel Wodkowski * Open bdev5 read/write. This should fail since bdev4 has been claimed 8434473942fSPawel Wodkowski * by a vbdev module. 8444473942fSPawel Wodkowski */ 84575dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev5", true, bdev_ut_event_cb, NULL, &desc[5]); 8464473942fSPawel Wodkowski CU_ASSERT(rc == -EPERM); 8474473942fSPawel Wodkowski 8484473942fSPawel Wodkowski /* Open bdev4 read-only. This should succeed. */ 84975dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev5", false, bdev_ut_event_cb, NULL, &desc[5]); 8504473942fSPawel Wodkowski CU_ASSERT(rc == 0); 8511196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc[5] != NULL); 85275dfecbbSShuhei Matsumoto CU_ASSERT(bdev[5] == spdk_bdev_desc_get_bdev(desc[5])); 8534473942fSPawel Wodkowski spdk_bdev_close(desc[5]); 8544473942fSPawel Wodkowski 8554473942fSPawel Wodkowski free_vbdev(bdev[8]); 8564473942fSPawel Wodkowski 85757d174ffSJim Harris free_vbdev(bdev[5]); 85857d174ffSJim Harris free_vbdev(bdev[6]); 8594473942fSPawel Wodkowski free_vbdev(bdev[7]); 8604473942fSPawel Wodkowski 8614473942fSPawel Wodkowski free_vbdev(bdev[4]); 86257d174ffSJim Harris 86357d174ffSJim Harris free_bdev(bdev[0]); 86457d174ffSJim Harris free_bdev(bdev[1]); 86557d174ffSJim Harris free_bdev(bdev[2]); 8664473942fSPawel Wodkowski free_bdev(bdev[3]); 867cec70a60SShuhei Matsumoto 868cec70a60SShuhei Matsumoto ut_fini_bdev(); 8694ee51dcbSJim Harris } 8704ee51dcbSJim Harris 871906ce694SDaniel Verkamp static void 8729f9c7161SMike Gerdts claim_test(void) 8739f9c7161SMike Gerdts { 8749f9c7161SMike Gerdts struct spdk_bdev *bdev; 8759f9c7161SMike Gerdts struct spdk_bdev_desc *desc, *open_desc; 8769f9c7161SMike Gerdts int rc; 8779f9c7161SMike Gerdts uint32_t count; 8789f9c7161SMike Gerdts 879cec70a60SShuhei Matsumoto ut_init_bdev(NULL); 880cec70a60SShuhei Matsumoto 8819f9c7161SMike Gerdts /* 8829f9c7161SMike Gerdts * A vbdev that uses a read-only bdev may need it to remain read-only. 8839f9c7161SMike Gerdts * To do so, it opens the bdev read-only, then claims it without 8849f9c7161SMike Gerdts * passing a spdk_bdev_desc. 8859f9c7161SMike Gerdts */ 8869f9c7161SMike Gerdts bdev = allocate_bdev("bdev0"); 8879f9c7161SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc); 8889f9c7161SMike Gerdts CU_ASSERT(rc == 0); 8899f9c7161SMike Gerdts CU_ASSERT(desc->write == false); 8909f9c7161SMike Gerdts 8919f9c7161SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &bdev_ut_if); 8929f9c7161SMike Gerdts CU_ASSERT(rc == 0); 8934bb902a6SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_EXCL_WRITE); 8949fd2f931SMike Gerdts CU_ASSERT(bdev->internal.claim.v1.module == &bdev_ut_if); 8959f9c7161SMike Gerdts 8969f9c7161SMike Gerdts /* There should be only one open descriptor and it should still be ro */ 8979f9c7161SMike Gerdts count = 0; 8989f9c7161SMike Gerdts TAILQ_FOREACH(open_desc, &bdev->internal.open_descs, link) { 8999f9c7161SMike Gerdts CU_ASSERT(open_desc == desc); 9009f9c7161SMike Gerdts CU_ASSERT(!open_desc->write); 9019f9c7161SMike Gerdts count++; 9029f9c7161SMike Gerdts } 9039f9c7161SMike Gerdts CU_ASSERT(count == 1); 9049f9c7161SMike Gerdts 9059f9c7161SMike Gerdts /* A read-only bdev is upgraded to read-write if desc is passed. */ 9069f9c7161SMike Gerdts spdk_bdev_module_release_bdev(bdev); 9079f9c7161SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, desc, &bdev_ut_if); 9089f9c7161SMike Gerdts CU_ASSERT(rc == 0); 9094bb902a6SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_EXCL_WRITE); 9109fd2f931SMike Gerdts CU_ASSERT(bdev->internal.claim.v1.module == &bdev_ut_if); 9119f9c7161SMike Gerdts 9129f9c7161SMike Gerdts /* There should be only one open descriptor and it should be rw */ 9139f9c7161SMike Gerdts count = 0; 9149f9c7161SMike Gerdts TAILQ_FOREACH(open_desc, &bdev->internal.open_descs, link) { 9159f9c7161SMike Gerdts CU_ASSERT(open_desc == desc); 9169f9c7161SMike Gerdts CU_ASSERT(open_desc->write); 9179f9c7161SMike Gerdts count++; 9189f9c7161SMike Gerdts } 9199f9c7161SMike Gerdts CU_ASSERT(count == 1); 9209f9c7161SMike Gerdts 9219f9c7161SMike Gerdts spdk_bdev_close(desc); 9229f9c7161SMike Gerdts free_bdev(bdev); 923cec70a60SShuhei Matsumoto ut_fini_bdev(); 9249f9c7161SMike Gerdts } 9259f9c7161SMike Gerdts 9269f9c7161SMike Gerdts static void 927e83f9767SDaniel Verkamp bytes_to_blocks_test(void) 928e83f9767SDaniel Verkamp { 929fb1630bfSShuhei Matsumoto struct spdk_bdev_desc desc = {0}; 930fb1630bfSShuhei Matsumoto struct spdk_bdev bdev = {0}; 931e83f9767SDaniel Verkamp uint64_t offset_blocks, num_blocks; 932e83f9767SDaniel Verkamp 933557f022fSShuhei Matsumoto 934557f022fSShuhei Matsumoto desc.bdev = &bdev; 935e83f9767SDaniel Verkamp memset(&bdev, 0, sizeof(bdev)); 936e83f9767SDaniel Verkamp 937e83f9767SDaniel Verkamp bdev.blocklen = 512; 938e83f9767SDaniel Verkamp 939e83f9767SDaniel Verkamp /* All parameters valid */ 940e83f9767SDaniel Verkamp offset_blocks = 0; 941e83f9767SDaniel Verkamp num_blocks = 0; 942557f022fSShuhei Matsumoto CU_ASSERT(bdev_bytes_to_blocks(&desc, 512, &offset_blocks, 1024, &num_blocks) == 0); 943e83f9767SDaniel Verkamp CU_ASSERT(offset_blocks == 1); 944e83f9767SDaniel Verkamp CU_ASSERT(num_blocks == 2); 945e83f9767SDaniel Verkamp 946e83f9767SDaniel Verkamp /* Offset not a block multiple */ 947557f022fSShuhei Matsumoto CU_ASSERT(bdev_bytes_to_blocks(&desc, 3, &offset_blocks, 512, &num_blocks) != 0); 948e83f9767SDaniel Verkamp 949e83f9767SDaniel Verkamp /* Length not a block multiple */ 950557f022fSShuhei Matsumoto CU_ASSERT(bdev_bytes_to_blocks(&desc, 512, &offset_blocks, 3, &num_blocks) != 0); 95102be32d4Slorneli 95202be32d4Slorneli /* In case blocklen not the power of two */ 95302be32d4Slorneli bdev.blocklen = 100; 954557f022fSShuhei Matsumoto CU_ASSERT(bdev_bytes_to_blocks(&desc, 100, &offset_blocks, 200, &num_blocks) == 0); 95502be32d4Slorneli CU_ASSERT(offset_blocks == 1); 95602be32d4Slorneli CU_ASSERT(num_blocks == 2); 95702be32d4Slorneli 95802be32d4Slorneli /* Offset not a block multiple */ 959557f022fSShuhei Matsumoto CU_ASSERT(bdev_bytes_to_blocks(&desc, 3, &offset_blocks, 100, &num_blocks) != 0); 96002be32d4Slorneli 96102be32d4Slorneli /* Length not a block multiple */ 962557f022fSShuhei Matsumoto CU_ASSERT(bdev_bytes_to_blocks(&desc, 100, &offset_blocks, 3, &num_blocks) != 0); 963e83f9767SDaniel Verkamp } 964e83f9767SDaniel Verkamp 965e83f9767SDaniel Verkamp static void 966d4822a7dSSlawomir Mrozowicz num_blocks_test(void) 967d4822a7dSSlawomir Mrozowicz { 968cec70a60SShuhei Matsumoto struct spdk_bdev *bdev; 9691196deb5SSeth Howell struct spdk_bdev_desc *desc = NULL; 9701196deb5SSeth Howell int rc; 971d4822a7dSSlawomir Mrozowicz 972cec70a60SShuhei Matsumoto ut_init_bdev(NULL); 973cec70a60SShuhei Matsumoto bdev = allocate_bdev("num_blocks"); 974cec70a60SShuhei Matsumoto 975cec70a60SShuhei Matsumoto spdk_bdev_notify_blockcnt_change(bdev, 50); 976d4822a7dSSlawomir Mrozowicz 977d4822a7dSSlawomir Mrozowicz /* Growing block number */ 978cec70a60SShuhei Matsumoto CU_ASSERT(spdk_bdev_notify_blockcnt_change(bdev, 70) == 0); 979d4822a7dSSlawomir Mrozowicz /* Shrinking block number */ 980cec70a60SShuhei Matsumoto CU_ASSERT(spdk_bdev_notify_blockcnt_change(bdev, 30) == 0); 981d4822a7dSSlawomir Mrozowicz 982739d5413STomasz Zawadzki rc = spdk_bdev_open_ext("num_blocks", false, bdev_open_cb1, &desc, &desc); 9831196deb5SSeth Howell CU_ASSERT(rc == 0); 9841196deb5SSeth Howell SPDK_CU_ASSERT_FATAL(desc != NULL); 985cec70a60SShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 986d4822a7dSSlawomir Mrozowicz 987d4822a7dSSlawomir Mrozowicz /* Growing block number */ 988cec70a60SShuhei Matsumoto CU_ASSERT(spdk_bdev_notify_blockcnt_change(bdev, 80) == 0); 989d4822a7dSSlawomir Mrozowicz /* Shrinking block number */ 990cec70a60SShuhei Matsumoto CU_ASSERT(spdk_bdev_notify_blockcnt_change(bdev, 20) != 0); 991d4822a7dSSlawomir Mrozowicz 9929522ed36SEvgeniy Kochetov g_event_type1 = 0xFF; 9939522ed36SEvgeniy Kochetov /* Growing block number */ 994cec70a60SShuhei Matsumoto CU_ASSERT(spdk_bdev_notify_blockcnt_change(bdev, 90) == 0); 9959522ed36SEvgeniy Kochetov 9969522ed36SEvgeniy Kochetov poll_threads(); 9979522ed36SEvgeniy Kochetov CU_ASSERT_EQUAL(g_event_type1, SPDK_BDEV_EVENT_RESIZE); 9989522ed36SEvgeniy Kochetov 9999522ed36SEvgeniy Kochetov g_event_type1 = 0xFF; 10009522ed36SEvgeniy Kochetov /* Growing block number and closing */ 1001cec70a60SShuhei Matsumoto CU_ASSERT(spdk_bdev_notify_blockcnt_change(bdev, 100) == 0); 10029522ed36SEvgeniy Kochetov 1003d4822a7dSSlawomir Mrozowicz spdk_bdev_close(desc); 1004cec70a60SShuhei Matsumoto free_bdev(bdev); 1005cec70a60SShuhei Matsumoto ut_fini_bdev(); 1006270a25dfSBen Walker 1007270a25dfSBen Walker poll_threads(); 10089522ed36SEvgeniy Kochetov 10099522ed36SEvgeniy Kochetov /* Callback is not called for closed device */ 10109522ed36SEvgeniy Kochetov CU_ASSERT_EQUAL(g_event_type1, 0xFF); 1011d4822a7dSSlawomir Mrozowicz } 1012d4822a7dSSlawomir Mrozowicz 1013d4822a7dSSlawomir Mrozowicz static void 1014906ce694SDaniel Verkamp io_valid_test(void) 1015906ce694SDaniel Verkamp { 1016906ce694SDaniel Verkamp struct spdk_bdev bdev; 1017906ce694SDaniel Verkamp 1018906ce694SDaniel Verkamp memset(&bdev, 0, sizeof(bdev)); 1019906ce694SDaniel Verkamp 1020906ce694SDaniel Verkamp bdev.blocklen = 512; 10210dc6aac1SMike Gerdts spdk_spin_init(&bdev.internal.spinlock); 10227d3b2c13SNick Connolly 1023d4822a7dSSlawomir Mrozowicz spdk_bdev_notify_blockcnt_change(&bdev, 100); 1024906ce694SDaniel Verkamp 1025906ce694SDaniel Verkamp /* All parameters valid */ 10260e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 1, 2) == true); 1027906ce694SDaniel Verkamp 1028906ce694SDaniel Verkamp /* Last valid block */ 10290e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 99, 1) == true); 1030906ce694SDaniel Verkamp 1031906ce694SDaniel Verkamp /* Offset past end of bdev */ 10320e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 100, 1) == false); 1033906ce694SDaniel Verkamp 1034906ce694SDaniel Verkamp /* Offset + length past end of bdev */ 10350e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 99, 2) == false); 1036906ce694SDaniel Verkamp 1037e83f9767SDaniel Verkamp /* Offset near end of uint64_t range (2^64 - 1) */ 10380e58d154SJim Harris CU_ASSERT(bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false); 10397d3b2c13SNick Connolly 10400dc6aac1SMike Gerdts spdk_spin_destroy(&bdev.internal.spinlock); 1041906ce694SDaniel Verkamp } 1042906ce694SDaniel Verkamp 1043b9afa3c7SSebastian Basierski static void 1044b9afa3c7SSebastian Basierski alias_add_del_test(void) 1045b9afa3c7SSebastian Basierski { 10466deac3e6Swuzhouhui struct spdk_bdev *bdev[3]; 1047b9afa3c7SSebastian Basierski int rc; 1048b9afa3c7SSebastian Basierski 1049cec70a60SShuhei Matsumoto ut_init_bdev(NULL); 1050cec70a60SShuhei Matsumoto 1051b9afa3c7SSebastian Basierski /* Creating and registering bdevs */ 1052b9afa3c7SSebastian Basierski bdev[0] = allocate_bdev("bdev0"); 1053b9afa3c7SSebastian Basierski SPDK_CU_ASSERT_FATAL(bdev[0] != 0); 1054b9afa3c7SSebastian Basierski 1055b9afa3c7SSebastian Basierski bdev[1] = allocate_bdev("bdev1"); 1056b9afa3c7SSebastian Basierski SPDK_CU_ASSERT_FATAL(bdev[1] != 0); 1057b9afa3c7SSebastian Basierski 10586deac3e6Swuzhouhui bdev[2] = allocate_bdev("bdev2"); 10596deac3e6Swuzhouhui SPDK_CU_ASSERT_FATAL(bdev[2] != 0); 10606deac3e6Swuzhouhui 1061270a25dfSBen Walker poll_threads(); 1062270a25dfSBen Walker 1063b9afa3c7SSebastian Basierski /* 1064b9afa3c7SSebastian Basierski * Trying adding an alias identical to name. 1065b9afa3c7SSebastian Basierski * Alias is identical to name, so it can not be added to aliases list 1066b9afa3c7SSebastian Basierski */ 1067b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name); 1068b9afa3c7SSebastian Basierski CU_ASSERT(rc == -EEXIST); 1069b9afa3c7SSebastian Basierski 1070b9afa3c7SSebastian Basierski /* 1071b9afa3c7SSebastian Basierski * Trying to add empty alias, 1072b9afa3c7SSebastian Basierski * this one should fail 1073b9afa3c7SSebastian Basierski */ 1074b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[0], NULL); 1075b9afa3c7SSebastian Basierski CU_ASSERT(rc == -EINVAL); 1076b9afa3c7SSebastian Basierski 1077b9afa3c7SSebastian Basierski /* Trying adding same alias to two different registered bdevs */ 1078b9afa3c7SSebastian Basierski 1079b9afa3c7SSebastian Basierski /* Alias is used first time, so this one should pass */ 1080b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[0], "proper alias 0"); 1081b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 1082b9afa3c7SSebastian Basierski 1083b9afa3c7SSebastian Basierski /* Alias was added to another bdev, so this one should fail */ 1084b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[1], "proper alias 0"); 1085b9afa3c7SSebastian Basierski CU_ASSERT(rc == -EEXIST); 1086b9afa3c7SSebastian Basierski 1087b9afa3c7SSebastian Basierski /* Alias is used first time, so this one should pass */ 1088b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_add(bdev[1], "proper alias 1"); 1089b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 1090b9afa3c7SSebastian Basierski 1091b9afa3c7SSebastian Basierski /* Trying removing an alias from registered bdevs */ 1092b9afa3c7SSebastian Basierski 1093b9afa3c7SSebastian Basierski /* Alias is not on a bdev aliases list, so this one should fail */ 1094b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[0], "not existing"); 1095b9afa3c7SSebastian Basierski CU_ASSERT(rc == -ENOENT); 1096b9afa3c7SSebastian Basierski 1097b9afa3c7SSebastian Basierski /* Alias is present on a bdev aliases list, so this one should pass */ 1098b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[0], "proper alias 0"); 1099b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 1100b9afa3c7SSebastian Basierski 1101b9afa3c7SSebastian Basierski /* Alias is present on a bdev aliases list, so this one should pass */ 1102b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[1], "proper alias 1"); 1103b9afa3c7SSebastian Basierski CU_ASSERT(rc == 0); 1104b9afa3c7SSebastian Basierski 1105b9afa3c7SSebastian Basierski /* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */ 1106b9afa3c7SSebastian Basierski rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name); 1107b9afa3c7SSebastian Basierski CU_ASSERT(rc != 0); 1108b9afa3c7SSebastian Basierski 11096deac3e6Swuzhouhui /* Trying to del all alias from empty alias list */ 11106deac3e6Swuzhouhui spdk_bdev_alias_del_all(bdev[2]); 111111ccf3beSSeth Howell SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&bdev[2]->aliases)); 11126deac3e6Swuzhouhui 11136deac3e6Swuzhouhui /* Trying to del all alias from non-empty alias list */ 11146deac3e6Swuzhouhui rc = spdk_bdev_alias_add(bdev[2], "alias0"); 11156deac3e6Swuzhouhui CU_ASSERT(rc == 0); 11166deac3e6Swuzhouhui rc = spdk_bdev_alias_add(bdev[2], "alias1"); 11176deac3e6Swuzhouhui CU_ASSERT(rc == 0); 11186deac3e6Swuzhouhui spdk_bdev_alias_del_all(bdev[2]); 11196deac3e6Swuzhouhui CU_ASSERT(TAILQ_EMPTY(&bdev[2]->aliases)); 11206deac3e6Swuzhouhui 1121b9afa3c7SSebastian Basierski /* Unregister and free bdevs */ 1122b9afa3c7SSebastian Basierski spdk_bdev_unregister(bdev[0], NULL, NULL); 1123b9afa3c7SSebastian Basierski spdk_bdev_unregister(bdev[1], NULL, NULL); 11246deac3e6Swuzhouhui spdk_bdev_unregister(bdev[2], NULL, NULL); 1125b9afa3c7SSebastian Basierski 1126270a25dfSBen Walker poll_threads(); 1127270a25dfSBen Walker 1128b9afa3c7SSebastian Basierski free(bdev[0]); 1129b9afa3c7SSebastian Basierski free(bdev[1]); 11306deac3e6Swuzhouhui free(bdev[2]); 1131cec70a60SShuhei Matsumoto 1132cec70a60SShuhei Matsumoto ut_fini_bdev(); 1133b9afa3c7SSebastian Basierski } 1134b9afa3c7SSebastian Basierski 113532d7c91cSJim Harris static void 113632d7c91cSJim Harris io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 113732d7c91cSJim Harris { 11384bd97621SJim Harris g_io_done = true; 11390df515a8SShuhei Matsumoto g_io_status = bdev_io->internal.status; 11406127461cSmatthewb if ((bdev_io->type == SPDK_BDEV_IO_TYPE_ZCOPY) && 11416127461cSmatthewb (bdev_io->u.bdev.zcopy.start)) { 11426127461cSmatthewb g_zcopy_bdev_io = bdev_io; 11436127461cSmatthewb } else { 114432d7c91cSJim Harris spdk_bdev_free_io(bdev_io); 11456127461cSmatthewb g_zcopy_bdev_io = NULL; 11466127461cSmatthewb } 114732d7c91cSJim Harris } 114832d7c91cSJim Harris 114932d7c91cSJim Harris struct bdev_ut_io_wait_entry { 115032d7c91cSJim Harris struct spdk_bdev_io_wait_entry entry; 115132d7c91cSJim Harris struct spdk_io_channel *io_ch; 115232d7c91cSJim Harris struct spdk_bdev_desc *desc; 115332d7c91cSJim Harris bool submitted; 115432d7c91cSJim Harris }; 115532d7c91cSJim Harris 115632d7c91cSJim Harris static void 115732d7c91cSJim Harris io_wait_cb(void *arg) 115832d7c91cSJim Harris { 115932d7c91cSJim Harris struct bdev_ut_io_wait_entry *entry = arg; 116032d7c91cSJim Harris int rc; 116132d7c91cSJim Harris 116232d7c91cSJim Harris rc = spdk_bdev_read_blocks(entry->desc, entry->io_ch, NULL, 0, 1, io_done, NULL); 116332d7c91cSJim Harris CU_ASSERT(rc == 0); 116432d7c91cSJim Harris entry->submitted = true; 116532d7c91cSJim Harris } 116632d7c91cSJim Harris 116732d7c91cSJim Harris static void 11689da1c738SChangpeng Liu bdev_io_types_test(void) 11699da1c738SChangpeng Liu { 11709da1c738SChangpeng Liu struct spdk_bdev *bdev; 11719da1c738SChangpeng Liu struct spdk_bdev_desc *desc = NULL; 11729da1c738SChangpeng Liu struct spdk_io_channel *io_ch; 1173f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 11749da1c738SChangpeng Liu int rc; 11759da1c738SChangpeng Liu 1176f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 1177f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 4; 1178f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 2; 1179107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 11809da1c738SChangpeng Liu 11819da1c738SChangpeng Liu bdev = allocate_bdev("bdev0"); 11829da1c738SChangpeng Liu 118375dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 11849da1c738SChangpeng Liu CU_ASSERT(rc == 0); 11859da1c738SChangpeng Liu poll_threads(); 11869da1c738SChangpeng Liu SPDK_CU_ASSERT_FATAL(desc != NULL); 118775dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 11889da1c738SChangpeng Liu io_ch = spdk_bdev_get_io_channel(desc); 11899da1c738SChangpeng Liu CU_ASSERT(io_ch != NULL); 11909da1c738SChangpeng Liu 11919da1c738SChangpeng Liu /* WRITE and WRITE ZEROES are not supported */ 1192e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, false); 1193e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE, false); 11949da1c738SChangpeng Liu rc = spdk_bdev_write_zeroes_blocks(desc, io_ch, 0, 128, io_done, NULL); 11959da1c738SChangpeng Liu CU_ASSERT(rc == -ENOTSUP); 1196e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, true); 1197e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE, true); 11989da1c738SChangpeng Liu 1199a9593c79SEvgeniy Kochetov /* NVME_IO, NVME_IO_MD and NVME_ADMIN are not supported */ 1200a9593c79SEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_NVME_IO, false); 1201a9593c79SEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_NVME_IO_MD, false); 1202a9593c79SEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_NVME_ADMIN, false); 1203a9593c79SEvgeniy Kochetov rc = spdk_bdev_nvme_io_passthru(desc, io_ch, NULL, NULL, 0, NULL, NULL); 1204a9593c79SEvgeniy Kochetov CU_ASSERT(rc == -ENOTSUP); 1205a9593c79SEvgeniy Kochetov rc = spdk_bdev_nvme_io_passthru_md(desc, io_ch, NULL, NULL, 0, NULL, 0, NULL, NULL); 1206a9593c79SEvgeniy Kochetov CU_ASSERT(rc == -ENOTSUP); 1207a9593c79SEvgeniy Kochetov rc = spdk_bdev_nvme_admin_passthru(desc, io_ch, NULL, NULL, 0, NULL, NULL); 1208a9593c79SEvgeniy Kochetov CU_ASSERT(rc == -ENOTSUP); 1209a9593c79SEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_NVME_IO, true); 1210a9593c79SEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_NVME_IO_MD, true); 1211a9593c79SEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_NVME_ADMIN, true); 1212a9593c79SEvgeniy Kochetov 12139da1c738SChangpeng Liu spdk_put_io_channel(io_ch); 12149da1c738SChangpeng Liu spdk_bdev_close(desc); 12159da1c738SChangpeng Liu free_bdev(bdev); 1216107741fcSKonrad Sztyber ut_fini_bdev(); 12179da1c738SChangpeng Liu } 12189da1c738SChangpeng Liu 12199da1c738SChangpeng Liu static void 122032d7c91cSJim Harris bdev_io_wait_test(void) 122132d7c91cSJim Harris { 122232d7c91cSJim Harris struct spdk_bdev *bdev; 1223fb0fe6b1SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 122432d7c91cSJim Harris struct spdk_io_channel *io_ch; 1225f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 122632d7c91cSJim Harris struct bdev_ut_io_wait_entry io_wait_entry; 122732d7c91cSJim Harris struct bdev_ut_io_wait_entry io_wait_entry2; 122832d7c91cSJim Harris int rc; 122932d7c91cSJim Harris 1230f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 1231f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 4; 1232f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 2; 1233107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 123432d7c91cSJim Harris 123532d7c91cSJim Harris bdev = allocate_bdev("bdev0"); 123632d7c91cSJim Harris 123775dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 123832d7c91cSJim Harris CU_ASSERT(rc == 0); 1239270a25dfSBen Walker poll_threads(); 1240fb0fe6b1SShuhei Matsumoto SPDK_CU_ASSERT_FATAL(desc != NULL); 124175dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 124232d7c91cSJim Harris io_ch = spdk_bdev_get_io_channel(desc); 124332d7c91cSJim Harris CU_ASSERT(io_ch != NULL); 124432d7c91cSJim Harris 124532d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 124632d7c91cSJim Harris CU_ASSERT(rc == 0); 124732d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 124832d7c91cSJim Harris CU_ASSERT(rc == 0); 124932d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 125032d7c91cSJim Harris CU_ASSERT(rc == 0); 125132d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 125232d7c91cSJim Harris CU_ASSERT(rc == 0); 125332d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 125432d7c91cSJim Harris 125532d7c91cSJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 125632d7c91cSJim Harris CU_ASSERT(rc == -ENOMEM); 125732d7c91cSJim Harris 125832d7c91cSJim Harris io_wait_entry.entry.bdev = bdev; 125932d7c91cSJim Harris io_wait_entry.entry.cb_fn = io_wait_cb; 126032d7c91cSJim Harris io_wait_entry.entry.cb_arg = &io_wait_entry; 126132d7c91cSJim Harris io_wait_entry.io_ch = io_ch; 126232d7c91cSJim Harris io_wait_entry.desc = desc; 126332d7c91cSJim Harris io_wait_entry.submitted = false; 126432d7c91cSJim Harris /* Cannot use the same io_wait_entry for two different calls. */ 126532d7c91cSJim Harris memcpy(&io_wait_entry2, &io_wait_entry, sizeof(io_wait_entry)); 126632d7c91cSJim Harris io_wait_entry2.entry.cb_arg = &io_wait_entry2; 126732d7c91cSJim Harris 126832d7c91cSJim Harris /* Queue two I/O waits. */ 126932d7c91cSJim Harris rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry.entry); 127032d7c91cSJim Harris CU_ASSERT(rc == 0); 127132d7c91cSJim Harris CU_ASSERT(io_wait_entry.submitted == false); 127232d7c91cSJim Harris rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry2.entry); 127332d7c91cSJim Harris CU_ASSERT(rc == 0); 127432d7c91cSJim Harris CU_ASSERT(io_wait_entry2.submitted == false); 127532d7c91cSJim Harris 127632d7c91cSJim Harris stub_complete_io(1); 127732d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 127832d7c91cSJim Harris CU_ASSERT(io_wait_entry.submitted == true); 127932d7c91cSJim Harris CU_ASSERT(io_wait_entry2.submitted == false); 128032d7c91cSJim Harris 128132d7c91cSJim Harris stub_complete_io(1); 128232d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 128332d7c91cSJim Harris CU_ASSERT(io_wait_entry2.submitted == true); 128432d7c91cSJim Harris 128532d7c91cSJim Harris stub_complete_io(4); 128632d7c91cSJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 128732d7c91cSJim Harris 128832d7c91cSJim Harris spdk_put_io_channel(io_ch); 128932d7c91cSJim Harris spdk_bdev_close(desc); 129032d7c91cSJim Harris free_bdev(bdev); 1291107741fcSKonrad Sztyber ut_fini_bdev(); 129232d7c91cSJim Harris } 129332d7c91cSJim Harris 12944bd97621SJim Harris static void 12953b616c0fSJin Yu bdev_io_spans_split_test(void) 12964bd97621SJim Harris { 12974bd97621SJim Harris struct spdk_bdev bdev; 12984bd97621SJim Harris struct spdk_bdev_io bdev_io; 1299b45556e2SChangpeng Liu struct iovec iov[SPDK_BDEV_IO_NUM_CHILD_IOV]; 13004bd97621SJim Harris 13014bd97621SJim Harris memset(&bdev, 0, sizeof(bdev)); 13023b616c0fSJin Yu bdev_io.u.bdev.iovs = iov; 13034bd97621SJim Harris 1304d4d5e20dSChangpeng Liu bdev_io.type = SPDK_BDEV_IO_TYPE_READ; 13054bd97621SJim Harris bdev.optimal_io_boundary = 0; 13063b616c0fSJin Yu bdev.max_segment_size = 0; 13073b616c0fSJin Yu bdev.max_num_segments = 0; 13084bd97621SJim Harris bdev_io.bdev = &bdev; 13094bd97621SJim Harris 13103b616c0fSJin Yu /* bdev has no optimal_io_boundary and max_size set - so this should return false. */ 1311aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 13124bd97621SJim Harris 13133b616c0fSJin Yu bdev.split_on_optimal_io_boundary = true; 13144bd97621SJim Harris bdev.optimal_io_boundary = 32; 13154bd97621SJim Harris bdev_io.type = SPDK_BDEV_IO_TYPE_RESET; 13164bd97621SJim Harris 13174bd97621SJim Harris /* RESETs are not based on LBAs - so this should return false. */ 1318aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 13194bd97621SJim Harris 13204bd97621SJim Harris bdev_io.type = SPDK_BDEV_IO_TYPE_READ; 13214bd97621SJim Harris bdev_io.u.bdev.offset_blocks = 0; 13224bd97621SJim Harris bdev_io.u.bdev.num_blocks = 32; 13234bd97621SJim Harris 13244bd97621SJim Harris /* This I/O run right up to, but does not cross, the boundary - so this should return false. */ 1325aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 13264bd97621SJim Harris 13274bd97621SJim Harris bdev_io.u.bdev.num_blocks = 33; 13284bd97621SJim Harris 13294bd97621SJim Harris /* This I/O spans a boundary. */ 1330aa485663SJim Harris CU_ASSERT(bdev_io_should_split(&bdev_io) == true); 13313b616c0fSJin Yu 13323b616c0fSJin Yu bdev_io.u.bdev.num_blocks = 32; 13333b616c0fSJin Yu bdev.max_segment_size = 512 * 32; 13343b616c0fSJin Yu bdev.max_num_segments = 1; 13353b616c0fSJin Yu bdev_io.u.bdev.iovcnt = 1; 13363b616c0fSJin Yu iov[0].iov_len = 512; 13373b616c0fSJin Yu 13383b616c0fSJin Yu /* Does not cross and exceed max_size or max_segs */ 13393b616c0fSJin Yu CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 13403b616c0fSJin Yu 13413b616c0fSJin Yu bdev.split_on_optimal_io_boundary = false; 13423b616c0fSJin Yu bdev.max_segment_size = 512; 13433b616c0fSJin Yu bdev.max_num_segments = 1; 13443b616c0fSJin Yu bdev_io.u.bdev.iovcnt = 2; 13453b616c0fSJin Yu 13463b616c0fSJin Yu /* Exceed max_segs */ 13473b616c0fSJin Yu CU_ASSERT(bdev_io_should_split(&bdev_io) == true); 13483b616c0fSJin Yu 13493b616c0fSJin Yu bdev.max_num_segments = 2; 13503b616c0fSJin Yu iov[0].iov_len = 513; 13513b616c0fSJin Yu iov[1].iov_len = 512; 13523b616c0fSJin Yu 13533b616c0fSJin Yu /* Exceed max_sizes */ 13543b616c0fSJin Yu CU_ASSERT(bdev_io_should_split(&bdev_io) == true); 1355d6e9827eSArtur Paszkiewicz 1356d6e9827eSArtur Paszkiewicz bdev.max_segment_size = 0; 1357d6e9827eSArtur Paszkiewicz bdev.write_unit_size = 32; 1358d6e9827eSArtur Paszkiewicz bdev.split_on_write_unit = true; 1359d6e9827eSArtur Paszkiewicz bdev_io.type = SPDK_BDEV_IO_TYPE_WRITE; 1360d6e9827eSArtur Paszkiewicz 1361d6e9827eSArtur Paszkiewicz /* This I/O is one write unit */ 1362d6e9827eSArtur Paszkiewicz CU_ASSERT(bdev_io_should_split(&bdev_io) == false); 1363d6e9827eSArtur Paszkiewicz 1364d6e9827eSArtur Paszkiewicz bdev_io.u.bdev.num_blocks = 32 * 2; 1365d6e9827eSArtur Paszkiewicz 1366d6e9827eSArtur Paszkiewicz /* This I/O is more than one write unit */ 1367d6e9827eSArtur Paszkiewicz CU_ASSERT(bdev_io_should_split(&bdev_io) == true); 1368d6e9827eSArtur Paszkiewicz 1369d6e9827eSArtur Paszkiewicz bdev_io.u.bdev.offset_blocks = 1; 1370d6e9827eSArtur Paszkiewicz bdev_io.u.bdev.num_blocks = 32; 1371d6e9827eSArtur Paszkiewicz 1372d6e9827eSArtur Paszkiewicz /* This I/O is not aligned to write unit size */ 1373d6e9827eSArtur Paszkiewicz CU_ASSERT(bdev_io_should_split(&bdev_io) == true); 13744bd97621SJim Harris } 13754bd97621SJim Harris 13764bd97621SJim Harris static void 13779697d84fSJin Yu bdev_io_boundary_split_test(void) 13784bd97621SJim Harris { 13794bd97621SJim Harris struct spdk_bdev *bdev; 1380fb0fe6b1SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 13814bd97621SJim Harris struct spdk_io_channel *io_ch; 1382f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 1383b45556e2SChangpeng Liu struct iovec iov[SPDK_BDEV_IO_NUM_CHILD_IOV * 2]; 13843c7894ffSShuhei Matsumoto struct ut_expected_io *expected_io; 138530f9fecaSJin Yu void *md_buf = (void *)0xFF000000; 13860df515a8SShuhei Matsumoto uint64_t i; 13874bd97621SJim Harris int rc; 13884bd97621SJim Harris 1389f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 1390f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 512; 1391f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 64; 1392107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 13934bd97621SJim Harris 13944bd97621SJim Harris bdev = allocate_bdev("bdev0"); 13954bd97621SJim Harris 139675dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 13974bd97621SJim Harris CU_ASSERT(rc == 0); 1398fb0fe6b1SShuhei Matsumoto SPDK_CU_ASSERT_FATAL(desc != NULL); 139975dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 14004bd97621SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 14014bd97621SJim Harris CU_ASSERT(io_ch != NULL); 14024bd97621SJim Harris 14034bd97621SJim Harris bdev->optimal_io_boundary = 16; 14044bd97621SJim Harris bdev->split_on_optimal_io_boundary = false; 14054bd97621SJim Harris 14064bd97621SJim Harris g_io_done = false; 14074bd97621SJim Harris 14084bd97621SJim Harris /* First test that the I/O does not get split if split_on_optimal_io_boundary == false. */ 14093c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 8, 1); 14103c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 8 * 512); 14113c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14124bd97621SJim Harris 14134bd97621SJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL); 14144bd97621SJim Harris CU_ASSERT(rc == 0); 14154bd97621SJim Harris CU_ASSERT(g_io_done == false); 14164bd97621SJim Harris 14174bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 14184bd97621SJim Harris stub_complete_io(1); 14194bd97621SJim Harris CU_ASSERT(g_io_done == true); 14204bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 14214bd97621SJim Harris 14224bd97621SJim Harris bdev->split_on_optimal_io_boundary = true; 142330f9fecaSJin Yu bdev->md_interleave = false; 142430f9fecaSJin Yu bdev->md_len = 8; 14254bd97621SJim Harris 14264bd97621SJim Harris /* Now test that a single-vector command is split correctly. 14274bd97621SJim Harris * Offset 14, length 8, payload 0xF000 14284bd97621SJim Harris * Child - Offset 14, length 2, payload 0xF000 14294bd97621SJim Harris * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 14304bd97621SJim Harris * 14318f33ef24SShuhei Matsumoto * Set up the expected values before calling spdk_bdev_read_blocks 14324bd97621SJim Harris */ 14334bd97621SJim Harris g_io_done = false; 14343c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1); 143530f9fecaSJin Yu expected_io->md_buf = md_buf; 14363c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512); 14373c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14384bd97621SJim Harris 14393c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1); 144030f9fecaSJin Yu expected_io->md_buf = md_buf + 2 * 8; 14413c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512); 14423c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14434bd97621SJim Harris 14448f33ef24SShuhei Matsumoto /* spdk_bdev_read_blocks will submit the first child immediately. */ 144530f9fecaSJin Yu rc = spdk_bdev_read_blocks_with_md(desc, io_ch, (void *)0xF000, md_buf, 144630f9fecaSJin Yu 14, 8, io_done, NULL); 14478f33ef24SShuhei Matsumoto CU_ASSERT(rc == 0); 14488f33ef24SShuhei Matsumoto CU_ASSERT(g_io_done == false); 14498f33ef24SShuhei Matsumoto 14505616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 14515616c1edSShuhei Matsumoto stub_complete_io(2); 14524bd97621SJim Harris CU_ASSERT(g_io_done == true); 14535616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 14544bd97621SJim Harris 14554bd97621SJim Harris /* Now set up a more complex, multi-vector command that needs to be split, 14564bd97621SJim Harris * including splitting iovecs. 14574bd97621SJim Harris */ 14584bd97621SJim Harris iov[0].iov_base = (void *)0x10000; 14594bd97621SJim Harris iov[0].iov_len = 512; 14604bd97621SJim Harris iov[1].iov_base = (void *)0x20000; 14614bd97621SJim Harris iov[1].iov_len = 20 * 512; 14624bd97621SJim Harris iov[2].iov_base = (void *)0x30000; 14634bd97621SJim Harris iov[2].iov_len = 11 * 512; 14644bd97621SJim Harris 14654bd97621SJim Harris g_io_done = false; 14663c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 2); 146730f9fecaSJin Yu expected_io->md_buf = md_buf; 14683c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0x10000, 512); 14693c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x20000, 512); 14703c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14714bd97621SJim Harris 14723c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 16, 1); 147330f9fecaSJin Yu expected_io->md_buf = md_buf + 2 * 8; 14743c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 512), 16 * 512); 14753c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14764bd97621SJim Harris 14773c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 2); 147830f9fecaSJin Yu expected_io->md_buf = md_buf + 18 * 8; 14793c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 17 * 512), 3 * 512); 14803c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x30000, 11 * 512); 14813c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 14824bd97621SJim Harris 148330f9fecaSJin Yu rc = spdk_bdev_writev_blocks_with_md(desc, io_ch, iov, 3, md_buf, 148430f9fecaSJin Yu 14, 32, io_done, NULL); 14858f33ef24SShuhei Matsumoto CU_ASSERT(rc == 0); 14868f33ef24SShuhei Matsumoto CU_ASSERT(g_io_done == false); 14878f33ef24SShuhei Matsumoto 14885616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 14895616c1edSShuhei Matsumoto stub_complete_io(3); 14904bd97621SJim Harris CU_ASSERT(g_io_done == true); 14914bd97621SJim Harris 14920df515a8SShuhei Matsumoto /* Test multi vector command that needs to be split by strip and then needs to be 14930df515a8SShuhei Matsumoto * split further due to the capacity of child iovs. 14940df515a8SShuhei Matsumoto */ 1495b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV * 2; i++) { 14960df515a8SShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 14970df515a8SShuhei Matsumoto iov[i].iov_len = 512; 14980df515a8SShuhei Matsumoto } 14990df515a8SShuhei Matsumoto 1500b45556e2SChangpeng Liu bdev->optimal_io_boundary = SPDK_BDEV_IO_NUM_CHILD_IOV; 15010df515a8SShuhei Matsumoto g_io_done = false; 1502b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, SPDK_BDEV_IO_NUM_CHILD_IOV, 1503b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV); 150430f9fecaSJin Yu expected_io->md_buf = md_buf; 1505b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV; i++) { 15063c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, i, (void *)((i + 1) * 0x10000), 512); 15070df515a8SShuhei Matsumoto } 15083c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 15090df515a8SShuhei Matsumoto 1510b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV, 1511b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV, SPDK_BDEV_IO_NUM_CHILD_IOV); 1512b45556e2SChangpeng Liu expected_io->md_buf = md_buf + SPDK_BDEV_IO_NUM_CHILD_IOV * 8; 1513b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV; i++) { 15143c7894ffSShuhei Matsumoto ut_expected_io_set_iov(expected_io, i, 1515b45556e2SChangpeng Liu (void *)((i + 1 + SPDK_BDEV_IO_NUM_CHILD_IOV) * 0x10000), 512); 15160df515a8SShuhei Matsumoto } 15173c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 15180df515a8SShuhei Matsumoto 1519b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks_with_md(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV * 2, md_buf, 1520b45556e2SChangpeng Liu 0, SPDK_BDEV_IO_NUM_CHILD_IOV * 2, io_done, NULL); 15218f33ef24SShuhei Matsumoto CU_ASSERT(rc == 0); 15228f33ef24SShuhei Matsumoto CU_ASSERT(g_io_done == false); 15238f33ef24SShuhei Matsumoto 15240df515a8SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 15250df515a8SShuhei Matsumoto stub_complete_io(1); 15260df515a8SShuhei Matsumoto CU_ASSERT(g_io_done == false); 15270df515a8SShuhei Matsumoto 15280df515a8SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 15290df515a8SShuhei Matsumoto stub_complete_io(1); 15300df515a8SShuhei Matsumoto CU_ASSERT(g_io_done == true); 15315616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 15320df515a8SShuhei Matsumoto 15330df515a8SShuhei Matsumoto /* Test multi vector command that needs to be split by strip and then needs to be 1534598ba408Slorneli * split further due to the capacity of child iovs. In this case, the length of 1535598ba408Slorneli * the rest of iovec array with an I/O boundary is the multiple of block size. 1536598ba408Slorneli */ 1537598ba408Slorneli 1538598ba408Slorneli /* Fill iovec array for exactly one boundary. The iovec cnt for this boundary 1539b45556e2SChangpeng Liu * is SPDK_BDEV_IO_NUM_CHILD_IOV + 1, which exceeds the capacity of child iovs. 1540598ba408Slorneli */ 1541b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 1542598ba408Slorneli iov[i].iov_base = (void *)((i + 1) * 0x10000); 1543598ba408Slorneli iov[i].iov_len = 512; 1544598ba408Slorneli } 1545b45556e2SChangpeng Liu for (i = SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i < SPDK_BDEV_IO_NUM_CHILD_IOV; i++) { 1546598ba408Slorneli iov[i].iov_base = (void *)((i + 1) * 0x10000); 1547598ba408Slorneli iov[i].iov_len = 256; 1548598ba408Slorneli } 1549b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV].iov_base = (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000); 1550b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV].iov_len = 512; 1551598ba408Slorneli 1552598ba408Slorneli /* Add an extra iovec to trigger split */ 1553b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV + 1].iov_base = (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000); 1554b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV + 1].iov_len = 512; 1555598ba408Slorneli 1556b45556e2SChangpeng Liu bdev->optimal_io_boundary = SPDK_BDEV_IO_NUM_CHILD_IOV; 1557598ba408Slorneli g_io_done = false; 1558598ba408Slorneli expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 1559b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV - 1, SPDK_BDEV_IO_NUM_CHILD_IOV); 156030f9fecaSJin Yu expected_io->md_buf = md_buf; 1561b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 1562598ba408Slorneli ut_expected_io_set_iov(expected_io, i, 1563598ba408Slorneli (void *)((i + 1) * 0x10000), 512); 1564598ba408Slorneli } 1565b45556e2SChangpeng Liu for (i = SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i < SPDK_BDEV_IO_NUM_CHILD_IOV; i++) { 1566598ba408Slorneli ut_expected_io_set_iov(expected_io, i, 1567598ba408Slorneli (void *)((i + 1) * 0x10000), 256); 1568598ba408Slorneli } 1569598ba408Slorneli TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1570598ba408Slorneli 1571b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV - 1, 1572598ba408Slorneli 1, 1); 1573b45556e2SChangpeng Liu expected_io->md_buf = md_buf + (SPDK_BDEV_IO_NUM_CHILD_IOV - 1) * 8; 1574598ba408Slorneli ut_expected_io_set_iov(expected_io, 0, 1575b45556e2SChangpeng Liu (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000), 512); 1576598ba408Slorneli TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1577598ba408Slorneli 1578b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV, 1579598ba408Slorneli 1, 1); 1580b45556e2SChangpeng Liu expected_io->md_buf = md_buf + SPDK_BDEV_IO_NUM_CHILD_IOV * 8; 1581598ba408Slorneli ut_expected_io_set_iov(expected_io, 0, 1582b45556e2SChangpeng Liu (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000), 512); 1583598ba408Slorneli TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1584598ba408Slorneli 1585b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks_with_md(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV + 2, md_buf, 1586b45556e2SChangpeng Liu 0, SPDK_BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 1587598ba408Slorneli CU_ASSERT(rc == 0); 1588598ba408Slorneli CU_ASSERT(g_io_done == false); 1589598ba408Slorneli 1590598ba408Slorneli CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1591598ba408Slorneli stub_complete_io(1); 1592598ba408Slorneli CU_ASSERT(g_io_done == false); 1593598ba408Slorneli 1594598ba408Slorneli CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 1595598ba408Slorneli stub_complete_io(2); 1596598ba408Slorneli CU_ASSERT(g_io_done == true); 1597598ba408Slorneli CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 1598598ba408Slorneli 1599598ba408Slorneli /* Test multi vector command that needs to be split by strip and then needs to be 1600efd7b514SChangpeng Liu * split further due to the capacity of child iovs, the child request offset should 1601efd7b514SChangpeng Liu * be rewind to last aligned offset and go success without error. 16020df515a8SShuhei Matsumoto */ 1603b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 1; i++) { 16040df515a8SShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 16050df515a8SShuhei Matsumoto iov[i].iov_len = 512; 16060df515a8SShuhei Matsumoto } 1607b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV - 1].iov_base = (void *)(SPDK_BDEV_IO_NUM_CHILD_IOV * 0x10000); 1608b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV - 1].iov_len = 256; 16090df515a8SShuhei Matsumoto 1610b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV].iov_base = (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000); 1611b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV].iov_len = 256; 1612efd7b514SChangpeng Liu 1613b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV + 1].iov_base = (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000); 1614b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV + 1].iov_len = 512; 1615efd7b514SChangpeng Liu 1616b45556e2SChangpeng Liu bdev->optimal_io_boundary = SPDK_BDEV_IO_NUM_CHILD_IOV; 16170df515a8SShuhei Matsumoto g_io_done = false; 16180df515a8SShuhei Matsumoto g_io_status = 0; 1619b45556e2SChangpeng Liu /* The first expected io should be start from offset 0 to SPDK_BDEV_IO_NUM_CHILD_IOV - 1 */ 1620efd7b514SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 1621b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV - 1, SPDK_BDEV_IO_NUM_CHILD_IOV - 1); 162230f9fecaSJin Yu expected_io->md_buf = md_buf; 1623b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 1; i++) { 1624efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, i, 1625efd7b514SChangpeng Liu (void *)((i + 1) * 0x10000), 512); 1626efd7b514SChangpeng Liu } 1627efd7b514SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1628b45556e2SChangpeng Liu /* The second expected io should be start from offset SPDK_BDEV_IO_NUM_CHILD_IOV - 1 to SPDK_BDEV_IO_NUM_CHILD_IOV */ 1629b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV - 1, 1630efd7b514SChangpeng Liu 1, 2); 1631b45556e2SChangpeng Liu expected_io->md_buf = md_buf + (SPDK_BDEV_IO_NUM_CHILD_IOV - 1) * 8; 1632efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, 0, 1633b45556e2SChangpeng Liu (void *)(SPDK_BDEV_IO_NUM_CHILD_IOV * 0x10000), 256); 1634efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, 1, 1635b45556e2SChangpeng Liu (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000), 256); 1636efd7b514SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1637b45556e2SChangpeng Liu /* The third expected io should be start from offset SPDK_BDEV_IO_NUM_CHILD_IOV to SPDK_BDEV_IO_NUM_CHILD_IOV + 1 */ 1638b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV, 1639efd7b514SChangpeng Liu 1, 1); 1640b45556e2SChangpeng Liu expected_io->md_buf = md_buf + SPDK_BDEV_IO_NUM_CHILD_IOV * 8; 1641efd7b514SChangpeng Liu ut_expected_io_set_iov(expected_io, 0, 1642b45556e2SChangpeng Liu (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000), 512); 1643efd7b514SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 16440df515a8SShuhei Matsumoto 1645b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks_with_md(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV * 2, md_buf, 1646b45556e2SChangpeng Liu 0, SPDK_BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 16470df515a8SShuhei Matsumoto CU_ASSERT(rc == 0); 1648efd7b514SChangpeng Liu CU_ASSERT(g_io_done == false); 1649efd7b514SChangpeng Liu 1650efd7b514SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1651efd7b514SChangpeng Liu stub_complete_io(1); 1652efd7b514SChangpeng Liu CU_ASSERT(g_io_done == false); 1653efd7b514SChangpeng Liu 1654efd7b514SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 1655efd7b514SChangpeng Liu stub_complete_io(2); 16560df515a8SShuhei Matsumoto CU_ASSERT(g_io_done == true); 1657efd7b514SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 16580df515a8SShuhei Matsumoto 16593deaf005SShuhei Matsumoto /* Test multi vector command that needs to be split due to the IO boundary and 16603deaf005SShuhei Matsumoto * the capacity of child iovs. Especially test the case when the command is 16613deaf005SShuhei Matsumoto * split due to the capacity of child iovs, the tail address is not aligned with 16623deaf005SShuhei Matsumoto * block size and is rewinded to the aligned address. 16633deaf005SShuhei Matsumoto * 16643deaf005SShuhei Matsumoto * The iovecs used in read request is complex but is based on the data 16653deaf005SShuhei Matsumoto * collected in the real issue. We change the base addresses but keep the lengths 16663deaf005SShuhei Matsumoto * not to loose the credibility of the test. 16673deaf005SShuhei Matsumoto */ 16683deaf005SShuhei Matsumoto bdev->optimal_io_boundary = 128; 16693deaf005SShuhei Matsumoto g_io_done = false; 16703deaf005SShuhei Matsumoto g_io_status = 0; 16713deaf005SShuhei Matsumoto 16723deaf005SShuhei Matsumoto for (i = 0; i < 31; i++) { 16733deaf005SShuhei Matsumoto iov[i].iov_base = (void *)(0xFEED0000000 + (i << 20)); 16743deaf005SShuhei Matsumoto iov[i].iov_len = 1024; 16753deaf005SShuhei Matsumoto } 16763deaf005SShuhei Matsumoto iov[31].iov_base = (void *)0xFEED1F00000; 16773deaf005SShuhei Matsumoto iov[31].iov_len = 32768; 16783deaf005SShuhei Matsumoto iov[32].iov_base = (void *)0xFEED2000000; 16793deaf005SShuhei Matsumoto iov[32].iov_len = 160; 16803deaf005SShuhei Matsumoto iov[33].iov_base = (void *)0xFEED2100000; 16813deaf005SShuhei Matsumoto iov[33].iov_len = 4096; 16823deaf005SShuhei Matsumoto iov[34].iov_base = (void *)0xFEED2200000; 16833deaf005SShuhei Matsumoto iov[34].iov_len = 4096; 16843deaf005SShuhei Matsumoto iov[35].iov_base = (void *)0xFEED2300000; 16853deaf005SShuhei Matsumoto iov[35].iov_len = 4096; 16863deaf005SShuhei Matsumoto iov[36].iov_base = (void *)0xFEED2400000; 16873deaf005SShuhei Matsumoto iov[36].iov_len = 4096; 16883deaf005SShuhei Matsumoto iov[37].iov_base = (void *)0xFEED2500000; 16893deaf005SShuhei Matsumoto iov[37].iov_len = 4096; 16903deaf005SShuhei Matsumoto iov[38].iov_base = (void *)0xFEED2600000; 16913deaf005SShuhei Matsumoto iov[38].iov_len = 4096; 16923deaf005SShuhei Matsumoto iov[39].iov_base = (void *)0xFEED2700000; 16933deaf005SShuhei Matsumoto iov[39].iov_len = 4096; 16943deaf005SShuhei Matsumoto iov[40].iov_base = (void *)0xFEED2800000; 16953deaf005SShuhei Matsumoto iov[40].iov_len = 4096; 16963deaf005SShuhei Matsumoto iov[41].iov_base = (void *)0xFEED2900000; 16973deaf005SShuhei Matsumoto iov[41].iov_len = 4096; 16983deaf005SShuhei Matsumoto iov[42].iov_base = (void *)0xFEED2A00000; 16993deaf005SShuhei Matsumoto iov[42].iov_len = 4096; 17003deaf005SShuhei Matsumoto iov[43].iov_base = (void *)0xFEED2B00000; 17013deaf005SShuhei Matsumoto iov[43].iov_len = 12288; 17023deaf005SShuhei Matsumoto iov[44].iov_base = (void *)0xFEED2C00000; 17033deaf005SShuhei Matsumoto iov[44].iov_len = 8192; 17043deaf005SShuhei Matsumoto iov[45].iov_base = (void *)0xFEED2F00000; 17053deaf005SShuhei Matsumoto iov[45].iov_len = 4096; 17063deaf005SShuhei Matsumoto iov[46].iov_base = (void *)0xFEED3000000; 17073deaf005SShuhei Matsumoto iov[46].iov_len = 4096; 17083deaf005SShuhei Matsumoto iov[47].iov_base = (void *)0xFEED3100000; 17093deaf005SShuhei Matsumoto iov[47].iov_len = 4096; 17103deaf005SShuhei Matsumoto iov[48].iov_base = (void *)0xFEED3200000; 17113deaf005SShuhei Matsumoto iov[48].iov_len = 24576; 17123deaf005SShuhei Matsumoto iov[49].iov_base = (void *)0xFEED3300000; 17133deaf005SShuhei Matsumoto iov[49].iov_len = 16384; 17143deaf005SShuhei Matsumoto iov[50].iov_base = (void *)0xFEED3400000; 17153deaf005SShuhei Matsumoto iov[50].iov_len = 12288; 17163deaf005SShuhei Matsumoto iov[51].iov_base = (void *)0xFEED3500000; 17173deaf005SShuhei Matsumoto iov[51].iov_len = 4096; 17183deaf005SShuhei Matsumoto iov[52].iov_base = (void *)0xFEED3600000; 17193deaf005SShuhei Matsumoto iov[52].iov_len = 4096; 17203deaf005SShuhei Matsumoto iov[53].iov_base = (void *)0xFEED3700000; 17213deaf005SShuhei Matsumoto iov[53].iov_len = 4096; 17223deaf005SShuhei Matsumoto iov[54].iov_base = (void *)0xFEED3800000; 17233deaf005SShuhei Matsumoto iov[54].iov_len = 28672; 17243deaf005SShuhei Matsumoto iov[55].iov_base = (void *)0xFEED3900000; 17253deaf005SShuhei Matsumoto iov[55].iov_len = 20480; 17263deaf005SShuhei Matsumoto iov[56].iov_base = (void *)0xFEED3A00000; 17273deaf005SShuhei Matsumoto iov[56].iov_len = 4096; 17283deaf005SShuhei Matsumoto iov[57].iov_base = (void *)0xFEED3B00000; 17293deaf005SShuhei Matsumoto iov[57].iov_len = 12288; 17303deaf005SShuhei Matsumoto iov[58].iov_base = (void *)0xFEED3C00000; 17313deaf005SShuhei Matsumoto iov[58].iov_len = 4096; 17323deaf005SShuhei Matsumoto iov[59].iov_base = (void *)0xFEED3D00000; 17333deaf005SShuhei Matsumoto iov[59].iov_len = 4096; 17343deaf005SShuhei Matsumoto iov[60].iov_base = (void *)0xFEED3E00000; 17353deaf005SShuhei Matsumoto iov[60].iov_len = 352; 17363deaf005SShuhei Matsumoto 17373deaf005SShuhei Matsumoto /* The 1st child IO must be from iov[0] to iov[31] split by the capacity 17383deaf005SShuhei Matsumoto * of child iovs, 17393deaf005SShuhei Matsumoto */ 17403deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 126, 32); 174130f9fecaSJin Yu expected_io->md_buf = md_buf; 17423deaf005SShuhei Matsumoto for (i = 0; i < 32; i++) { 17433deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, i, iov[i].iov_base, iov[i].iov_len); 17443deaf005SShuhei Matsumoto } 17453deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 17463deaf005SShuhei Matsumoto 17473deaf005SShuhei Matsumoto /* The 2nd child IO must be from iov[32] to the first 864 bytes of iov[33] 17483deaf005SShuhei Matsumoto * split by the IO boundary requirement. 17493deaf005SShuhei Matsumoto */ 17503deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 126, 2, 2); 175130f9fecaSJin Yu expected_io->md_buf = md_buf + 126 * 8; 17523deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, iov[32].iov_base, iov[32].iov_len); 17533deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[33].iov_base, 864); 17543deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 17553deaf005SShuhei Matsumoto 17563deaf005SShuhei Matsumoto /* The 3rd child IO must be from the remaining 3232 bytes of iov[33] to 17573deaf005SShuhei Matsumoto * the first 864 bytes of iov[46] split by the IO boundary requirement. 17583deaf005SShuhei Matsumoto */ 17593deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 128, 128, 14); 176030f9fecaSJin Yu expected_io->md_buf = md_buf + 128 * 8; 17613deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[33].iov_base + 864), 17623deaf005SShuhei Matsumoto iov[33].iov_len - 864); 17633deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[34].iov_base, iov[34].iov_len); 17643deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[35].iov_base, iov[35].iov_len); 17653deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 3, iov[36].iov_base, iov[36].iov_len); 17663deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 4, iov[37].iov_base, iov[37].iov_len); 17673deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 5, iov[38].iov_base, iov[38].iov_len); 17683deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 6, iov[39].iov_base, iov[39].iov_len); 17693deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 7, iov[40].iov_base, iov[40].iov_len); 17703deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 8, iov[41].iov_base, iov[41].iov_len); 17713deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 9, iov[42].iov_base, iov[42].iov_len); 17723deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 10, iov[43].iov_base, iov[43].iov_len); 17733deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 11, iov[44].iov_base, iov[44].iov_len); 17743deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 12, iov[45].iov_base, iov[45].iov_len); 17753deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 13, iov[46].iov_base, 864); 17763deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 17773deaf005SShuhei Matsumoto 17783deaf005SShuhei Matsumoto /* The 4th child IO must be from the remaining 3232 bytes of iov[46] to the 17793deaf005SShuhei Matsumoto * first 864 bytes of iov[52] split by the IO boundary requirement. 17803deaf005SShuhei Matsumoto */ 17813deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 256, 128, 7); 178230f9fecaSJin Yu expected_io->md_buf = md_buf + 256 * 8; 17833deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[46].iov_base + 864), 17843deaf005SShuhei Matsumoto iov[46].iov_len - 864); 17853deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[47].iov_base, iov[47].iov_len); 17863deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[48].iov_base, iov[48].iov_len); 17873deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 3, iov[49].iov_base, iov[49].iov_len); 17883deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 4, iov[50].iov_base, iov[50].iov_len); 17893deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 5, iov[51].iov_base, iov[51].iov_len); 17903deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 6, iov[52].iov_base, 864); 17913deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 17923deaf005SShuhei Matsumoto 17933deaf005SShuhei Matsumoto /* The 5th child IO must be from the remaining 3232 bytes of iov[52] to 17943deaf005SShuhei Matsumoto * the first 4096 bytes of iov[57] split by the IO boundary requirement. 17953deaf005SShuhei Matsumoto */ 17963deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 384, 128, 6); 179730f9fecaSJin Yu expected_io->md_buf = md_buf + 384 * 8; 17983deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[52].iov_base + 864), 17993deaf005SShuhei Matsumoto iov[52].iov_len - 864); 18003deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[53].iov_base, iov[53].iov_len); 18013deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[54].iov_base, iov[54].iov_len); 18023deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 3, iov[55].iov_base, iov[55].iov_len); 18033deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 4, iov[56].iov_base, iov[56].iov_len); 18043deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 5, iov[57].iov_base, 4960); 18053deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 18063deaf005SShuhei Matsumoto 18073deaf005SShuhei Matsumoto /* The 6th child IO must be from the remaining 7328 bytes of iov[57] 18083deaf005SShuhei Matsumoto * to the first 3936 bytes of iov[58] split by the capacity of child iovs. 18093deaf005SShuhei Matsumoto */ 18103deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 512, 30, 3); 181130f9fecaSJin Yu expected_io->md_buf = md_buf + 512 * 8; 18123deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[57].iov_base + 4960), 18133deaf005SShuhei Matsumoto iov[57].iov_len - 4960); 18143deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[58].iov_base, iov[58].iov_len); 18153deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 2, iov[59].iov_base, 3936); 18163deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 18173deaf005SShuhei Matsumoto 18183deaf005SShuhei Matsumoto /* The 7th child IO is from the remaining 160 bytes of iov[59] and iov[60]. */ 18193deaf005SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 542, 1, 2); 182030f9fecaSJin Yu expected_io->md_buf = md_buf + 542 * 8; 18213deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)((uintptr_t)iov[59].iov_base + 3936), 18223deaf005SShuhei Matsumoto iov[59].iov_len - 3936); 18233deaf005SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, iov[60].iov_base, iov[60].iov_len); 18243deaf005SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 18253deaf005SShuhei Matsumoto 182630f9fecaSJin Yu rc = spdk_bdev_readv_blocks_with_md(desc, io_ch, iov, 61, md_buf, 182730f9fecaSJin Yu 0, 543, io_done, NULL); 18283deaf005SShuhei Matsumoto CU_ASSERT(rc == 0); 18293deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == false); 18303deaf005SShuhei Matsumoto 18313deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 18323deaf005SShuhei Matsumoto stub_complete_io(1); 18333deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == false); 18343deaf005SShuhei Matsumoto 18353deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 5); 18363deaf005SShuhei Matsumoto stub_complete_io(5); 18373deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == false); 18383deaf005SShuhei Matsumoto 18393deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 18403deaf005SShuhei Matsumoto stub_complete_io(1); 18413deaf005SShuhei Matsumoto CU_ASSERT(g_io_done == true); 18423deaf005SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 18433deaf005SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 18443deaf005SShuhei Matsumoto 18454f860d7eSJim Harris /* Test a WRITE_ZEROES that would span an I/O boundary. WRITE_ZEROES should not be 18464f860d7eSJim Harris * split, so test that. 18474bd97621SJim Harris */ 18484bd97621SJim Harris bdev->optimal_io_boundary = 15; 18494bd97621SJim Harris g_io_done = false; 18503c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, 9, 36, 0); 18513c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 18524bd97621SJim Harris 18534bd97621SJim Harris rc = spdk_bdev_write_zeroes_blocks(desc, io_ch, 9, 36, io_done, NULL); 18544bd97621SJim Harris CU_ASSERT(rc == 0); 18554bd97621SJim Harris CU_ASSERT(g_io_done == false); 18564bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 18574bd97621SJim Harris stub_complete_io(1); 18584bd97621SJim Harris CU_ASSERT(g_io_done == true); 18594bd97621SJim Harris 18604f860d7eSJim Harris /* Test an UNMAP. This should also not be split. */ 18614bd97621SJim Harris bdev->optimal_io_boundary = 16; 18624bd97621SJim Harris g_io_done = false; 18633c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_UNMAP, 15, 2, 0); 18643c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 18654bd97621SJim Harris 18664bd97621SJim Harris rc = spdk_bdev_unmap_blocks(desc, io_ch, 15, 2, io_done, NULL); 18674bd97621SJim Harris CU_ASSERT(rc == 0); 18684bd97621SJim Harris CU_ASSERT(g_io_done == false); 18694bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 18704bd97621SJim Harris stub_complete_io(1); 18714bd97621SJim Harris CU_ASSERT(g_io_done == true); 18724bd97621SJim Harris 18734f860d7eSJim Harris /* Test a FLUSH. This should also not be split. */ 18744bd97621SJim Harris bdev->optimal_io_boundary = 16; 18754bd97621SJim Harris g_io_done = false; 18763c7894ffSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_FLUSH, 15, 2, 0); 18773c7894ffSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 18784bd97621SJim Harris 18794bd97621SJim Harris rc = spdk_bdev_flush_blocks(desc, io_ch, 15, 2, io_done, NULL); 18804bd97621SJim Harris CU_ASSERT(rc == 0); 18814bd97621SJim Harris CU_ASSERT(g_io_done == false); 18824bd97621SJim Harris CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 18834bd97621SJim Harris stub_complete_io(1); 18844bd97621SJim Harris CU_ASSERT(g_io_done == true); 18854bd97621SJim Harris 18866c8702acSEvgeniy Kochetov /* Test a COPY. This should also not be split. */ 18876c8702acSEvgeniy Kochetov bdev->optimal_io_boundary = 15; 18886c8702acSEvgeniy Kochetov g_io_done = false; 18896c8702acSEvgeniy Kochetov expected_io = ut_alloc_expected_copy_io(SPDK_BDEV_IO_TYPE_COPY, 9, 45, 36); 18906c8702acSEvgeniy Kochetov TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 18916c8702acSEvgeniy Kochetov 18926c8702acSEvgeniy Kochetov rc = spdk_bdev_copy_blocks(desc, io_ch, 9, 45, 36, io_done, NULL); 18936c8702acSEvgeniy Kochetov CU_ASSERT(rc == 0); 18946c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == false); 18956c8702acSEvgeniy Kochetov CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 18966c8702acSEvgeniy Kochetov stub_complete_io(1); 18976c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == true); 18986c8702acSEvgeniy Kochetov 18993c7894ffSShuhei Matsumoto CU_ASSERT(TAILQ_EMPTY(&g_bdev_ut_channel->expected_io)); 19004bd97621SJim Harris 1901c55c85f8SChangpeng Liu /* Children requests return an error status */ 1902c55c85f8SChangpeng Liu bdev->optimal_io_boundary = 16; 1903c55c85f8SChangpeng Liu iov[0].iov_base = (void *)0x10000; 1904c55c85f8SChangpeng Liu iov[0].iov_len = 512 * 64; 1905c55c85f8SChangpeng Liu g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 1906c55c85f8SChangpeng Liu g_io_done = false; 1907c55c85f8SChangpeng Liu g_io_status = SPDK_BDEV_IO_STATUS_SUCCESS; 1908c55c85f8SChangpeng Liu 1909c55c85f8SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 1, 1, 64, io_done, NULL); 1910c55c85f8SChangpeng Liu CU_ASSERT(rc == 0); 1911c55c85f8SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 5); 1912c55c85f8SChangpeng Liu stub_complete_io(4); 1913c55c85f8SChangpeng Liu CU_ASSERT(g_io_done == false); 1914c55c85f8SChangpeng Liu CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 1915c55c85f8SChangpeng Liu stub_complete_io(1); 1916c55c85f8SChangpeng Liu CU_ASSERT(g_io_done == true); 1917c55c85f8SChangpeng Liu CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 1918c55c85f8SChangpeng Liu 1919c9c7c281SJosh Soref /* Test if a multi vector command terminated with failure before continuing 1920089d178aSShuhei Matsumoto * splitting process when one of child I/O failed. 1921089d178aSShuhei Matsumoto * The multi vector command is as same as the above that needs to be split by strip 1922089d178aSShuhei Matsumoto * and then needs to be split further due to the capacity of child iovs. 1923089d178aSShuhei Matsumoto */ 1924b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 1; i++) { 1925089d178aSShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 1926089d178aSShuhei Matsumoto iov[i].iov_len = 512; 1927089d178aSShuhei Matsumoto } 1928b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV - 1].iov_base = (void *)(SPDK_BDEV_IO_NUM_CHILD_IOV * 0x10000); 1929b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV - 1].iov_len = 256; 1930089d178aSShuhei Matsumoto 1931b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV].iov_base = (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000); 1932b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV].iov_len = 256; 1933089d178aSShuhei Matsumoto 1934b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV + 1].iov_base = (void *)((SPDK_BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000); 1935b45556e2SChangpeng Liu iov[SPDK_BDEV_IO_NUM_CHILD_IOV + 1].iov_len = 512; 1936089d178aSShuhei Matsumoto 1937b45556e2SChangpeng Liu bdev->optimal_io_boundary = SPDK_BDEV_IO_NUM_CHILD_IOV; 1938089d178aSShuhei Matsumoto 1939089d178aSShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 1940089d178aSShuhei Matsumoto g_io_done = false; 1941089d178aSShuhei Matsumoto g_io_status = SPDK_BDEV_IO_STATUS_SUCCESS; 1942089d178aSShuhei Matsumoto 1943b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV * 2, 0, 1944b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 1945089d178aSShuhei Matsumoto CU_ASSERT(rc == 0); 1946089d178aSShuhei Matsumoto CU_ASSERT(g_io_done == false); 1947089d178aSShuhei Matsumoto 1948089d178aSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 1949089d178aSShuhei Matsumoto stub_complete_io(1); 1950089d178aSShuhei Matsumoto CU_ASSERT(g_io_done == true); 1951089d178aSShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 1952089d178aSShuhei Matsumoto 1953089d178aSShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 1954089d178aSShuhei Matsumoto 1955ebacdcd9Spaul luse /* for this test we will create the following conditions to hit the code path where 1956ebacdcd9Spaul luse * we are trying to send and IO following a split that has no iovs because we had to 1957ebacdcd9Spaul luse * trim them for alignment reasons. 1958ebacdcd9Spaul luse * 1959ebacdcd9Spaul luse * - 16K boundary, our IO will start at offset 0 with a length of 0x4200 1960ebacdcd9Spaul luse * - Our IOVs are 0x212 in size so that we run into the 16K boundary at child IOV 1961ebacdcd9Spaul luse * position 30 and overshoot by 0x2e. 1962ebacdcd9Spaul luse * - That means we'll send the IO and loop back to pick up the remaining bytes at 1963ebacdcd9Spaul luse * child IOV index 31. When we do, we find that we have to shorten index 31 by 0x2e 1964ebacdcd9Spaul luse * which eliniates that vector so we just send the first split IO with 30 vectors 1965ebacdcd9Spaul luse * and let the completion pick up the last 2 vectors. 1966ebacdcd9Spaul luse */ 1967ebacdcd9Spaul luse bdev->optimal_io_boundary = 32; 1968ebacdcd9Spaul luse bdev->split_on_optimal_io_boundary = true; 1969ebacdcd9Spaul luse g_io_done = false; 1970ebacdcd9Spaul luse 1971ebacdcd9Spaul luse /* Init all parent IOVs to 0x212 */ 1972b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV + 2; i++) { 1973ebacdcd9Spaul luse iov[i].iov_base = (void *)((i + 1) * 0x10000); 1974ebacdcd9Spaul luse iov[i].iov_len = 0x212; 1975ebacdcd9Spaul luse } 1976ebacdcd9Spaul luse 1977b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, SPDK_BDEV_IO_NUM_CHILD_IOV, 1978b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV - 1); 1979ebacdcd9Spaul luse /* expect 0-29 to be 1:1 with the parent iov */ 1980b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 1981ebacdcd9Spaul luse ut_expected_io_set_iov(expected_io, i, iov[i].iov_base, iov[i].iov_len); 1982ebacdcd9Spaul luse } 1983ebacdcd9Spaul luse 1984ebacdcd9Spaul luse /* expect index 30 to be shortened to 0x1e4 (0x212 - 0x1e) because of the alignment 1985ebacdcd9Spaul luse * where 0x1e is the amount we overshot the 16K boundary 1986ebacdcd9Spaul luse */ 1987b45556e2SChangpeng Liu ut_expected_io_set_iov(expected_io, SPDK_BDEV_IO_NUM_CHILD_IOV - 2, 1988b45556e2SChangpeng Liu (void *)(iov[SPDK_BDEV_IO_NUM_CHILD_IOV - 2].iov_base), 0x1e4); 1989ebacdcd9Spaul luse TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 1990ebacdcd9Spaul luse 1991ebacdcd9Spaul luse /* 2nd child IO will have 2 remaining vectors, one to pick up from the one that was 1992ebacdcd9Spaul luse * shortened that take it to the next boundary and then a final one to get us to 1993ebacdcd9Spaul luse * 0x4200 bytes for the IO. 1994ebacdcd9Spaul luse */ 1995b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV, 1996c26697bfSSlawomir Ptak 1, 2); 1997ebacdcd9Spaul luse /* position 30 picked up the remaining bytes to the next boundary */ 1998ebacdcd9Spaul luse ut_expected_io_set_iov(expected_io, 0, 1999b45556e2SChangpeng Liu (void *)(iov[SPDK_BDEV_IO_NUM_CHILD_IOV - 2].iov_base + 0x1e4), 0x2e); 2000ebacdcd9Spaul luse 2001c9c7c281SJosh Soref /* position 31 picked the the rest of the transfer to get us to 0x4200 */ 2002ebacdcd9Spaul luse ut_expected_io_set_iov(expected_io, 1, 2003b45556e2SChangpeng Liu (void *)(iov[SPDK_BDEV_IO_NUM_CHILD_IOV - 1].iov_base), 0x1d2); 2004ebacdcd9Spaul luse TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 2005ebacdcd9Spaul luse 2006b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV + 1, 0, 2007b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 2008ebacdcd9Spaul luse CU_ASSERT(rc == 0); 2009ebacdcd9Spaul luse CU_ASSERT(g_io_done == false); 2010ebacdcd9Spaul luse 2011ebacdcd9Spaul luse CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 2012ebacdcd9Spaul luse stub_complete_io(1); 2013ebacdcd9Spaul luse CU_ASSERT(g_io_done == false); 2014ebacdcd9Spaul luse 2015ebacdcd9Spaul luse CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 2016ebacdcd9Spaul luse stub_complete_io(1); 2017ebacdcd9Spaul luse CU_ASSERT(g_io_done == true); 2018ebacdcd9Spaul luse CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 2019ebacdcd9Spaul luse 20204bd97621SJim Harris spdk_put_io_channel(io_ch); 20214bd97621SJim Harris spdk_bdev_close(desc); 20224bd97621SJim Harris free_bdev(bdev); 2023107741fcSKonrad Sztyber ut_fini_bdev(); 20244bd97621SJim Harris } 20254bd97621SJim Harris 2026a8780177SShuhei Matsumoto static void 20279697d84fSJin Yu bdev_io_max_size_and_segment_split_test(void) 20289697d84fSJin Yu { 20299697d84fSJin Yu struct spdk_bdev *bdev; 20309697d84fSJin Yu struct spdk_bdev_desc *desc = NULL; 20319697d84fSJin Yu struct spdk_io_channel *io_ch; 2032f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 2033b45556e2SChangpeng Liu struct iovec iov[SPDK_BDEV_IO_NUM_CHILD_IOV * 2]; 20349697d84fSJin Yu struct ut_expected_io *expected_io; 20359697d84fSJin Yu uint64_t i; 20369697d84fSJin Yu int rc; 20379697d84fSJin Yu 2038f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 2039f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 512; 2040f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 64; 20412d36698dSTomasz Zawadzki bdev_opts.opts_size = sizeof(bdev_opts); 2042107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 20439697d84fSJin Yu 20449697d84fSJin Yu bdev = allocate_bdev("bdev0"); 20459697d84fSJin Yu 20469697d84fSJin Yu rc = spdk_bdev_open_ext(bdev->name, true, bdev_ut_event_cb, NULL, &desc); 20479697d84fSJin Yu CU_ASSERT(rc == 0); 20489697d84fSJin Yu SPDK_CU_ASSERT_FATAL(desc != NULL); 20499697d84fSJin Yu io_ch = spdk_bdev_get_io_channel(desc); 20509697d84fSJin Yu CU_ASSERT(io_ch != NULL); 20519697d84fSJin Yu 20529697d84fSJin Yu bdev->split_on_optimal_io_boundary = false; 20539697d84fSJin Yu bdev->optimal_io_boundary = 0; 20549697d84fSJin Yu 20559697d84fSJin Yu /* Case 0 max_num_segments == 0. 20569697d84fSJin Yu * but segment size 2 * 512 > 512 20579697d84fSJin Yu */ 20589697d84fSJin Yu bdev->max_segment_size = 512; 20599697d84fSJin Yu bdev->max_num_segments = 0; 20609697d84fSJin Yu g_io_done = false; 20619697d84fSJin Yu 20629697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 2); 20639697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 512); 20649697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, (void *)(0xF000 + 512), 512); 20659697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 20669697d84fSJin Yu 20679697d84fSJin Yu rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 2, io_done, NULL); 20689697d84fSJin Yu CU_ASSERT(rc == 0); 20699697d84fSJin Yu CU_ASSERT(g_io_done == false); 20709697d84fSJin Yu 20719697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 20729697d84fSJin Yu stub_complete_io(1); 20739697d84fSJin Yu CU_ASSERT(g_io_done == true); 20749697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 20759697d84fSJin Yu 20769697d84fSJin Yu /* Case 1 max_segment_size == 0 20779697d84fSJin Yu * but iov num 2 > 1. 20789697d84fSJin Yu */ 20799697d84fSJin Yu bdev->max_segment_size = 0; 20809697d84fSJin Yu bdev->max_num_segments = 1; 20819697d84fSJin Yu g_io_done = false; 20829697d84fSJin Yu 20839697d84fSJin Yu iov[0].iov_base = (void *)0x10000; 20849697d84fSJin Yu iov[0].iov_len = 512; 20859697d84fSJin Yu iov[1].iov_base = (void *)0x20000; 20869697d84fSJin Yu iov[1].iov_len = 8 * 512; 20879697d84fSJin Yu 20889697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 1, 1); 20899697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[0].iov_base, iov[0].iov_len); 20909697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 20919697d84fSJin Yu 20929697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 15, 8, 1); 20939697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[1].iov_base, iov[1].iov_len); 20949697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 20959697d84fSJin Yu 20969697d84fSJin Yu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 2, 14, 9, io_done, NULL); 20979697d84fSJin Yu CU_ASSERT(rc == 0); 20989697d84fSJin Yu CU_ASSERT(g_io_done == false); 20999697d84fSJin Yu 21009697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 21019697d84fSJin Yu stub_complete_io(2); 21029697d84fSJin Yu CU_ASSERT(g_io_done == true); 21039697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 21049697d84fSJin Yu 21059697d84fSJin Yu /* Test that a non-vector command is split correctly. 21069697d84fSJin Yu * Set up the expected values before calling spdk_bdev_read_blocks 21079697d84fSJin Yu */ 21089697d84fSJin Yu bdev->max_segment_size = 512; 21099697d84fSJin Yu bdev->max_num_segments = 1; 21109697d84fSJin Yu g_io_done = false; 21119697d84fSJin Yu 21129697d84fSJin Yu /* Child IO 0 */ 21139697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 1, 1); 21149697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 512); 21159697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21169697d84fSJin Yu 21179697d84fSJin Yu /* Child IO 1 */ 21189697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 15, 1, 1); 21199697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 1 * 512), 512); 21209697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21219697d84fSJin Yu 21229697d84fSJin Yu /* spdk_bdev_read_blocks will submit the first child immediately. */ 21239697d84fSJin Yu rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 2, io_done, NULL); 21249697d84fSJin Yu CU_ASSERT(rc == 0); 21259697d84fSJin Yu CU_ASSERT(g_io_done == false); 21269697d84fSJin Yu 21279697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 21289697d84fSJin Yu stub_complete_io(2); 21299697d84fSJin Yu CU_ASSERT(g_io_done == true); 21309697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 21319697d84fSJin Yu 21329697d84fSJin Yu /* Now set up a more complex, multi-vector command that needs to be split, 21339697d84fSJin Yu * including splitting iovecs. 21349697d84fSJin Yu */ 21359697d84fSJin Yu bdev->max_segment_size = 2 * 512; 21369697d84fSJin Yu bdev->max_num_segments = 1; 21379697d84fSJin Yu g_io_done = false; 21389697d84fSJin Yu 21399697d84fSJin Yu iov[0].iov_base = (void *)0x10000; 21409697d84fSJin Yu iov[0].iov_len = 2 * 512; 21419697d84fSJin Yu iov[1].iov_base = (void *)0x20000; 21429697d84fSJin Yu iov[1].iov_len = 4 * 512; 21439697d84fSJin Yu iov[2].iov_base = (void *)0x30000; 21449697d84fSJin Yu iov[2].iov_len = 6 * 512; 21459697d84fSJin Yu 21469697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 1); 21479697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[0].iov_base, 512 * 2); 21489697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21499697d84fSJin Yu 21509697d84fSJin Yu /* Split iov[1].size to 2 iov entries then split the segments */ 21519697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 2, 1); 21529697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[1].iov_base, 512 * 2); 21539697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21549697d84fSJin Yu 21559697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 18, 2, 1); 21569697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[1].iov_base + 512 * 2, 512 * 2); 21579697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21589697d84fSJin Yu 21599697d84fSJin Yu /* Split iov[2].size to 3 iov entries then split the segments */ 21609697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 20, 2, 1); 21619697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[2].iov_base, 512 * 2); 21629697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21639697d84fSJin Yu 21649697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 22, 2, 1); 21659697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[2].iov_base + 512 * 2, 512 * 2); 21669697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21679697d84fSJin Yu 21689697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 24, 2, 1); 21699697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[2].iov_base + 512 * 4, 512 * 2); 21709697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 21719697d84fSJin Yu 21729697d84fSJin Yu rc = spdk_bdev_writev_blocks(desc, io_ch, iov, 3, 14, 12, io_done, NULL); 21739697d84fSJin Yu CU_ASSERT(rc == 0); 21749697d84fSJin Yu CU_ASSERT(g_io_done == false); 21759697d84fSJin Yu 21769697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 6); 21779697d84fSJin Yu stub_complete_io(6); 21789697d84fSJin Yu CU_ASSERT(g_io_done == true); 21799697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 21809697d84fSJin Yu 21819697d84fSJin Yu /* Test multi vector command that needs to be split by strip and then needs to be 21829697d84fSJin Yu * split further due to the capacity of parent IO child iovs. 21839697d84fSJin Yu */ 21849697d84fSJin Yu bdev->max_segment_size = 512; 21859697d84fSJin Yu bdev->max_num_segments = 1; 21869697d84fSJin Yu g_io_done = false; 21879697d84fSJin Yu 2188b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV; i++) { 21899697d84fSJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 21909697d84fSJin Yu iov[i].iov_len = 512 * 2; 21919697d84fSJin Yu } 21929697d84fSJin Yu 21939697d84fSJin Yu /* Each input iov.size is split into 2 iovs, 21949697d84fSJin Yu * half of the input iov can fill all child iov entries of a single IO. 21959697d84fSJin Yu */ 2196b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV / 2; i++) { 21979697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 2 * i, 1, 1); 21989697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[i].iov_base, 512); 21999697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 22009697d84fSJin Yu 22019697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 2 * i + 1, 1, 1); 22029697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[i].iov_base + 512, 512); 22039697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 22049697d84fSJin Yu } 22059697d84fSJin Yu 22069697d84fSJin Yu /* The remaining iov is split in the second round */ 2207b45556e2SChangpeng Liu for (i = SPDK_BDEV_IO_NUM_CHILD_IOV / 2; i < SPDK_BDEV_IO_NUM_CHILD_IOV; i++) { 22089697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, i * 2, 1, 1); 22099697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[i].iov_base, 512); 22109697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 22119697d84fSJin Yu 22129697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, i * 2 + 1, 1, 1); 22139697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[i].iov_base + 512, 512); 22149697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 22159697d84fSJin Yu } 22169697d84fSJin Yu 2217b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV, 0, 2218b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV * 2, io_done, NULL); 22199697d84fSJin Yu CU_ASSERT(rc == 0); 22209697d84fSJin Yu CU_ASSERT(g_io_done == false); 22219697d84fSJin Yu 2222b45556e2SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == SPDK_BDEV_IO_NUM_CHILD_IOV); 2223b45556e2SChangpeng Liu stub_complete_io(SPDK_BDEV_IO_NUM_CHILD_IOV); 22249697d84fSJin Yu CU_ASSERT(g_io_done == false); 22259697d84fSJin Yu 2226b45556e2SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == SPDK_BDEV_IO_NUM_CHILD_IOV); 2227b45556e2SChangpeng Liu stub_complete_io(SPDK_BDEV_IO_NUM_CHILD_IOV); 22289697d84fSJin Yu CU_ASSERT(g_io_done == true); 22299697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 22309697d84fSJin Yu 22319697d84fSJin Yu /* A wrong case, a child IO that is divided does 22329697d84fSJin Yu * not meet the principle of multiples of block size, 22339697d84fSJin Yu * and exits with error 22349697d84fSJin Yu */ 22359697d84fSJin Yu bdev->max_segment_size = 512; 22369697d84fSJin Yu bdev->max_num_segments = 1; 22379697d84fSJin Yu g_io_done = false; 22389697d84fSJin Yu 22399697d84fSJin Yu iov[0].iov_base = (void *)0x10000; 22409697d84fSJin Yu iov[0].iov_len = 512 + 256; 22419697d84fSJin Yu iov[1].iov_base = (void *)0x20000; 22429697d84fSJin Yu iov[1].iov_len = 256; 22439697d84fSJin Yu 22449697d84fSJin Yu /* iov[0] is split to 512 and 256. 22459697d84fSJin Yu * 256 is less than a block size, and it is found 22469697d84fSJin Yu * in the next round of split that it is the first child IO smaller than 22479697d84fSJin Yu * the block size, so the error exit 22489697d84fSJin Yu */ 22499697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 1, 1); 22509697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[0].iov_base, 512); 22519697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 22529697d84fSJin Yu 22539697d84fSJin Yu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 2, 0, 2, io_done, NULL); 22549697d84fSJin Yu CU_ASSERT(rc == 0); 22559697d84fSJin Yu CU_ASSERT(g_io_done == false); 22569697d84fSJin Yu 22579697d84fSJin Yu /* First child IO is OK */ 22589697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 22599697d84fSJin Yu stub_complete_io(1); 22609697d84fSJin Yu CU_ASSERT(g_io_done == true); 22619697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 22629697d84fSJin Yu 22639697d84fSJin Yu /* error exit */ 22649697d84fSJin Yu stub_complete_io(1); 22659697d84fSJin Yu CU_ASSERT(g_io_done == true); 22669697d84fSJin Yu CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 22679697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 22689697d84fSJin Yu 22699697d84fSJin Yu /* Test multi vector command that needs to be split by strip and then needs to be 22709697d84fSJin Yu * split further due to the capacity of child iovs. 22719697d84fSJin Yu * 22729697d84fSJin Yu * In this case, the last two iovs need to be split, but it will exceed the capacity 22739697d84fSJin Yu * of child iovs, so it needs to wait until the first batch completed. 22749697d84fSJin Yu */ 22759697d84fSJin Yu bdev->max_segment_size = 512; 2276b45556e2SChangpeng Liu bdev->max_num_segments = SPDK_BDEV_IO_NUM_CHILD_IOV; 22779697d84fSJin Yu g_io_done = false; 22789697d84fSJin Yu 2279b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 22809697d84fSJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 22819697d84fSJin Yu iov[i].iov_len = 512; 22829697d84fSJin Yu } 2283b45556e2SChangpeng Liu for (i = SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i < SPDK_BDEV_IO_NUM_CHILD_IOV; i++) { 22849697d84fSJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 22859697d84fSJin Yu iov[i].iov_len = 512 * 2; 22869697d84fSJin Yu } 22879697d84fSJin Yu 22889697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 2289b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV, SPDK_BDEV_IO_NUM_CHILD_IOV); 2290b45556e2SChangpeng Liu /* 0 ~ (SPDK_BDEV_IO_NUM_CHILD_IOV - 2) Will not be split */ 2291b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 22929697d84fSJin Yu ut_expected_io_set_iov(expected_io, i, iov[i].iov_base, iov[i].iov_len); 22939697d84fSJin Yu } 2294b45556e2SChangpeng Liu /* (SPDK_BDEV_IO_NUM_CHILD_IOV - 2) is split */ 22959697d84fSJin Yu ut_expected_io_set_iov(expected_io, i, iov[i].iov_base, 512); 22969697d84fSJin Yu ut_expected_io_set_iov(expected_io, i + 1, iov[i].iov_base + 512, 512); 22979697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 22989697d84fSJin Yu 22999697d84fSJin Yu /* Child iov entries exceed the max num of parent IO so split it in next round */ 2300b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV, 2, 2); 23019697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[i + 1].iov_base, 512); 23029697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[i + 1].iov_base + 512, 512); 23039697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 23049697d84fSJin Yu 2305b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV, 0, 2306b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV + 2, io_done, NULL); 23079697d84fSJin Yu CU_ASSERT(rc == 0); 23089697d84fSJin Yu CU_ASSERT(g_io_done == false); 23099697d84fSJin Yu 23109697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 23119697d84fSJin Yu stub_complete_io(1); 23129697d84fSJin Yu CU_ASSERT(g_io_done == false); 23139697d84fSJin Yu 23149697d84fSJin Yu /* Next round */ 23159697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 23169697d84fSJin Yu stub_complete_io(1); 23179697d84fSJin Yu CU_ASSERT(g_io_done == true); 23189697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 23199697d84fSJin Yu 23209697d84fSJin Yu /* This case is similar to the previous one, but the io composed of 23219697d84fSJin Yu * the last few entries of child iov is not enough for a blocklen, so they 23229697d84fSJin Yu * cannot be put into this IO, but wait until the next time. 23239697d84fSJin Yu */ 23249697d84fSJin Yu bdev->max_segment_size = 512; 2325b45556e2SChangpeng Liu bdev->max_num_segments = SPDK_BDEV_IO_NUM_CHILD_IOV; 23269697d84fSJin Yu g_io_done = false; 23279697d84fSJin Yu 2328b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 23299697d84fSJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 23309697d84fSJin Yu iov[i].iov_len = 512; 23319697d84fSJin Yu } 23329697d84fSJin Yu 2333b45556e2SChangpeng Liu for (i = SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i < SPDK_BDEV_IO_NUM_CHILD_IOV + 2; i++) { 23349697d84fSJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 23359697d84fSJin Yu iov[i].iov_len = 128; 23369697d84fSJin Yu } 23379697d84fSJin Yu 2338b45556e2SChangpeng Liu /* First child iovcnt is't SPDK_BDEV_IO_NUM_CHILD_IOV but SPDK_BDEV_IO_NUM_CHILD_IOV - 2. 23399697d84fSJin Yu * Because the left 2 iov is not enough for a blocklen. 23409697d84fSJin Yu */ 23419697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 2342b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV - 2, SPDK_BDEV_IO_NUM_CHILD_IOV - 2); 2343b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 23449697d84fSJin Yu ut_expected_io_set_iov(expected_io, i, iov[i].iov_base, iov[i].iov_len); 23459697d84fSJin Yu } 23469697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 23479697d84fSJin Yu 23489697d84fSJin Yu /* The second child io waits until the end of the first child io before executing. 23499697d84fSJin Yu * Because the iovcnt of the two IOs exceeds the child iovcnt of the parent IO. 2350b45556e2SChangpeng Liu * SPDK_BDEV_IO_NUM_CHILD_IOV - 2 to SPDK_BDEV_IO_NUM_CHILD_IOV + 2 23519697d84fSJin Yu */ 2352b45556e2SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, SPDK_BDEV_IO_NUM_CHILD_IOV - 2, 23539697d84fSJin Yu 1, 4); 23549697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[i].iov_base, iov[i].iov_len); 23559697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[i + 1].iov_base, iov[i + 1].iov_len); 23569697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[i + 2].iov_base, iov[i + 2].iov_len); 23579697d84fSJin Yu ut_expected_io_set_iov(expected_io, 3, iov[i + 3].iov_base, iov[i + 3].iov_len); 23589697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 23599697d84fSJin Yu 2360b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV + 2, 0, 2361b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV - 1, io_done, NULL); 23629697d84fSJin Yu CU_ASSERT(rc == 0); 23639697d84fSJin Yu CU_ASSERT(g_io_done == false); 23649697d84fSJin Yu 23659697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 23669697d84fSJin Yu stub_complete_io(1); 23679697d84fSJin Yu CU_ASSERT(g_io_done == false); 23689697d84fSJin Yu 23699697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 23709697d84fSJin Yu stub_complete_io(1); 23719697d84fSJin Yu CU_ASSERT(g_io_done == true); 23729697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 23739697d84fSJin Yu 23749697d84fSJin Yu /* A very complicated case. Each sg entry exceeds max_segment_size and 23759697d84fSJin Yu * needs to be split. At the same time, child io must be a multiple of blocklen. 23769697d84fSJin Yu * At the same time, child iovcnt exceeds parent iovcnt. 23779697d84fSJin Yu */ 23789697d84fSJin Yu bdev->max_segment_size = 512 + 128; 23799697d84fSJin Yu bdev->max_num_segments = 3; 23809697d84fSJin Yu g_io_done = false; 23819697d84fSJin Yu 2382b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i++) { 23839697d84fSJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 23849697d84fSJin Yu iov[i].iov_len = 512 + 256; 23859697d84fSJin Yu } 23869697d84fSJin Yu 2387b45556e2SChangpeng Liu for (i = SPDK_BDEV_IO_NUM_CHILD_IOV - 2; i < SPDK_BDEV_IO_NUM_CHILD_IOV + 2; i++) { 23889697d84fSJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 23899697d84fSJin Yu iov[i].iov_len = 512 + 128; 23909697d84fSJin Yu } 23919697d84fSJin Yu 23929697d84fSJin Yu /* Child IOs use 9 entries per for() round and 3 * 9 = 27 child iov entries. 23939697d84fSJin Yu * Consume 4 parent IO iov entries per for() round and 6 block size. 23949697d84fSJin Yu * Generate 9 child IOs. 23959697d84fSJin Yu */ 23969697d84fSJin Yu for (i = 0; i < 3; i++) { 23979697d84fSJin Yu uint32_t j = i * 4; 23989697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, i * 6, 2, 3); 23999697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[j].iov_base, 640); 24009697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[j].iov_base + 640, 128); 24019697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[j + 1].iov_base, 256); 24029697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24039697d84fSJin Yu 24049697d84fSJin Yu /* Child io must be a multiple of blocklen 24059697d84fSJin Yu * iov[j + 2] must be split. If the third entry is also added, 24069697d84fSJin Yu * the multiple of blocklen cannot be guaranteed. But it still 24079697d84fSJin Yu * occupies one iov entry of the parent child iov. 24089697d84fSJin Yu */ 24099697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, i * 6 + 2, 2, 2); 24109697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[j + 1].iov_base + 256, 512); 24119697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[j + 2].iov_base, 512); 24129697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24139697d84fSJin Yu 24149697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, i * 6 + 4, 2, 3); 24159697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[j + 2].iov_base + 512, 256); 24169697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[j + 3].iov_base, 640); 24179697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[j + 3].iov_base + 640, 128); 24189697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24199697d84fSJin Yu } 24209697d84fSJin Yu 24219697d84fSJin Yu /* Child iov position at 27, the 10th child IO 24229697d84fSJin Yu * iov entry index is 3 * 4 and offset is 3 * 6 24239697d84fSJin Yu */ 24249697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 18, 2, 3); 24259697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[12].iov_base, 640); 24269697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[12].iov_base + 640, 128); 24279697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[13].iov_base, 256); 24289697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24299697d84fSJin Yu 24309697d84fSJin Yu /* Child iov position at 30, the 11th child IO */ 24319697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 20, 2, 2); 24329697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[13].iov_base + 256, 512); 24339697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[14].iov_base, 512); 24349697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24359697d84fSJin Yu 24369697d84fSJin Yu /* The 2nd split round and iovpos is 0, the 12th child IO */ 24379697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 22, 2, 3); 24389697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[14].iov_base + 512, 256); 24399697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[15].iov_base, 640); 24409697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[15].iov_base + 640, 128); 24419697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24429697d84fSJin Yu 24439697d84fSJin Yu /* Consume 9 child IOs and 27 child iov entries. 24449697d84fSJin Yu * Consume 4 parent IO iov entries per for() round and 6 block size. 24459697d84fSJin Yu * Parent IO iov index start from 16 and block offset start from 24 24469697d84fSJin Yu */ 24479697d84fSJin Yu for (i = 0; i < 3; i++) { 24489697d84fSJin Yu uint32_t j = i * 4 + 16; 24499697d84fSJin Yu uint32_t offset = i * 6 + 24; 24509697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, offset, 2, 3); 24519697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[j].iov_base, 640); 24529697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[j].iov_base + 640, 128); 24539697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[j + 1].iov_base, 256); 24549697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24559697d84fSJin Yu 24569697d84fSJin Yu /* Child io must be a multiple of blocklen 24579697d84fSJin Yu * iov[j + 2] must be split. If the third entry is also added, 24589697d84fSJin Yu * the multiple of blocklen cannot be guaranteed. But it still 24599697d84fSJin Yu * occupies one iov entry of the parent child iov. 24609697d84fSJin Yu */ 24619697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, offset + 2, 2, 2); 24629697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[j + 1].iov_base + 256, 512); 24639697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[j + 2].iov_base, 512); 24649697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24659697d84fSJin Yu 24669697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, offset + 4, 2, 3); 24679697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[j + 2].iov_base + 512, 256); 24689697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[j + 3].iov_base, 640); 24699697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[j + 3].iov_base + 640, 128); 24709697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24719697d84fSJin Yu } 24729697d84fSJin Yu 24739697d84fSJin Yu /* The 22th child IO, child iov position at 30 */ 24749697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 42, 1, 1); 24759697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[28].iov_base, 512); 24769697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24779697d84fSJin Yu 24789697d84fSJin Yu /* The third round */ 24799697d84fSJin Yu /* Here is the 23nd child IO and child iovpos is 0 */ 24809697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 43, 2, 3); 24819697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[28].iov_base + 512, 256); 24829697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[29].iov_base, 640); 24839697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[29].iov_base + 640, 128); 24849697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24859697d84fSJin Yu 24869697d84fSJin Yu /* The 24th child IO */ 24879697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 45, 3, 3); 24889697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[30].iov_base, 640); 24899697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[31].iov_base, 640); 24909697d84fSJin Yu ut_expected_io_set_iov(expected_io, 2, iov[32].iov_base, 256); 24919697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24929697d84fSJin Yu 24939697d84fSJin Yu /* The 25th child IO */ 24949697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 48, 2, 2); 24959697d84fSJin Yu ut_expected_io_set_iov(expected_io, 0, iov[32].iov_base + 256, 384); 24969697d84fSJin Yu ut_expected_io_set_iov(expected_io, 1, iov[33].iov_base, 640); 24979697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 24989697d84fSJin Yu 2499b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV + 2, 0, 25009697d84fSJin Yu 50, io_done, NULL); 25019697d84fSJin Yu CU_ASSERT(rc == 0); 25029697d84fSJin Yu CU_ASSERT(g_io_done == false); 25039697d84fSJin Yu 25049697d84fSJin Yu /* Parent IO supports up to 32 child iovs, so it is calculated that 25059697d84fSJin Yu * a maximum of 11 IOs can be split at a time, and the 25069697d84fSJin Yu * splitting will continue after the first batch is over. 25079697d84fSJin Yu */ 25089697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 11); 25099697d84fSJin Yu stub_complete_io(11); 25109697d84fSJin Yu CU_ASSERT(g_io_done == false); 25119697d84fSJin Yu 25129697d84fSJin Yu /* The 2nd round */ 25139697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 11); 25149697d84fSJin Yu stub_complete_io(11); 25159697d84fSJin Yu CU_ASSERT(g_io_done == false); 25169697d84fSJin Yu 25179697d84fSJin Yu /* The last round */ 25189697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 25199697d84fSJin Yu stub_complete_io(3); 25209697d84fSJin Yu CU_ASSERT(g_io_done == true); 25219697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 25229697d84fSJin Yu 25239697d84fSJin Yu /* Test an WRITE_ZEROES. This should also not be split. */ 25249697d84fSJin Yu bdev->max_segment_size = 512; 25259697d84fSJin Yu bdev->max_num_segments = 1; 25269697d84fSJin Yu g_io_done = false; 25279697d84fSJin Yu 25289697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, 9, 36, 0); 25299697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 25309697d84fSJin Yu 25319697d84fSJin Yu rc = spdk_bdev_write_zeroes_blocks(desc, io_ch, 9, 36, io_done, NULL); 25329697d84fSJin Yu CU_ASSERT(rc == 0); 25339697d84fSJin Yu CU_ASSERT(g_io_done == false); 25349697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 25359697d84fSJin Yu stub_complete_io(1); 25369697d84fSJin Yu CU_ASSERT(g_io_done == true); 25379697d84fSJin Yu 25389697d84fSJin Yu /* Test an UNMAP. This should also not be split. */ 25399697d84fSJin Yu g_io_done = false; 25409697d84fSJin Yu 25419697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_UNMAP, 15, 4, 0); 25429697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 25439697d84fSJin Yu 25449697d84fSJin Yu rc = spdk_bdev_unmap_blocks(desc, io_ch, 15, 4, io_done, NULL); 25459697d84fSJin Yu CU_ASSERT(rc == 0); 25469697d84fSJin Yu CU_ASSERT(g_io_done == false); 25479697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 25489697d84fSJin Yu stub_complete_io(1); 25499697d84fSJin Yu CU_ASSERT(g_io_done == true); 25509697d84fSJin Yu 25519697d84fSJin Yu /* Test a FLUSH. This should also not be split. */ 25529697d84fSJin Yu g_io_done = false; 25539697d84fSJin Yu 25549697d84fSJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_FLUSH, 15, 4, 0); 25559697d84fSJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 25569697d84fSJin Yu 2557c26697bfSSlawomir Ptak rc = spdk_bdev_flush_blocks(desc, io_ch, 15, 4, io_done, NULL); 25589697d84fSJin Yu CU_ASSERT(rc == 0); 25599697d84fSJin Yu CU_ASSERT(g_io_done == false); 25609697d84fSJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 25619697d84fSJin Yu stub_complete_io(1); 25629697d84fSJin Yu CU_ASSERT(g_io_done == true); 25639697d84fSJin Yu 25646c8702acSEvgeniy Kochetov /* Test a COPY. This should also not be split. */ 25656c8702acSEvgeniy Kochetov g_io_done = false; 25666c8702acSEvgeniy Kochetov 25676c8702acSEvgeniy Kochetov expected_io = ut_alloc_expected_copy_io(SPDK_BDEV_IO_TYPE_COPY, 9, 45, 36); 25686c8702acSEvgeniy Kochetov TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 25696c8702acSEvgeniy Kochetov 25706c8702acSEvgeniy Kochetov rc = spdk_bdev_copy_blocks(desc, io_ch, 9, 45, 36, io_done, NULL); 25716c8702acSEvgeniy Kochetov CU_ASSERT(rc == 0); 25726c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == false); 25736c8702acSEvgeniy Kochetov CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 25746c8702acSEvgeniy Kochetov stub_complete_io(1); 25756c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == true); 25766c8702acSEvgeniy Kochetov 257701ccef6eSKonrad Sztyber /* Test that IOs are split on max_rw_size */ 257801ccef6eSKonrad Sztyber bdev->max_rw_size = 2; 257901ccef6eSKonrad Sztyber bdev->max_segment_size = 0; 258001ccef6eSKonrad Sztyber bdev->max_num_segments = 0; 258101ccef6eSKonrad Sztyber g_io_done = false; 258201ccef6eSKonrad Sztyber 258301ccef6eSKonrad Sztyber /* 5 blocks in a contiguous buffer */ 258401ccef6eSKonrad Sztyber iov[0].iov_base = (void *)0x10000; 258501ccef6eSKonrad Sztyber iov[0].iov_len = 5 * 512; 258601ccef6eSKonrad Sztyber 258701ccef6eSKonrad Sztyber /* First: offset=0, num_blocks=2 */ 258801ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 2, 1); 258901ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x10000, 2 * 512); 259001ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 259101ccef6eSKonrad Sztyber /* Second: offset=2, num_blocks=2 */ 259201ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 2, 2, 1); 259301ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x10000 + 2 * 512, 2 * 512); 259401ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 259501ccef6eSKonrad Sztyber /* Third: offset=4, num_blocks=1 */ 259601ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 4, 1, 1); 259701ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x10000 + 4 * 512, 512); 259801ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 259901ccef6eSKonrad Sztyber 260001ccef6eSKonrad Sztyber rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 1, 0, 5, io_done, NULL); 260101ccef6eSKonrad Sztyber CU_ASSERT(rc == 0); 260201ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == false); 260301ccef6eSKonrad Sztyber 260401ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 260501ccef6eSKonrad Sztyber stub_complete_io(3); 260601ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == true); 260701ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 260801ccef6eSKonrad Sztyber 260901ccef6eSKonrad Sztyber /* Check splitting on both max_rw_size + max_num_segments */ 261001ccef6eSKonrad Sztyber bdev->max_rw_size = 2; 261101ccef6eSKonrad Sztyber bdev->max_num_segments = 2; 261201ccef6eSKonrad Sztyber bdev->max_segment_size = 0; 261301ccef6eSKonrad Sztyber g_io_done = false; 261401ccef6eSKonrad Sztyber 261501ccef6eSKonrad Sztyber /* 5 blocks split across 4 iovs */ 261601ccef6eSKonrad Sztyber iov[0].iov_base = (void *)0x10000; 261701ccef6eSKonrad Sztyber iov[0].iov_len = 3 * 512; 261801ccef6eSKonrad Sztyber iov[1].iov_base = (void *)0x20000; 261901ccef6eSKonrad Sztyber iov[1].iov_len = 256; 262001ccef6eSKonrad Sztyber iov[2].iov_base = (void *)0x30000; 262101ccef6eSKonrad Sztyber iov[2].iov_len = 256; 262201ccef6eSKonrad Sztyber iov[3].iov_base = (void *)0x40000; 262301ccef6eSKonrad Sztyber iov[3].iov_len = 512; 262401ccef6eSKonrad Sztyber 262501ccef6eSKonrad Sztyber /* First: offset=0, num_blocks=2, iovcnt=1 */ 262601ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 2, 1); 262701ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x10000, 2 * 512); 262801ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 262901ccef6eSKonrad Sztyber /* Second: offset=2, num_blocks=1, iovcnt=1 (max_segment_size prevents from submitting 263001ccef6eSKonrad Sztyber * the rest of iov[0], and iov[1]+iov[2]) 263101ccef6eSKonrad Sztyber */ 263201ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 2, 1, 1); 263301ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x10000 + 2 * 512, 512); 263401ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 263501ccef6eSKonrad Sztyber /* Third: offset=3, num_blocks=1, iovcnt=2 (iov[1]+iov[2]) */ 263601ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 3, 1, 2); 263701ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x20000, 256); 263801ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 1, (void *)0x30000, 256); 263901ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 264001ccef6eSKonrad Sztyber /* Fourth: offset=4, num_blocks=1, iovcnt=1 (iov[3]) */ 264101ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 4, 1, 1); 264201ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x40000, 512); 264301ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 264401ccef6eSKonrad Sztyber 264501ccef6eSKonrad Sztyber rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 4, 0, 5, io_done, NULL); 264601ccef6eSKonrad Sztyber CU_ASSERT(rc == 0); 264701ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == false); 264801ccef6eSKonrad Sztyber 264901ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 265001ccef6eSKonrad Sztyber stub_complete_io(4); 265101ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == true); 265201ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 265301ccef6eSKonrad Sztyber 265401ccef6eSKonrad Sztyber /* Check splitting on both max_rw_size + max_segment_size */ 265501ccef6eSKonrad Sztyber bdev->max_rw_size = 2; 265601ccef6eSKonrad Sztyber bdev->max_segment_size = 512; 265701ccef6eSKonrad Sztyber bdev->max_num_segments = 0; 265801ccef6eSKonrad Sztyber g_io_done = false; 265901ccef6eSKonrad Sztyber 266001ccef6eSKonrad Sztyber /* 6 blocks in a contiguous buffer */ 266101ccef6eSKonrad Sztyber iov[0].iov_base = (void *)0x10000; 266201ccef6eSKonrad Sztyber iov[0].iov_len = 6 * 512; 266301ccef6eSKonrad Sztyber 266401ccef6eSKonrad Sztyber /* We expect 3 IOs each with 2 blocks and 2 iovs */ 266501ccef6eSKonrad Sztyber for (i = 0; i < 3; ++i) { 266601ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, i * 2, 2, 2); 266701ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x10000 + i * 2 * 512, 512); 266801ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 1, (void *)0x10000 + i * 2 * 512 + 512, 512); 266901ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 267001ccef6eSKonrad Sztyber } 267101ccef6eSKonrad Sztyber 267201ccef6eSKonrad Sztyber rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 1, 0, 6, io_done, NULL); 267301ccef6eSKonrad Sztyber CU_ASSERT(rc == 0); 267401ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == false); 267501ccef6eSKonrad Sztyber 267601ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 267701ccef6eSKonrad Sztyber stub_complete_io(3); 267801ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == true); 267901ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 268001ccef6eSKonrad Sztyber 268101ccef6eSKonrad Sztyber /* Check splitting on max_rw_size limited by SPDK_BDEV_IO_NUM_CHILD_IOV */ 268201ccef6eSKonrad Sztyber bdev->max_rw_size = 1; 268301ccef6eSKonrad Sztyber bdev->max_segment_size = 0; 268401ccef6eSKonrad Sztyber bdev->max_num_segments = 0; 268501ccef6eSKonrad Sztyber g_io_done = false; 268601ccef6eSKonrad Sztyber 268701ccef6eSKonrad Sztyber /* SPDK_BDEV_IO_NUM_CHILD_IOV + 1 blocks */ 268801ccef6eSKonrad Sztyber iov[0].iov_base = (void *)0x10000; 268901ccef6eSKonrad Sztyber iov[0].iov_len = (SPDK_BDEV_IO_NUM_CHILD_IOV + 1) * 512; 269001ccef6eSKonrad Sztyber 269101ccef6eSKonrad Sztyber /* We expect SPDK_BDEV_IO_NUM_CHILD_IOV + 1 IOs each with a single iov */ 269201ccef6eSKonrad Sztyber for (i = 0; i < 3; ++i) { 269301ccef6eSKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, i, 1, 1); 269401ccef6eSKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, (void *)0x10000 + i * 512, 512); 269501ccef6eSKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 269601ccef6eSKonrad Sztyber } 269701ccef6eSKonrad Sztyber 269801ccef6eSKonrad Sztyber rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 1, 0, SPDK_BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL); 269901ccef6eSKonrad Sztyber CU_ASSERT(rc == 0); 270001ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == false); 270101ccef6eSKonrad Sztyber 270201ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == SPDK_BDEV_IO_NUM_CHILD_IOV); 270301ccef6eSKonrad Sztyber stub_complete_io(SPDK_BDEV_IO_NUM_CHILD_IOV); 270401ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == false); 270501ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 270601ccef6eSKonrad Sztyber stub_complete_io(1); 270701ccef6eSKonrad Sztyber CU_ASSERT(g_io_done == true); 270801ccef6eSKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 270901ccef6eSKonrad Sztyber 27109697d84fSJin Yu spdk_put_io_channel(io_ch); 27119697d84fSJin Yu spdk_bdev_close(desc); 27129697d84fSJin Yu free_bdev(bdev); 2713107741fcSKonrad Sztyber ut_fini_bdev(); 27149697d84fSJin Yu } 27159697d84fSJin Yu 27169697d84fSJin Yu static void 27171fae3687SJin Yu bdev_io_mix_split_test(void) 27181fae3687SJin Yu { 27191fae3687SJin Yu struct spdk_bdev *bdev; 27201fae3687SJin Yu struct spdk_bdev_desc *desc = NULL; 27211fae3687SJin Yu struct spdk_io_channel *io_ch; 2722f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 2723b45556e2SChangpeng Liu struct iovec iov[SPDK_BDEV_IO_NUM_CHILD_IOV * 2]; 27241fae3687SJin Yu struct ut_expected_io *expected_io; 27251fae3687SJin Yu uint64_t i; 27261fae3687SJin Yu int rc; 27271fae3687SJin Yu 2728f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 2729f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 512; 2730f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 64; 2731107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 27321fae3687SJin Yu 27331fae3687SJin Yu bdev = allocate_bdev("bdev0"); 27341fae3687SJin Yu 27351fae3687SJin Yu rc = spdk_bdev_open_ext(bdev->name, true, bdev_ut_event_cb, NULL, &desc); 27361fae3687SJin Yu CU_ASSERT(rc == 0); 27371fae3687SJin Yu SPDK_CU_ASSERT_FATAL(desc != NULL); 27381fae3687SJin Yu io_ch = spdk_bdev_get_io_channel(desc); 27391fae3687SJin Yu CU_ASSERT(io_ch != NULL); 27401fae3687SJin Yu 27411fae3687SJin Yu /* First case optimal_io_boundary == max_segment_size * max_num_segments */ 27421fae3687SJin Yu bdev->split_on_optimal_io_boundary = true; 27431fae3687SJin Yu bdev->optimal_io_boundary = 16; 27441fae3687SJin Yu 27451fae3687SJin Yu bdev->max_segment_size = 512; 27461fae3687SJin Yu bdev->max_num_segments = 16; 27471fae3687SJin Yu g_io_done = false; 27481fae3687SJin Yu 27491fae3687SJin Yu /* IO crossing the IO boundary requires split 27501fae3687SJin Yu * Total 2 child IOs. 27511fae3687SJin Yu */ 27521fae3687SJin Yu 27531fae3687SJin Yu /* The 1st child IO split the segment_size to multiple segment entry */ 27541fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 2); 27551fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 512); 27561fae3687SJin Yu ut_expected_io_set_iov(expected_io, 1, (void *)(0xF000 + 512), 512); 27571fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 27581fae3687SJin Yu 27591fae3687SJin Yu /* The 2nd child IO split the segment_size to multiple segment entry */ 27601fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 2, 2); 27611fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 512); 27621fae3687SJin Yu ut_expected_io_set_iov(expected_io, 1, (void *)(0xF000 + 3 * 512), 512); 27631fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 27641fae3687SJin Yu 27651fae3687SJin Yu rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 4, io_done, NULL); 27661fae3687SJin Yu CU_ASSERT(rc == 0); 27671fae3687SJin Yu CU_ASSERT(g_io_done == false); 27681fae3687SJin Yu 27691fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 27701fae3687SJin Yu stub_complete_io(2); 27711fae3687SJin Yu CU_ASSERT(g_io_done == true); 27721fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 27731fae3687SJin Yu 27741fae3687SJin Yu /* Second case optimal_io_boundary > max_segment_size * max_num_segments */ 27751fae3687SJin Yu bdev->max_segment_size = 15 * 512; 27761fae3687SJin Yu bdev->max_num_segments = 1; 27771fae3687SJin Yu g_io_done = false; 27781fae3687SJin Yu 27791fae3687SJin Yu /* IO crossing the IO boundary requires split. 27801fae3687SJin Yu * The 1st child IO segment size exceeds the max_segment_size, 27813f912cf0SMichal Berger * So 1st child IO will be split to multiple segment entry. 27821fae3687SJin Yu * Then it split to 2 child IOs because of the max_num_segments. 27831fae3687SJin Yu * Total 3 child IOs. 27841fae3687SJin Yu */ 27851fae3687SJin Yu 27861fae3687SJin Yu /* The first 2 IOs are in an IO boundary. 27871fae3687SJin Yu * Because the optimal_io_boundary > max_segment_size * max_num_segments 27881fae3687SJin Yu * So it split to the first 2 IOs. 27891fae3687SJin Yu */ 27901fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 15, 1); 27911fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 512 * 15); 27921fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 27931fae3687SJin Yu 27941fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 15, 1, 1); 27951fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 512 * 15), 512); 27961fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 27971fae3687SJin Yu 27981fae3687SJin Yu /* The 3rd Child IO is because of the io boundary */ 27991fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 2, 1); 28001fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 512 * 16), 512 * 2); 28011fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 28021fae3687SJin Yu 28031fae3687SJin Yu rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 0, 18, io_done, NULL); 28041fae3687SJin Yu CU_ASSERT(rc == 0); 28051fae3687SJin Yu CU_ASSERT(g_io_done == false); 28061fae3687SJin Yu 28071fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 28081fae3687SJin Yu stub_complete_io(3); 28091fae3687SJin Yu CU_ASSERT(g_io_done == true); 28101fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 28111fae3687SJin Yu 28121fae3687SJin Yu /* Third case optimal_io_boundary < max_segment_size * max_num_segments */ 28131fae3687SJin Yu bdev->max_segment_size = 17 * 512; 28141fae3687SJin Yu bdev->max_num_segments = 1; 28151fae3687SJin Yu g_io_done = false; 28161fae3687SJin Yu 28171fae3687SJin Yu /* IO crossing the IO boundary requires split. 28181fae3687SJin Yu * Child IO does not split. 28191fae3687SJin Yu * Total 2 child IOs. 28201fae3687SJin Yu */ 28211fae3687SJin Yu 28221fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 0, 16, 1); 28231fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 512 * 16); 28241fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 28251fae3687SJin Yu 28261fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 2, 1); 28271fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 512 * 16), 512 * 2); 28281fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 28291fae3687SJin Yu 28301fae3687SJin Yu rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 0, 18, io_done, NULL); 28311fae3687SJin Yu CU_ASSERT(rc == 0); 28321fae3687SJin Yu CU_ASSERT(g_io_done == false); 28331fae3687SJin Yu 28341fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 28351fae3687SJin Yu stub_complete_io(2); 28361fae3687SJin Yu CU_ASSERT(g_io_done == true); 28371fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 28381fae3687SJin Yu 28391fae3687SJin Yu /* Now set up a more complex, multi-vector command that needs to be split, 28401fae3687SJin Yu * including splitting iovecs. 28411fae3687SJin Yu * optimal_io_boundary < max_segment_size * max_num_segments 28421fae3687SJin Yu */ 28431fae3687SJin Yu bdev->max_segment_size = 3 * 512; 28441fae3687SJin Yu bdev->max_num_segments = 6; 28451fae3687SJin Yu g_io_done = false; 28461fae3687SJin Yu 28471fae3687SJin Yu iov[0].iov_base = (void *)0x10000; 28481fae3687SJin Yu iov[0].iov_len = 4 * 512; 28491fae3687SJin Yu iov[1].iov_base = (void *)0x20000; 28501fae3687SJin Yu iov[1].iov_len = 4 * 512; 28511fae3687SJin Yu iov[2].iov_base = (void *)0x30000; 28521fae3687SJin Yu iov[2].iov_len = 10 * 512; 28531fae3687SJin Yu 28541fae3687SJin Yu /* IO crossing the IO boundary requires split. 28551fae3687SJin Yu * The 1st child IO segment size exceeds the max_segment_size and after 28561fae3687SJin Yu * splitting segment_size, the num_segments exceeds max_num_segments. 28573f912cf0SMichal Berger * So 1st child IO will be split to 2 child IOs. 28581fae3687SJin Yu * Total 3 child IOs. 28591fae3687SJin Yu */ 28601fae3687SJin Yu 28611fae3687SJin Yu /* The first 2 IOs are in an IO boundary. 2862c9c7c281SJosh Soref * After splitting segment size the segment num exceeds. 28631fae3687SJin Yu * So it splits to 2 child IOs. 28641fae3687SJin Yu */ 28651fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 0, 14, 6); 28661fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, iov[0].iov_base, 512 * 3); 28671fae3687SJin Yu ut_expected_io_set_iov(expected_io, 1, iov[0].iov_base + 512 * 3, 512); 28681fae3687SJin Yu ut_expected_io_set_iov(expected_io, 2, iov[1].iov_base, 512 * 3); 28691fae3687SJin Yu ut_expected_io_set_iov(expected_io, 3, iov[1].iov_base + 512 * 3, 512); 28701fae3687SJin Yu ut_expected_io_set_iov(expected_io, 4, iov[2].iov_base, 512 * 3); 28711fae3687SJin Yu ut_expected_io_set_iov(expected_io, 5, iov[2].iov_base + 512 * 3, 512 * 3); 28721fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 28731fae3687SJin Yu 28741fae3687SJin Yu /* The 2nd child IO has the left segment entry */ 28751fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 1); 28761fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, iov[2].iov_base + 512 * 6, 512 * 2); 28771fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 28781fae3687SJin Yu 28791fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 2, 1); 28801fae3687SJin Yu ut_expected_io_set_iov(expected_io, 0, iov[2].iov_base + 512 * 8, 512 * 2); 28811fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 28821fae3687SJin Yu 28831fae3687SJin Yu rc = spdk_bdev_writev_blocks(desc, io_ch, iov, 3, 0, 18, io_done, NULL); 28841fae3687SJin Yu CU_ASSERT(rc == 0); 28851fae3687SJin Yu CU_ASSERT(g_io_done == false); 28861fae3687SJin Yu 28871fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 28881fae3687SJin Yu stub_complete_io(3); 28891fae3687SJin Yu CU_ASSERT(g_io_done == true); 28901fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 28911fae3687SJin Yu 28921fae3687SJin Yu /* A very complicated case. Each sg entry exceeds max_segment_size 28931fae3687SJin Yu * and split on io boundary. 28941fae3687SJin Yu * optimal_io_boundary < max_segment_size * max_num_segments 28951fae3687SJin Yu */ 28961fae3687SJin Yu bdev->max_segment_size = 3 * 512; 2897b45556e2SChangpeng Liu bdev->max_num_segments = SPDK_BDEV_IO_NUM_CHILD_IOV; 28981fae3687SJin Yu g_io_done = false; 28991fae3687SJin Yu 29001fae3687SJin Yu for (i = 0; i < 20; i++) { 29011fae3687SJin Yu iov[i].iov_base = (void *)((i + 1) * 0x10000); 29021fae3687SJin Yu iov[i].iov_len = 512 * 4; 29031fae3687SJin Yu } 29041fae3687SJin Yu 29051fae3687SJin Yu /* IO crossing the IO boundary requires split. 29061fae3687SJin Yu * 80 block length can split 5 child IOs base on offset and IO boundary. 29073f912cf0SMichal Berger * Each iov entry needs to be split to 2 entries because of max_segment_size 29081fae3687SJin Yu * Total 5 child IOs. 29091fae3687SJin Yu */ 29101fae3687SJin Yu 29111fae3687SJin Yu /* 4 iov entries are in an IO boundary and each iov entry splits to 2. 29121fae3687SJin Yu * So each child IO occupies 8 child iov entries. 29131fae3687SJin Yu */ 29141fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 0, 16, 8); 29151fae3687SJin Yu for (i = 0; i < 4; i++) { 29161fae3687SJin Yu int iovcnt = i * 2; 29171fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt, iov[i].iov_base, 512 * 3); 29181fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt + 1, iov[i].iov_base + 512 * 3, 512); 29191fae3687SJin Yu } 29201fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 29211fae3687SJin Yu 29221fae3687SJin Yu /* 2nd child IO and total 16 child iov entries of parent IO */ 29231fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 16, 8); 29241fae3687SJin Yu for (i = 4; i < 8; i++) { 29251fae3687SJin Yu int iovcnt = (i - 4) * 2; 29261fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt, iov[i].iov_base, 512 * 3); 29271fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt + 1, iov[i].iov_base + 512 * 3, 512); 29281fae3687SJin Yu } 29291fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 29301fae3687SJin Yu 29311fae3687SJin Yu /* 3rd child IO and total 24 child iov entries of parent IO */ 29321fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 16, 8); 29331fae3687SJin Yu for (i = 8; i < 12; i++) { 29341fae3687SJin Yu int iovcnt = (i - 8) * 2; 29351fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt, iov[i].iov_base, 512 * 3); 29361fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt + 1, iov[i].iov_base + 512 * 3, 512); 29371fae3687SJin Yu } 29381fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 29391fae3687SJin Yu 29401fae3687SJin Yu /* 4th child IO and total 32 child iov entries of parent IO */ 29411fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 48, 16, 8); 29421fae3687SJin Yu for (i = 12; i < 16; i++) { 29431fae3687SJin Yu int iovcnt = (i - 12) * 2; 29441fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt, iov[i].iov_base, 512 * 3); 29451fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt + 1, iov[i].iov_base + 512 * 3, 512); 29461fae3687SJin Yu } 29471fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 29481fae3687SJin Yu 29493f912cf0SMichal Berger /* 5th child IO and because of the child iov entry it should be split 29501fae3687SJin Yu * in next round. 29511fae3687SJin Yu */ 29521fae3687SJin Yu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 64, 16, 8); 29531fae3687SJin Yu for (i = 16; i < 20; i++) { 29541fae3687SJin Yu int iovcnt = (i - 16) * 2; 29551fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt, iov[i].iov_base, 512 * 3); 29561fae3687SJin Yu ut_expected_io_set_iov(expected_io, iovcnt + 1, iov[i].iov_base + 512 * 3, 512); 29571fae3687SJin Yu } 29581fae3687SJin Yu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 29591fae3687SJin Yu 29601fae3687SJin Yu rc = spdk_bdev_writev_blocks(desc, io_ch, iov, 20, 0, 80, io_done, NULL); 29611fae3687SJin Yu CU_ASSERT(rc == 0); 29621fae3687SJin Yu CU_ASSERT(g_io_done == false); 29631fae3687SJin Yu 29641fae3687SJin Yu /* First split round */ 29651fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 29661fae3687SJin Yu stub_complete_io(4); 29671fae3687SJin Yu CU_ASSERT(g_io_done == false); 29681fae3687SJin Yu 29691fae3687SJin Yu /* Second split round */ 29701fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 29711fae3687SJin Yu stub_complete_io(1); 29721fae3687SJin Yu CU_ASSERT(g_io_done == true); 29731fae3687SJin Yu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 29741fae3687SJin Yu 29751fae3687SJin Yu spdk_put_io_channel(io_ch); 29761fae3687SJin Yu spdk_bdev_close(desc); 29771fae3687SJin Yu free_bdev(bdev); 2978107741fcSKonrad Sztyber ut_fini_bdev(); 29791fae3687SJin Yu } 29801fae3687SJin Yu 29811fae3687SJin Yu static void 2982a8780177SShuhei Matsumoto bdev_io_split_with_io_wait(void) 2983a8780177SShuhei Matsumoto { 2984a8780177SShuhei Matsumoto struct spdk_bdev *bdev; 2985b701087fSDarek Stojaczyk struct spdk_bdev_desc *desc = NULL; 2986a8780177SShuhei Matsumoto struct spdk_io_channel *io_ch; 2987a8780177SShuhei Matsumoto struct spdk_bdev_channel *channel; 2988a8780177SShuhei Matsumoto struct spdk_bdev_mgmt_channel *mgmt_ch; 2989f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 29905616c1edSShuhei Matsumoto struct iovec iov[3]; 2991a8780177SShuhei Matsumoto struct ut_expected_io *expected_io; 2992a8780177SShuhei Matsumoto int rc; 2993a8780177SShuhei Matsumoto 2994f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 2995f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 2; 2996f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 1; 2997107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 2998a8780177SShuhei Matsumoto 2999a8780177SShuhei Matsumoto bdev = allocate_bdev("bdev0"); 3000a8780177SShuhei Matsumoto 300175dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 3002a8780177SShuhei Matsumoto CU_ASSERT(rc == 0); 3003a8780177SShuhei Matsumoto CU_ASSERT(desc != NULL); 300475dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 3005a8780177SShuhei Matsumoto io_ch = spdk_bdev_get_io_channel(desc); 3006a8780177SShuhei Matsumoto CU_ASSERT(io_ch != NULL); 3007a8780177SShuhei Matsumoto channel = spdk_io_channel_get_ctx(io_ch); 3008a8780177SShuhei Matsumoto mgmt_ch = channel->shared_resource->mgmt_ch; 3009a8780177SShuhei Matsumoto 3010a8780177SShuhei Matsumoto bdev->optimal_io_boundary = 16; 3011a8780177SShuhei Matsumoto bdev->split_on_optimal_io_boundary = true; 3012a8780177SShuhei Matsumoto 3013a8780177SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 3014a8780177SShuhei Matsumoto CU_ASSERT(rc == 0); 3015a8780177SShuhei Matsumoto 3016a8780177SShuhei Matsumoto /* Now test that a single-vector command is split correctly. 3017a8780177SShuhei Matsumoto * Offset 14, length 8, payload 0xF000 3018a8780177SShuhei Matsumoto * Child - Offset 14, length 2, payload 0xF000 3019a8780177SShuhei Matsumoto * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 3020a8780177SShuhei Matsumoto * 3021a8780177SShuhei Matsumoto * Set up the expected values before calling spdk_bdev_read_blocks 3022a8780177SShuhei Matsumoto */ 3023a8780177SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1); 3024a8780177SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512); 3025a8780177SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 3026a8780177SShuhei Matsumoto 3027a8780177SShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1); 3028a8780177SShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512); 3029a8780177SShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 3030a8780177SShuhei Matsumoto 30315616c1edSShuhei Matsumoto /* The following children will be submitted sequentially due to the capacity of 30325616c1edSShuhei Matsumoto * spdk_bdev_io. 30335616c1edSShuhei Matsumoto */ 30345616c1edSShuhei Matsumoto 3035a8780177SShuhei Matsumoto /* The first child I/O will be queued to wait until an spdk_bdev_io becomes available */ 3036a8780177SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL); 3037a8780177SShuhei Matsumoto CU_ASSERT(rc == 0); 3038a8780177SShuhei Matsumoto CU_ASSERT(!TAILQ_EMPTY(&mgmt_ch->io_wait_queue)); 3039a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 3040a8780177SShuhei Matsumoto 3041a8780177SShuhei Matsumoto /* Completing the first read I/O will submit the first child */ 3042a8780177SShuhei Matsumoto stub_complete_io(1); 3043a8780177SShuhei Matsumoto CU_ASSERT(TAILQ_EMPTY(&mgmt_ch->io_wait_queue)); 3044a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 3045a8780177SShuhei Matsumoto 3046a8780177SShuhei Matsumoto /* Completing the first child will submit the second child */ 3047a8780177SShuhei Matsumoto stub_complete_io(1); 3048a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 3049a8780177SShuhei Matsumoto 3050a8780177SShuhei Matsumoto /* Complete the second child I/O. This should result in our callback getting 3051a8780177SShuhei Matsumoto * invoked since the parent I/O is now complete. 3052a8780177SShuhei Matsumoto */ 3053a8780177SShuhei Matsumoto stub_complete_io(1); 3054a8780177SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3055a8780177SShuhei Matsumoto 30565616c1edSShuhei Matsumoto /* Now set up a more complex, multi-vector command that needs to be split, 30575616c1edSShuhei Matsumoto * including splitting iovecs. 30585616c1edSShuhei Matsumoto */ 30595616c1edSShuhei Matsumoto iov[0].iov_base = (void *)0x10000; 30605616c1edSShuhei Matsumoto iov[0].iov_len = 512; 30615616c1edSShuhei Matsumoto iov[1].iov_base = (void *)0x20000; 30625616c1edSShuhei Matsumoto iov[1].iov_len = 20 * 512; 30635616c1edSShuhei Matsumoto iov[2].iov_base = (void *)0x30000; 30645616c1edSShuhei Matsumoto iov[2].iov_len = 11 * 512; 30655616c1edSShuhei Matsumoto 30665616c1edSShuhei Matsumoto g_io_done = false; 30675616c1edSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 2); 30685616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)0x10000, 512); 30695616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x20000, 512); 30705616c1edSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 30715616c1edSShuhei Matsumoto 30725616c1edSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 16, 1); 30735616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 512), 16 * 512); 30745616c1edSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 30755616c1edSShuhei Matsumoto 30765616c1edSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 2); 30775616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 0, (void *)(0x20000 + 17 * 512), 3 * 512); 30785616c1edSShuhei Matsumoto ut_expected_io_set_iov(expected_io, 1, (void *)0x30000, 11 * 512); 30795616c1edSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 30805616c1edSShuhei Matsumoto 30815616c1edSShuhei Matsumoto rc = spdk_bdev_writev_blocks(desc, io_ch, iov, 3, 14, 32, io_done, NULL); 30825616c1edSShuhei Matsumoto CU_ASSERT(rc == 0); 30835616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == false); 30845616c1edSShuhei Matsumoto 30855616c1edSShuhei Matsumoto /* The following children will be submitted sequentially due to the capacity of 30865616c1edSShuhei Matsumoto * spdk_bdev_io. 30875616c1edSShuhei Matsumoto */ 30885616c1edSShuhei Matsumoto 30895616c1edSShuhei Matsumoto /* Completing the first child will submit the second child */ 30905616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 30915616c1edSShuhei Matsumoto stub_complete_io(1); 30925616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == false); 30935616c1edSShuhei Matsumoto 30945616c1edSShuhei Matsumoto /* Completing the second child will submit the third child */ 30955616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 30965616c1edSShuhei Matsumoto stub_complete_io(1); 30975616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == false); 30985616c1edSShuhei Matsumoto 30995616c1edSShuhei Matsumoto /* Completing the third child will result in our callback getting invoked 31005616c1edSShuhei Matsumoto * since the parent I/O is now complete. 31015616c1edSShuhei Matsumoto */ 31025616c1edSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 31035616c1edSShuhei Matsumoto stub_complete_io(1); 31045616c1edSShuhei Matsumoto CU_ASSERT(g_io_done == true); 31055616c1edSShuhei Matsumoto 3106a8780177SShuhei Matsumoto CU_ASSERT(TAILQ_EMPTY(&g_bdev_ut_channel->expected_io)); 3107a8780177SShuhei Matsumoto 3108a8780177SShuhei Matsumoto spdk_put_io_channel(io_ch); 3109a8780177SShuhei Matsumoto spdk_bdev_close(desc); 3110a8780177SShuhei Matsumoto free_bdev(bdev); 3111107741fcSKonrad Sztyber ut_fini_bdev(); 3112a8780177SShuhei Matsumoto } 3113a8780177SShuhei Matsumoto 3114dadd2a6dSPiotr Pelplinski static void 3115d6e9827eSArtur Paszkiewicz bdev_io_write_unit_split_test(void) 3116d6e9827eSArtur Paszkiewicz { 3117d6e9827eSArtur Paszkiewicz struct spdk_bdev *bdev; 3118d6e9827eSArtur Paszkiewicz struct spdk_bdev_desc *desc = NULL; 3119d6e9827eSArtur Paszkiewicz struct spdk_io_channel *io_ch; 3120d6e9827eSArtur Paszkiewicz struct spdk_bdev_opts bdev_opts = {}; 3121b45556e2SChangpeng Liu struct iovec iov[SPDK_BDEV_IO_NUM_CHILD_IOV * 4]; 3122d6e9827eSArtur Paszkiewicz struct ut_expected_io *expected_io; 3123d6e9827eSArtur Paszkiewicz uint64_t i; 3124d6e9827eSArtur Paszkiewicz int rc; 3125d6e9827eSArtur Paszkiewicz 3126d6e9827eSArtur Paszkiewicz spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 3127d6e9827eSArtur Paszkiewicz bdev_opts.bdev_io_pool_size = 512; 3128d6e9827eSArtur Paszkiewicz bdev_opts.bdev_io_cache_size = 64; 3129107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 3130d6e9827eSArtur Paszkiewicz 3131d6e9827eSArtur Paszkiewicz bdev = allocate_bdev("bdev0"); 3132d6e9827eSArtur Paszkiewicz 3133d6e9827eSArtur Paszkiewicz rc = spdk_bdev_open_ext(bdev->name, true, bdev_ut_event_cb, NULL, &desc); 3134d6e9827eSArtur Paszkiewicz CU_ASSERT(rc == 0); 3135d6e9827eSArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(desc != NULL); 3136d6e9827eSArtur Paszkiewicz io_ch = spdk_bdev_get_io_channel(desc); 3137d6e9827eSArtur Paszkiewicz CU_ASSERT(io_ch != NULL); 3138d6e9827eSArtur Paszkiewicz 3139d6e9827eSArtur Paszkiewicz /* Write I/O 2x larger than write_unit_size should get split into 2 I/Os */ 3140d6e9827eSArtur Paszkiewicz bdev->write_unit_size = 32; 3141d6e9827eSArtur Paszkiewicz bdev->split_on_write_unit = true; 3142d6e9827eSArtur Paszkiewicz g_io_done = false; 3143d6e9827eSArtur Paszkiewicz 3144d6e9827eSArtur Paszkiewicz expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 0, 32, 1); 3145d6e9827eSArtur Paszkiewicz ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 32 * 512); 3146d6e9827eSArtur Paszkiewicz TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 3147d6e9827eSArtur Paszkiewicz 3148d6e9827eSArtur Paszkiewicz expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 32, 1); 3149d6e9827eSArtur Paszkiewicz ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 32 * 512), 32 * 512); 3150d6e9827eSArtur Paszkiewicz TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 3151d6e9827eSArtur Paszkiewicz 3152d6e9827eSArtur Paszkiewicz rc = spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 0, 64, io_done, NULL); 3153d6e9827eSArtur Paszkiewicz CU_ASSERT(rc == 0); 3154d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == false); 3155d6e9827eSArtur Paszkiewicz 3156d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 3157d6e9827eSArtur Paszkiewicz stub_complete_io(2); 3158d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == true); 3159d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3160d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 3161d6e9827eSArtur Paszkiewicz 3162d6e9827eSArtur Paszkiewicz /* Same as above but with optimal_io_boundary < write_unit_size - the I/O should be split 3163d6e9827eSArtur Paszkiewicz * based on write_unit_size, not optimal_io_boundary */ 3164d6e9827eSArtur Paszkiewicz bdev->split_on_optimal_io_boundary = true; 3165d6e9827eSArtur Paszkiewicz bdev->optimal_io_boundary = 16; 3166d6e9827eSArtur Paszkiewicz g_io_done = false; 3167d6e9827eSArtur Paszkiewicz 3168d6e9827eSArtur Paszkiewicz rc = spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 0, 64, io_done, NULL); 3169d6e9827eSArtur Paszkiewicz CU_ASSERT(rc == 0); 3170d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == false); 3171d6e9827eSArtur Paszkiewicz 3172d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 3173d6e9827eSArtur Paszkiewicz stub_complete_io(2); 3174d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == true); 3175d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3176d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 3177d6e9827eSArtur Paszkiewicz 3178d6e9827eSArtur Paszkiewicz /* Write I/O should fail if it is smaller than write_unit_size */ 3179d6e9827eSArtur Paszkiewicz g_io_done = false; 3180d6e9827eSArtur Paszkiewicz 3181d6e9827eSArtur Paszkiewicz rc = spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 0, 31, io_done, NULL); 3182d6e9827eSArtur Paszkiewicz CU_ASSERT(rc == 0); 3183d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == false); 3184d6e9827eSArtur Paszkiewicz 3185d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3186d6e9827eSArtur Paszkiewicz poll_threads(); 3187d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == true); 3188d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3189d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 3190d6e9827eSArtur Paszkiewicz 3191d6e9827eSArtur Paszkiewicz /* Same for I/O not aligned to write_unit_size */ 3192d6e9827eSArtur Paszkiewicz g_io_done = false; 3193d6e9827eSArtur Paszkiewicz 3194d6e9827eSArtur Paszkiewicz rc = spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 1, 32, io_done, NULL); 3195d6e9827eSArtur Paszkiewicz CU_ASSERT(rc == 0); 3196d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == false); 3197d6e9827eSArtur Paszkiewicz 3198d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3199d6e9827eSArtur Paszkiewicz poll_threads(); 3200d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == true); 3201d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3202d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 3203d6e9827eSArtur Paszkiewicz 3204d6e9827eSArtur Paszkiewicz /* Write should fail if it needs to be split but there are not enough iovs to submit 3205d6e9827eSArtur Paszkiewicz * an entire write unit */ 3206d6e9827eSArtur Paszkiewicz bdev->write_unit_size = SPDK_COUNTOF(iov) / 2; 3207d6e9827eSArtur Paszkiewicz g_io_done = false; 3208d6e9827eSArtur Paszkiewicz 3209d6e9827eSArtur Paszkiewicz for (i = 0; i < SPDK_COUNTOF(iov); i++) { 3210d6e9827eSArtur Paszkiewicz iov[i].iov_base = (void *)(0x1000 + 512 * i); 3211d6e9827eSArtur Paszkiewicz iov[i].iov_len = 512; 3212d6e9827eSArtur Paszkiewicz } 3213d6e9827eSArtur Paszkiewicz 3214d6e9827eSArtur Paszkiewicz rc = spdk_bdev_writev_blocks(desc, io_ch, iov, SPDK_COUNTOF(iov), 0, SPDK_COUNTOF(iov), 3215d6e9827eSArtur Paszkiewicz io_done, NULL); 3216d6e9827eSArtur Paszkiewicz CU_ASSERT(rc == 0); 3217d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == false); 3218d6e9827eSArtur Paszkiewicz 3219d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3220d6e9827eSArtur Paszkiewicz poll_threads(); 3221d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_done == true); 3222d6e9827eSArtur Paszkiewicz CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 3223d6e9827eSArtur Paszkiewicz CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 3224d6e9827eSArtur Paszkiewicz 3225d6e9827eSArtur Paszkiewicz spdk_put_io_channel(io_ch); 3226d6e9827eSArtur Paszkiewicz spdk_bdev_close(desc); 3227d6e9827eSArtur Paszkiewicz free_bdev(bdev); 3228107741fcSKonrad Sztyber ut_fini_bdev(); 3229d6e9827eSArtur Paszkiewicz } 3230d6e9827eSArtur Paszkiewicz 3231d6e9827eSArtur Paszkiewicz static void 3232dadd2a6dSPiotr Pelplinski bdev_io_alignment(void) 3233dadd2a6dSPiotr Pelplinski { 3234dadd2a6dSPiotr Pelplinski struct spdk_bdev *bdev; 3235e2ce08cfSTomasz Zawadzki struct spdk_bdev_desc *desc = NULL; 3236dadd2a6dSPiotr Pelplinski struct spdk_io_channel *io_ch; 3237f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 3238dadd2a6dSPiotr Pelplinski int rc; 32399714818dSyidong0635 void *buf = NULL; 3240dadd2a6dSPiotr Pelplinski struct iovec iovs[2]; 3241dadd2a6dSPiotr Pelplinski int iovcnt; 3242dadd2a6dSPiotr Pelplinski uint64_t alignment; 3243dadd2a6dSPiotr Pelplinski 3244f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 3245f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 20; 3246f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 2; 3247107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 3248dadd2a6dSPiotr Pelplinski 324980da9548SMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 3250dadd2a6dSPiotr Pelplinski bdev = allocate_bdev("bdev0"); 3251dadd2a6dSPiotr Pelplinski 325275dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 3253dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 3254dadd2a6dSPiotr Pelplinski CU_ASSERT(desc != NULL); 325575dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 3256dadd2a6dSPiotr Pelplinski io_ch = spdk_bdev_get_io_channel(desc); 3257dadd2a6dSPiotr Pelplinski CU_ASSERT(io_ch != NULL); 3258dadd2a6dSPiotr Pelplinski 3259dadd2a6dSPiotr Pelplinski /* Create aligned buffer */ 3260dadd2a6dSPiotr Pelplinski rc = posix_memalign(&buf, 4096, 8192); 3261dadd2a6dSPiotr Pelplinski SPDK_CU_ASSERT_FATAL(rc == 0); 3262dadd2a6dSPiotr Pelplinski 3263dadd2a6dSPiotr Pelplinski /* Pass aligned single buffer with no alignment required */ 3264dadd2a6dSPiotr Pelplinski alignment = 1; 3265dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3266dadd2a6dSPiotr Pelplinski 3267dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf, 0, 1, io_done, NULL); 3268dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 3269dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3270dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3271dadd2a6dSPiotr Pelplinski alignment)); 3272dadd2a6dSPiotr Pelplinski 3273dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf, 0, 1, io_done, NULL); 3274dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 3275dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3276dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3277dadd2a6dSPiotr Pelplinski alignment)); 3278dadd2a6dSPiotr Pelplinski 3279dadd2a6dSPiotr Pelplinski /* Pass unaligned single buffer with no alignment required */ 3280dadd2a6dSPiotr Pelplinski alignment = 1; 3281dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3282dadd2a6dSPiotr Pelplinski 3283dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 3284dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 32857fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3286dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == buf + 4); 3287dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3288dadd2a6dSPiotr Pelplinski 3289dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 3290dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 32917fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3292dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == buf + 4); 3293dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3294dadd2a6dSPiotr Pelplinski 3295dadd2a6dSPiotr Pelplinski /* Pass unaligned single buffer with 512 alignment required */ 3296dadd2a6dSPiotr Pelplinski alignment = 512; 3297dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3298dadd2a6dSPiotr Pelplinski 3299dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 3300dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33017fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.bounce_buf.orig_iovcnt == 1); 33027fee8002SBen Walker CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_buf.iov); 3303dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3304dadd2a6dSPiotr Pelplinski alignment)); 3305dadd2a6dSPiotr Pelplinski stub_complete_io(1); 33067fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3307dadd2a6dSPiotr Pelplinski 3308dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf + 4, 0, 1, io_done, NULL); 3309dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33107fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.bounce_buf.orig_iovcnt == 1); 33117fee8002SBen Walker CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_buf.iov); 3312dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3313dadd2a6dSPiotr Pelplinski alignment)); 3314dadd2a6dSPiotr Pelplinski stub_complete_io(1); 33157fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3316dadd2a6dSPiotr Pelplinski 3317dadd2a6dSPiotr Pelplinski /* Pass unaligned single buffer with 4096 alignment required */ 3318dadd2a6dSPiotr Pelplinski alignment = 4096; 3319dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3320dadd2a6dSPiotr Pelplinski 3321dadd2a6dSPiotr Pelplinski rc = spdk_bdev_write_blocks(desc, io_ch, buf + 8, 0, 1, io_done, NULL); 3322dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33237fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.bounce_buf.orig_iovcnt == 1); 33247fee8002SBen Walker CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_buf.iov); 3325dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3326dadd2a6dSPiotr Pelplinski alignment)); 3327dadd2a6dSPiotr Pelplinski stub_complete_io(1); 33287fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3329dadd2a6dSPiotr Pelplinski 3330dadd2a6dSPiotr Pelplinski rc = spdk_bdev_read_blocks(desc, io_ch, buf + 8, 0, 1, io_done, NULL); 3331dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33327fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.bounce_buf.orig_iovcnt == 1); 33337fee8002SBen Walker CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_buf.iov); 3334dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3335dadd2a6dSPiotr Pelplinski alignment)); 3336dadd2a6dSPiotr Pelplinski stub_complete_io(1); 33377fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3338dadd2a6dSPiotr Pelplinski 3339dadd2a6dSPiotr Pelplinski /* Pass aligned iovs with no alignment required */ 3340dadd2a6dSPiotr Pelplinski alignment = 1; 3341dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3342dadd2a6dSPiotr Pelplinski 3343dadd2a6dSPiotr Pelplinski iovcnt = 1; 3344dadd2a6dSPiotr Pelplinski iovs[0].iov_base = buf; 3345dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 512; 3346dadd2a6dSPiotr Pelplinski 3347dadd2a6dSPiotr Pelplinski rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3348dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33497fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3350dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3351dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 3352dadd2a6dSPiotr Pelplinski 3353dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3354dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33557fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3356dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3357dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 3358dadd2a6dSPiotr Pelplinski 3359dadd2a6dSPiotr Pelplinski /* Pass unaligned iovs with no alignment required */ 3360dadd2a6dSPiotr Pelplinski alignment = 1; 3361dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3362dadd2a6dSPiotr Pelplinski 3363dadd2a6dSPiotr Pelplinski iovcnt = 2; 3364dadd2a6dSPiotr Pelplinski iovs[0].iov_base = buf + 16; 3365dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 256; 3366dadd2a6dSPiotr Pelplinski iovs[1].iov_base = buf + 16 + 256 + 32; 3367dadd2a6dSPiotr Pelplinski iovs[1].iov_len = 256; 3368dadd2a6dSPiotr Pelplinski 3369dadd2a6dSPiotr Pelplinski rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3370dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33717fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3372dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3373dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 3374dadd2a6dSPiotr Pelplinski 3375dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3376dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33777fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3378dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3379dadd2a6dSPiotr Pelplinski CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == iovs[0].iov_base); 3380dadd2a6dSPiotr Pelplinski 3381dadd2a6dSPiotr Pelplinski /* Pass unaligned iov with 2048 alignment required */ 3382dadd2a6dSPiotr Pelplinski alignment = 2048; 3383dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3384dadd2a6dSPiotr Pelplinski 3385dadd2a6dSPiotr Pelplinski iovcnt = 2; 3386dadd2a6dSPiotr Pelplinski iovs[0].iov_base = buf + 16; 3387dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 256; 3388dadd2a6dSPiotr Pelplinski iovs[1].iov_base = buf + 16 + 256 + 32; 3389dadd2a6dSPiotr Pelplinski iovs[1].iov_len = 256; 3390dadd2a6dSPiotr Pelplinski 3391dadd2a6dSPiotr Pelplinski rc = spdk_bdev_writev(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3392dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 33937fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.bounce_buf.orig_iovcnt == iovcnt); 33947fee8002SBen Walker CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_buf.iov); 3395dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3396dadd2a6dSPiotr Pelplinski alignment)); 3397dadd2a6dSPiotr Pelplinski stub_complete_io(1); 33987fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3399dadd2a6dSPiotr Pelplinski 3400dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3401dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 34027fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.bounce_buf.orig_iovcnt == iovcnt); 34037fee8002SBen Walker CU_ASSERT(g_bdev_io->u.bdev.iovs == &g_bdev_io->internal.bounce_buf.iov); 3404dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3405dadd2a6dSPiotr Pelplinski alignment)); 3406dadd2a6dSPiotr Pelplinski stub_complete_io(1); 34077fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3408dadd2a6dSPiotr Pelplinski 3409dadd2a6dSPiotr Pelplinski /* Pass iov without allocated buffer without alignment required */ 3410dadd2a6dSPiotr Pelplinski alignment = 1; 3411dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3412dadd2a6dSPiotr Pelplinski 3413dadd2a6dSPiotr Pelplinski iovcnt = 1; 3414dadd2a6dSPiotr Pelplinski iovs[0].iov_base = NULL; 3415dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 0; 3416dadd2a6dSPiotr Pelplinski 3417dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3418dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 34197fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3420dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3421dadd2a6dSPiotr Pelplinski alignment)); 3422dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3423dadd2a6dSPiotr Pelplinski 3424dadd2a6dSPiotr Pelplinski /* Pass iov without allocated buffer with 1024 alignment required */ 3425dadd2a6dSPiotr Pelplinski alignment = 1024; 3426dadd2a6dSPiotr Pelplinski bdev->required_alignment = spdk_u32log2(alignment); 3427dadd2a6dSPiotr Pelplinski 3428dadd2a6dSPiotr Pelplinski iovcnt = 1; 3429dadd2a6dSPiotr Pelplinski iovs[0].iov_base = NULL; 3430dadd2a6dSPiotr Pelplinski iovs[0].iov_len = 0; 3431dadd2a6dSPiotr Pelplinski 3432dadd2a6dSPiotr Pelplinski rc = spdk_bdev_readv(desc, io_ch, iovs, iovcnt, 0, 512, io_done, NULL); 3433dadd2a6dSPiotr Pelplinski CU_ASSERT(rc == 0); 34347fee8002SBen Walker CU_ASSERT(g_bdev_io->internal.f.has_bounce_buf == false); 3435dadd2a6dSPiotr Pelplinski CU_ASSERT(_are_iovs_aligned(g_bdev_io->u.bdev.iovs, g_bdev_io->u.bdev.iovcnt, 3436dadd2a6dSPiotr Pelplinski alignment)); 3437dadd2a6dSPiotr Pelplinski stub_complete_io(1); 3438dadd2a6dSPiotr Pelplinski 3439dadd2a6dSPiotr Pelplinski spdk_put_io_channel(io_ch); 3440dadd2a6dSPiotr Pelplinski spdk_bdev_close(desc); 3441dadd2a6dSPiotr Pelplinski free_bdev(bdev); 3442ae43c81aSJim Harris fn_table.submit_request = stub_submit_request; 3443107741fcSKonrad Sztyber ut_fini_bdev(); 3444dadd2a6dSPiotr Pelplinski 3445dadd2a6dSPiotr Pelplinski free(buf); 3446dadd2a6dSPiotr Pelplinski } 3447dadd2a6dSPiotr Pelplinski 344842dba604SPiotr Pelplinski static void 344945f48053SChangpeng Liu bdev_io_alignment_with_boundary(void) 345045f48053SChangpeng Liu { 345145f48053SChangpeng Liu struct spdk_bdev *bdev; 3452e2ce08cfSTomasz Zawadzki struct spdk_bdev_desc *desc = NULL; 345345f48053SChangpeng Liu struct spdk_io_channel *io_ch; 3454f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 345545f48053SChangpeng Liu int rc; 34569714818dSyidong0635 void *buf = NULL; 345745f48053SChangpeng Liu struct iovec iovs[2]; 345845f48053SChangpeng Liu int iovcnt; 345945f48053SChangpeng Liu uint64_t alignment; 346045f48053SChangpeng Liu 3461f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 3462f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 20; 3463f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 2; 3464d3d077ccSZiye Yang bdev_opts.opts_size = sizeof(bdev_opts); 3465107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 346645f48053SChangpeng Liu 346780da9548SMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 346845f48053SChangpeng Liu bdev = allocate_bdev("bdev0"); 346945f48053SChangpeng Liu 347075dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 347145f48053SChangpeng Liu CU_ASSERT(rc == 0); 347245f48053SChangpeng Liu CU_ASSERT(desc != NULL); 347375dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 347445f48053SChangpeng Liu io_ch = spdk_bdev_get_io_channel(desc); 347545f48053SChangpeng Liu CU_ASSERT(io_ch != NULL); 347645f48053SChangpeng Liu 347745f48053SChangpeng Liu /* Create aligned buffer */ 347845f48053SChangpeng Liu rc = posix_memalign(&buf, 4096, 131072); 347945f48053SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0); 348045f48053SChangpeng Liu g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 348145f48053SChangpeng Liu 34827fee8002SBen Walker #ifdef NOTDEF 348345f48053SChangpeng Liu /* 512 * 3 with 2 IO boundary, allocate small data buffer from bdev layer */ 348445f48053SChangpeng Liu alignment = 512; 348545f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 348645f48053SChangpeng Liu bdev->optimal_io_boundary = 2; 348745f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 348845f48053SChangpeng Liu 348945f48053SChangpeng Liu iovcnt = 1; 349045f48053SChangpeng Liu iovs[0].iov_base = NULL; 349145f48053SChangpeng Liu iovs[0].iov_len = 512 * 3; 349245f48053SChangpeng Liu 349345f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 3, io_done, NULL); 349445f48053SChangpeng Liu CU_ASSERT(rc == 0); 349545f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 349645f48053SChangpeng Liu stub_complete_io(2); 349745f48053SChangpeng Liu 349845f48053SChangpeng Liu /* 8KiB with 16 IO boundary, allocate large data buffer from bdev layer */ 349945f48053SChangpeng Liu alignment = 512; 350045f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 350145f48053SChangpeng Liu bdev->optimal_io_boundary = 16; 350245f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 350345f48053SChangpeng Liu 350445f48053SChangpeng Liu iovcnt = 1; 350545f48053SChangpeng Liu iovs[0].iov_base = NULL; 350645f48053SChangpeng Liu iovs[0].iov_len = 512 * 16; 350745f48053SChangpeng Liu 350845f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 16, io_done, NULL); 350945f48053SChangpeng Liu CU_ASSERT(rc == 0); 351045f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 351145f48053SChangpeng Liu stub_complete_io(2); 351245f48053SChangpeng Liu 351345f48053SChangpeng Liu /* 512 * 160 with 128 IO boundary, 63.5KiB + 16.5KiB for the two children requests */ 351445f48053SChangpeng Liu alignment = 512; 351545f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 351645f48053SChangpeng Liu bdev->optimal_io_boundary = 128; 351745f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 351845f48053SChangpeng Liu 351945f48053SChangpeng Liu iovcnt = 1; 352045f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 352145f48053SChangpeng Liu iovs[0].iov_len = 512 * 160; 352245f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 160, io_done, NULL); 352345f48053SChangpeng Liu CU_ASSERT(rc == 0); 352445f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 352545f48053SChangpeng Liu stub_complete_io(2); 352645f48053SChangpeng Liu 35277fee8002SBen Walker #endif 35287fee8002SBen Walker 352945f48053SChangpeng Liu /* 512 * 3 with 2 IO boundary */ 353045f48053SChangpeng Liu alignment = 512; 353145f48053SChangpeng Liu bdev->required_alignment = spdk_u32log2(alignment); 353245f48053SChangpeng Liu bdev->optimal_io_boundary = 2; 353345f48053SChangpeng Liu bdev->split_on_optimal_io_boundary = true; 353445f48053SChangpeng Liu 353545f48053SChangpeng Liu iovcnt = 2; 353645f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 353745f48053SChangpeng Liu iovs[0].iov_len = 512; 353845f48053SChangpeng Liu iovs[1].iov_base = buf + 16 + 512 + 32; 353945f48053SChangpeng Liu iovs[1].iov_len = 1024; 354045f48053SChangpeng Liu 354145f48053SChangpeng Liu rc = spdk_bdev_writev_blocks(desc, io_ch, iovs, iovcnt, 1, 3, io_done, NULL); 354245f48053SChangpeng Liu CU_ASSERT(rc == 0); 354345f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 354445f48053SChangpeng Liu stub_complete_io(2); 354545f48053SChangpeng Liu 354645f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 3, io_done, NULL); 354745f48053SChangpeng Liu CU_ASSERT(rc == 0); 354845f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 354945f48053SChangpeng Liu stub_complete_io(2); 355045f48053SChangpeng Liu 355145f48053SChangpeng Liu /* 512 * 64 with 32 IO boundary */ 355245f48053SChangpeng Liu bdev->optimal_io_boundary = 32; 355345f48053SChangpeng Liu iovcnt = 2; 355445f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 355545f48053SChangpeng Liu iovs[0].iov_len = 16384; 355645f48053SChangpeng Liu iovs[1].iov_base = buf + 16 + 16384 + 32; 355745f48053SChangpeng Liu iovs[1].iov_len = 16384; 355845f48053SChangpeng Liu 355945f48053SChangpeng Liu rc = spdk_bdev_writev_blocks(desc, io_ch, iovs, iovcnt, 1, 64, io_done, NULL); 356045f48053SChangpeng Liu CU_ASSERT(rc == 0); 356145f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 356245f48053SChangpeng Liu stub_complete_io(3); 356345f48053SChangpeng Liu 356445f48053SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iovs, iovcnt, 1, 64, io_done, NULL); 356545f48053SChangpeng Liu CU_ASSERT(rc == 0); 356645f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 3); 356745f48053SChangpeng Liu stub_complete_io(3); 356845f48053SChangpeng Liu 356945f48053SChangpeng Liu /* 512 * 160 with 32 IO boundary */ 357045f48053SChangpeng Liu iovcnt = 1; 357145f48053SChangpeng Liu iovs[0].iov_base = buf + 16; 357245f48053SChangpeng Liu iovs[0].iov_len = 16384 + 65536; 357345f48053SChangpeng Liu 357445f48053SChangpeng Liu rc = spdk_bdev_writev_blocks(desc, io_ch, iovs, iovcnt, 1, 160, io_done, NULL); 357545f48053SChangpeng Liu CU_ASSERT(rc == 0); 357645f48053SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 6); 357745f48053SChangpeng Liu stub_complete_io(6); 357845f48053SChangpeng Liu 357945f48053SChangpeng Liu spdk_put_io_channel(io_ch); 358045f48053SChangpeng Liu spdk_bdev_close(desc); 358145f48053SChangpeng Liu free_bdev(bdev); 3582ae43c81aSJim Harris fn_table.submit_request = stub_submit_request; 3583107741fcSKonrad Sztyber ut_fini_bdev(); 358445f48053SChangpeng Liu 358545f48053SChangpeng Liu free(buf); 358645f48053SChangpeng Liu } 358745f48053SChangpeng Liu 358845f48053SChangpeng Liu static void 358942dba604SPiotr Pelplinski histogram_status_cb(void *cb_arg, int status) 359042dba604SPiotr Pelplinski { 359142dba604SPiotr Pelplinski g_status = status; 359242dba604SPiotr Pelplinski } 359342dba604SPiotr Pelplinski 359442dba604SPiotr Pelplinski static void 359542dba604SPiotr Pelplinski histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) 359642dba604SPiotr Pelplinski { 359742dba604SPiotr Pelplinski g_status = status; 359842dba604SPiotr Pelplinski g_histogram = histogram; 359942dba604SPiotr Pelplinski } 360042dba604SPiotr Pelplinski 360142dba604SPiotr Pelplinski static void 360242dba604SPiotr Pelplinski histogram_io_count(void *ctx, uint64_t start, uint64_t end, uint64_t count, 360342dba604SPiotr Pelplinski uint64_t total, uint64_t so_far) 360442dba604SPiotr Pelplinski { 360542dba604SPiotr Pelplinski g_count += count; 360642dba604SPiotr Pelplinski } 360742dba604SPiotr Pelplinski 360842dba604SPiotr Pelplinski static void 3609f192c11bSRichael Zhuang histogram_channel_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) 3610f192c11bSRichael Zhuang { 3611f192c11bSRichael Zhuang spdk_histogram_data_fn cb_fn = cb_arg; 3612f192c11bSRichael Zhuang 3613f192c11bSRichael Zhuang g_status = status; 3614f192c11bSRichael Zhuang 3615f192c11bSRichael Zhuang if (status == 0) { 3616f192c11bSRichael Zhuang spdk_histogram_data_iterate(histogram, cb_fn, NULL); 3617f192c11bSRichael Zhuang } 3618f192c11bSRichael Zhuang } 3619f192c11bSRichael Zhuang 3620f192c11bSRichael Zhuang static void 362142dba604SPiotr Pelplinski bdev_histograms(void) 362242dba604SPiotr Pelplinski { 362342dba604SPiotr Pelplinski struct spdk_bdev *bdev; 3624dae8e892STomasz Zawadzki struct spdk_bdev_desc *desc = NULL; 362542dba604SPiotr Pelplinski struct spdk_io_channel *ch; 362642dba604SPiotr Pelplinski struct spdk_histogram_data *histogram; 362742dba604SPiotr Pelplinski uint8_t buf[4096]; 362842dba604SPiotr Pelplinski int rc; 362942dba604SPiotr Pelplinski 3630107741fcSKonrad Sztyber ut_init_bdev(NULL); 363142dba604SPiotr Pelplinski 363242dba604SPiotr Pelplinski bdev = allocate_bdev("bdev"); 363342dba604SPiotr Pelplinski 363475dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 363542dba604SPiotr Pelplinski CU_ASSERT(rc == 0); 363642dba604SPiotr Pelplinski CU_ASSERT(desc != NULL); 363775dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 363842dba604SPiotr Pelplinski 363942dba604SPiotr Pelplinski ch = spdk_bdev_get_io_channel(desc); 364042dba604SPiotr Pelplinski CU_ASSERT(ch != NULL); 364142dba604SPiotr Pelplinski 364242dba604SPiotr Pelplinski /* Enable histogram */ 364342dba604SPiotr Pelplinski g_status = -1; 364442dba604SPiotr Pelplinski spdk_bdev_histogram_enable(bdev, histogram_status_cb, NULL, true); 364542dba604SPiotr Pelplinski poll_threads(); 364642dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 364742dba604SPiotr Pelplinski CU_ASSERT(bdev->internal.histogram_enabled == true); 364842dba604SPiotr Pelplinski 364942dba604SPiotr Pelplinski /* Allocate histogram */ 365042dba604SPiotr Pelplinski histogram = spdk_histogram_data_alloc(); 365142dba604SPiotr Pelplinski SPDK_CU_ASSERT_FATAL(histogram != NULL); 365242dba604SPiotr Pelplinski 365342dba604SPiotr Pelplinski /* Check if histogram is zeroed */ 365442dba604SPiotr Pelplinski spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); 365542dba604SPiotr Pelplinski poll_threads(); 365642dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 365742dba604SPiotr Pelplinski SPDK_CU_ASSERT_FATAL(g_histogram != NULL); 365842dba604SPiotr Pelplinski 365942dba604SPiotr Pelplinski g_count = 0; 366042dba604SPiotr Pelplinski spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); 366142dba604SPiotr Pelplinski 366242dba604SPiotr Pelplinski CU_ASSERT(g_count == 0); 366342dba604SPiotr Pelplinski 36641d94a0b0SJim Harris rc = spdk_bdev_write_blocks(desc, ch, buf, 0, 1, io_done, NULL); 366542dba604SPiotr Pelplinski CU_ASSERT(rc == 0); 366642dba604SPiotr Pelplinski 366742dba604SPiotr Pelplinski spdk_delay_us(10); 366842dba604SPiotr Pelplinski stub_complete_io(1); 366942dba604SPiotr Pelplinski poll_threads(); 367042dba604SPiotr Pelplinski 36711d94a0b0SJim Harris rc = spdk_bdev_read_blocks(desc, ch, buf, 0, 1, io_done, NULL); 367242dba604SPiotr Pelplinski CU_ASSERT(rc == 0); 367342dba604SPiotr Pelplinski 367442dba604SPiotr Pelplinski spdk_delay_us(10); 367542dba604SPiotr Pelplinski stub_complete_io(1); 367642dba604SPiotr Pelplinski poll_threads(); 367742dba604SPiotr Pelplinski 367842dba604SPiotr Pelplinski /* Check if histogram gathered data from all I/O channels */ 367942dba604SPiotr Pelplinski g_histogram = NULL; 368042dba604SPiotr Pelplinski spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); 368142dba604SPiotr Pelplinski poll_threads(); 368242dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 368342dba604SPiotr Pelplinski CU_ASSERT(bdev->internal.histogram_enabled == true); 368442dba604SPiotr Pelplinski SPDK_CU_ASSERT_FATAL(g_histogram != NULL); 368542dba604SPiotr Pelplinski 368642dba604SPiotr Pelplinski g_count = 0; 368742dba604SPiotr Pelplinski spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); 368842dba604SPiotr Pelplinski CU_ASSERT(g_count == 2); 368942dba604SPiotr Pelplinski 3690f192c11bSRichael Zhuang g_count = 0; 369136f8f8daSRichael Zhuang spdk_bdev_channel_get_histogram(ch, histogram_channel_data_cb, histogram_io_count); 3692f192c11bSRichael Zhuang CU_ASSERT(g_status == 0); 3693f192c11bSRichael Zhuang CU_ASSERT(g_count == 2); 3694f192c11bSRichael Zhuang 369542dba604SPiotr Pelplinski /* Disable histogram */ 369642dba604SPiotr Pelplinski spdk_bdev_histogram_enable(bdev, histogram_status_cb, NULL, false); 369742dba604SPiotr Pelplinski poll_threads(); 369842dba604SPiotr Pelplinski CU_ASSERT(g_status == 0); 369942dba604SPiotr Pelplinski CU_ASSERT(bdev->internal.histogram_enabled == false); 370042dba604SPiotr Pelplinski 370142dba604SPiotr Pelplinski /* Try to run histogram commands on disabled bdev */ 370242dba604SPiotr Pelplinski spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); 370342dba604SPiotr Pelplinski poll_threads(); 370442dba604SPiotr Pelplinski CU_ASSERT(g_status == -EFAULT); 370542dba604SPiotr Pelplinski 370636f8f8daSRichael Zhuang spdk_bdev_channel_get_histogram(ch, histogram_channel_data_cb, NULL); 3707f192c11bSRichael Zhuang CU_ASSERT(g_status == -EFAULT); 3708f192c11bSRichael Zhuang 370926f6c2a0SDarek Stojaczyk spdk_histogram_data_free(histogram); 371042dba604SPiotr Pelplinski spdk_put_io_channel(ch); 371142dba604SPiotr Pelplinski spdk_bdev_close(desc); 371242dba604SPiotr Pelplinski free_bdev(bdev); 3713107741fcSKonrad Sztyber ut_fini_bdev(); 371442dba604SPiotr Pelplinski } 371542dba604SPiotr Pelplinski 3716e2918289SKonrad Sztyber static void 37173eda8bf6SMaciej Szwed _bdev_compare(bool emulated) 371877183c9cSMaciej Szwed { 371977183c9cSMaciej Szwed struct spdk_bdev *bdev; 372077183c9cSMaciej Szwed struct spdk_bdev_desc *desc = NULL; 372177183c9cSMaciej Szwed struct spdk_io_channel *ioch; 372277183c9cSMaciej Szwed struct ut_expected_io *expected_io; 372377183c9cSMaciej Szwed uint64_t offset, num_blocks; 372477183c9cSMaciej Szwed uint32_t num_completed; 372577183c9cSMaciej Szwed char aa_buf[512]; 372677183c9cSMaciej Szwed char bb_buf[512]; 372777183c9cSMaciej Szwed struct iovec compare_iov; 37280bd6b7f2SJonas Pfefferle uint8_t expected_io_type; 372977183c9cSMaciej Szwed int rc; 373077183c9cSMaciej Szwed 37313eda8bf6SMaciej Szwed if (emulated) { 37320bd6b7f2SJonas Pfefferle expected_io_type = SPDK_BDEV_IO_TYPE_READ; 37333eda8bf6SMaciej Szwed } else { 37340bd6b7f2SJonas Pfefferle expected_io_type = SPDK_BDEV_IO_TYPE_COMPARE; 37353eda8bf6SMaciej Szwed } 37363eda8bf6SMaciej Szwed 373777183c9cSMaciej Szwed memset(aa_buf, 0xaa, sizeof(aa_buf)); 373877183c9cSMaciej Szwed memset(bb_buf, 0xbb, sizeof(bb_buf)); 373977183c9cSMaciej Szwed 37403eda8bf6SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = !emulated; 3741bee042e4SMaciej Szwed 3742107741fcSKonrad Sztyber ut_init_bdev(NULL); 374377183c9cSMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 374477183c9cSMaciej Szwed bdev = allocate_bdev("bdev"); 374577183c9cSMaciej Szwed 374675dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 374777183c9cSMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 374877183c9cSMaciej Szwed SPDK_CU_ASSERT_FATAL(desc != NULL); 374975dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 375077183c9cSMaciej Szwed ioch = spdk_bdev_get_io_channel(desc); 375177183c9cSMaciej Szwed SPDK_CU_ASSERT_FATAL(ioch != NULL); 375277183c9cSMaciej Szwed 375377183c9cSMaciej Szwed fn_table.submit_request = stub_submit_request_get_buf; 375477183c9cSMaciej Szwed g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 375577183c9cSMaciej Szwed 375677183c9cSMaciej Szwed offset = 50; 375777183c9cSMaciej Szwed num_blocks = 1; 375877183c9cSMaciej Szwed compare_iov.iov_base = aa_buf; 375977183c9cSMaciej Szwed compare_iov.iov_len = sizeof(aa_buf); 376077183c9cSMaciej Szwed 3761f46d3a24SKanKuo /* 1. successful comparev */ 37620bd6b7f2SJonas Pfefferle expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 376377183c9cSMaciej Szwed TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 376477183c9cSMaciej Szwed 376577183c9cSMaciej Szwed g_io_done = false; 376677183c9cSMaciej Szwed g_compare_read_buf = aa_buf; 376777183c9cSMaciej Szwed g_compare_read_buf_len = sizeof(aa_buf); 376877183c9cSMaciej Szwed rc = spdk_bdev_comparev_blocks(desc, ioch, &compare_iov, 1, offset, num_blocks, io_done, NULL); 376977183c9cSMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 377077183c9cSMaciej Szwed num_completed = stub_complete_io(1); 377177183c9cSMaciej Szwed CU_ASSERT_EQUAL(num_completed, 1); 377277183c9cSMaciej Szwed CU_ASSERT(g_io_done == true); 377377183c9cSMaciej Szwed CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 377477183c9cSMaciej Szwed 3775f46d3a24SKanKuo /* 2. miscompare comparev */ 37760bd6b7f2SJonas Pfefferle expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 377777183c9cSMaciej Szwed TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 377877183c9cSMaciej Szwed 377977183c9cSMaciej Szwed g_io_done = false; 378077183c9cSMaciej Szwed g_compare_read_buf = bb_buf; 378177183c9cSMaciej Szwed g_compare_read_buf_len = sizeof(bb_buf); 378277183c9cSMaciej Szwed rc = spdk_bdev_comparev_blocks(desc, ioch, &compare_iov, 1, offset, num_blocks, io_done, NULL); 378377183c9cSMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 378477183c9cSMaciej Szwed num_completed = stub_complete_io(1); 378577183c9cSMaciej Szwed CU_ASSERT_EQUAL(num_completed, 1); 378677183c9cSMaciej Szwed CU_ASSERT(g_io_done == true); 378777183c9cSMaciej Szwed CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 378877183c9cSMaciej Szwed 3789f46d3a24SKanKuo /* 3. successful compare */ 3790f46d3a24SKanKuo g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 3791f46d3a24SKanKuo expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 3792f46d3a24SKanKuo TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 3793f46d3a24SKanKuo 3794f46d3a24SKanKuo g_io_done = false; 3795f46d3a24SKanKuo g_compare_read_buf = aa_buf; 3796f46d3a24SKanKuo g_compare_read_buf_len = sizeof(aa_buf); 3797f46d3a24SKanKuo rc = spdk_bdev_compare_blocks(desc, ioch, aa_buf, offset, num_blocks, io_done, NULL); 3798f46d3a24SKanKuo CU_ASSERT_EQUAL(rc, 0); 3799f46d3a24SKanKuo num_completed = stub_complete_io(1); 3800f46d3a24SKanKuo CU_ASSERT_EQUAL(num_completed, 1); 3801f46d3a24SKanKuo CU_ASSERT(g_io_done == true); 3802f46d3a24SKanKuo CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 3803f46d3a24SKanKuo 3804f46d3a24SKanKuo /* 4. miscompare compare */ 3805f46d3a24SKanKuo expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 3806f46d3a24SKanKuo TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 3807f46d3a24SKanKuo 3808f46d3a24SKanKuo g_io_done = false; 3809f46d3a24SKanKuo g_compare_read_buf = bb_buf; 3810f46d3a24SKanKuo g_compare_read_buf_len = sizeof(bb_buf); 3811f46d3a24SKanKuo rc = spdk_bdev_compare_blocks(desc, ioch, aa_buf, offset, num_blocks, io_done, NULL); 3812f46d3a24SKanKuo CU_ASSERT_EQUAL(rc, 0); 3813f46d3a24SKanKuo num_completed = stub_complete_io(1); 3814f46d3a24SKanKuo CU_ASSERT_EQUAL(num_completed, 1); 3815f46d3a24SKanKuo CU_ASSERT(g_io_done == true); 3816f46d3a24SKanKuo CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 3817f46d3a24SKanKuo 381877183c9cSMaciej Szwed spdk_put_io_channel(ioch); 381977183c9cSMaciej Szwed spdk_bdev_close(desc); 382077183c9cSMaciej Szwed free_bdev(bdev); 382177183c9cSMaciej Szwed fn_table.submit_request = stub_submit_request; 3822107741fcSKonrad Sztyber ut_fini_bdev(); 382377183c9cSMaciej Szwed 3824bee042e4SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = true; 3825bee042e4SMaciej Szwed 382677183c9cSMaciej Szwed g_compare_read_buf = NULL; 382777183c9cSMaciej Szwed } 382877183c9cSMaciej Szwed 382977183c9cSMaciej Szwed static void 38300bd6b7f2SJonas Pfefferle _bdev_compare_with_md(bool emulated) 38310bd6b7f2SJonas Pfefferle { 38320bd6b7f2SJonas Pfefferle struct spdk_bdev *bdev; 38330bd6b7f2SJonas Pfefferle struct spdk_bdev_desc *desc = NULL; 38340bd6b7f2SJonas Pfefferle struct spdk_io_channel *ioch; 38350bd6b7f2SJonas Pfefferle struct ut_expected_io *expected_io; 38360bd6b7f2SJonas Pfefferle uint64_t offset, num_blocks; 38370bd6b7f2SJonas Pfefferle uint32_t num_completed; 38380bd6b7f2SJonas Pfefferle char buf[1024 + 16 /* 2 * blocklen + 2 * mdlen */]; 38390bd6b7f2SJonas Pfefferle char buf_interleaved_miscompare[1024 + 16 /* 2 * blocklen + 2 * mdlen */]; 38400bd6b7f2SJonas Pfefferle char buf_miscompare[1024 /* 2 * blocklen */]; 38410bd6b7f2SJonas Pfefferle char md_buf[16]; 38420bd6b7f2SJonas Pfefferle char md_buf_miscompare[16]; 38430bd6b7f2SJonas Pfefferle struct iovec compare_iov; 38440bd6b7f2SJonas Pfefferle uint8_t expected_io_type; 38450bd6b7f2SJonas Pfefferle int rc; 38460bd6b7f2SJonas Pfefferle 38470bd6b7f2SJonas Pfefferle if (emulated) { 38480bd6b7f2SJonas Pfefferle expected_io_type = SPDK_BDEV_IO_TYPE_READ; 38490bd6b7f2SJonas Pfefferle } else { 38500bd6b7f2SJonas Pfefferle expected_io_type = SPDK_BDEV_IO_TYPE_COMPARE; 38510bd6b7f2SJonas Pfefferle } 38520bd6b7f2SJonas Pfefferle 38530bd6b7f2SJonas Pfefferle memset(buf, 0xaa, sizeof(buf)); 38540bd6b7f2SJonas Pfefferle memset(buf_interleaved_miscompare, 0xaa, sizeof(buf_interleaved_miscompare)); 38550bd6b7f2SJonas Pfefferle /* make last md different */ 38560bd6b7f2SJonas Pfefferle memset(buf_interleaved_miscompare + 1024 + 8, 0xbb, 8); 38570bd6b7f2SJonas Pfefferle memset(buf_miscompare, 0xbb, sizeof(buf_miscompare)); 38580bd6b7f2SJonas Pfefferle memset(md_buf, 0xaa, 16); 38590bd6b7f2SJonas Pfefferle memset(md_buf_miscompare, 0xbb, 16); 38600bd6b7f2SJonas Pfefferle 38610bd6b7f2SJonas Pfefferle g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = !emulated; 38620bd6b7f2SJonas Pfefferle 3863107741fcSKonrad Sztyber ut_init_bdev(NULL); 38640bd6b7f2SJonas Pfefferle fn_table.submit_request = stub_submit_request_get_buf; 38650bd6b7f2SJonas Pfefferle bdev = allocate_bdev("bdev"); 38660bd6b7f2SJonas Pfefferle 38670bd6b7f2SJonas Pfefferle rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 38680bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(rc, 0); 38690bd6b7f2SJonas Pfefferle SPDK_CU_ASSERT_FATAL(desc != NULL); 38700bd6b7f2SJonas Pfefferle CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 38710bd6b7f2SJonas Pfefferle ioch = spdk_bdev_get_io_channel(desc); 38720bd6b7f2SJonas Pfefferle SPDK_CU_ASSERT_FATAL(ioch != NULL); 38730bd6b7f2SJonas Pfefferle 38740bd6b7f2SJonas Pfefferle fn_table.submit_request = stub_submit_request_get_buf; 38750bd6b7f2SJonas Pfefferle g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 38760bd6b7f2SJonas Pfefferle 38770bd6b7f2SJonas Pfefferle offset = 50; 38780bd6b7f2SJonas Pfefferle num_blocks = 2; 38790bd6b7f2SJonas Pfefferle 38800bd6b7f2SJonas Pfefferle /* interleaved md & data */ 38810bd6b7f2SJonas Pfefferle bdev->md_interleave = true; 38820bd6b7f2SJonas Pfefferle bdev->md_len = 8; 38830bd6b7f2SJonas Pfefferle bdev->blocklen = 512 + 8; 38840bd6b7f2SJonas Pfefferle compare_iov.iov_base = buf; 38850bd6b7f2SJonas Pfefferle compare_iov.iov_len = sizeof(buf); 38860bd6b7f2SJonas Pfefferle 38870bd6b7f2SJonas Pfefferle /* 1. successful compare with md interleaved */ 38880bd6b7f2SJonas Pfefferle expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 38890bd6b7f2SJonas Pfefferle TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 38900bd6b7f2SJonas Pfefferle 38910bd6b7f2SJonas Pfefferle g_io_done = false; 38920bd6b7f2SJonas Pfefferle g_compare_read_buf = buf; 38930bd6b7f2SJonas Pfefferle g_compare_read_buf_len = sizeof(buf); 38940bd6b7f2SJonas Pfefferle rc = spdk_bdev_comparev_blocks(desc, ioch, &compare_iov, 1, offset, num_blocks, io_done, NULL); 38950bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(rc, 0); 38960bd6b7f2SJonas Pfefferle num_completed = stub_complete_io(1); 38970bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(num_completed, 1); 38980bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_done == true); 38990bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 39000bd6b7f2SJonas Pfefferle 39010bd6b7f2SJonas Pfefferle /* 2. miscompare with md interleaved */ 39020bd6b7f2SJonas Pfefferle expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 39030bd6b7f2SJonas Pfefferle TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 39040bd6b7f2SJonas Pfefferle 39050bd6b7f2SJonas Pfefferle g_io_done = false; 39060bd6b7f2SJonas Pfefferle g_compare_read_buf = buf_interleaved_miscompare; 39070bd6b7f2SJonas Pfefferle g_compare_read_buf_len = sizeof(buf_interleaved_miscompare); 39080bd6b7f2SJonas Pfefferle rc = spdk_bdev_comparev_blocks(desc, ioch, &compare_iov, 1, offset, num_blocks, io_done, NULL); 39090bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(rc, 0); 39100bd6b7f2SJonas Pfefferle num_completed = stub_complete_io(1); 39110bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(num_completed, 1); 39120bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_done == true); 39130bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 39140bd6b7f2SJonas Pfefferle 39150bd6b7f2SJonas Pfefferle /* Separate data & md buffers */ 39160bd6b7f2SJonas Pfefferle bdev->md_interleave = false; 39170bd6b7f2SJonas Pfefferle bdev->blocklen = 512; 39180bd6b7f2SJonas Pfefferle compare_iov.iov_base = buf; 39190bd6b7f2SJonas Pfefferle compare_iov.iov_len = 1024; 39200bd6b7f2SJonas Pfefferle 39210bd6b7f2SJonas Pfefferle /* 3. successful compare with md separated */ 39220bd6b7f2SJonas Pfefferle expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 39230bd6b7f2SJonas Pfefferle TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 39240bd6b7f2SJonas Pfefferle 39250bd6b7f2SJonas Pfefferle g_io_done = false; 39260bd6b7f2SJonas Pfefferle g_compare_read_buf = buf; 39270bd6b7f2SJonas Pfefferle g_compare_read_buf_len = 1024; 39280bd6b7f2SJonas Pfefferle g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 39290bd6b7f2SJonas Pfefferle g_compare_md_buf = md_buf; 39300bd6b7f2SJonas Pfefferle rc = spdk_bdev_comparev_blocks_with_md(desc, ioch, &compare_iov, 1, md_buf, 39310bd6b7f2SJonas Pfefferle offset, num_blocks, io_done, NULL); 39320bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(rc, 0); 39330bd6b7f2SJonas Pfefferle num_completed = stub_complete_io(1); 39340bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(num_completed, 1); 39350bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_done == true); 39360bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 39370bd6b7f2SJonas Pfefferle 39380bd6b7f2SJonas Pfefferle /* 4. miscompare with md separated where md buf is different */ 39390bd6b7f2SJonas Pfefferle expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 39400bd6b7f2SJonas Pfefferle TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 39410bd6b7f2SJonas Pfefferle 39420bd6b7f2SJonas Pfefferle g_io_done = false; 39430bd6b7f2SJonas Pfefferle g_compare_read_buf = buf; 39440bd6b7f2SJonas Pfefferle g_compare_read_buf_len = 1024; 39450bd6b7f2SJonas Pfefferle g_compare_md_buf = md_buf_miscompare; 39460bd6b7f2SJonas Pfefferle rc = spdk_bdev_comparev_blocks_with_md(desc, ioch, &compare_iov, 1, md_buf, 39470bd6b7f2SJonas Pfefferle offset, num_blocks, io_done, NULL); 39480bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(rc, 0); 39490bd6b7f2SJonas Pfefferle num_completed = stub_complete_io(1); 39500bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(num_completed, 1); 39510bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_done == true); 39520bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 39530bd6b7f2SJonas Pfefferle 39540bd6b7f2SJonas Pfefferle /* 5. miscompare with md separated where buf is different */ 39550bd6b7f2SJonas Pfefferle expected_io = ut_alloc_expected_io(expected_io_type, offset, num_blocks, 0); 39560bd6b7f2SJonas Pfefferle TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 39570bd6b7f2SJonas Pfefferle 39580bd6b7f2SJonas Pfefferle g_io_done = false; 39590bd6b7f2SJonas Pfefferle g_compare_read_buf = buf_miscompare; 39600bd6b7f2SJonas Pfefferle g_compare_read_buf_len = sizeof(buf_miscompare); 39610bd6b7f2SJonas Pfefferle g_compare_md_buf = md_buf; 39620bd6b7f2SJonas Pfefferle rc = spdk_bdev_comparev_blocks_with_md(desc, ioch, &compare_iov, 1, md_buf, 39630bd6b7f2SJonas Pfefferle offset, num_blocks, io_done, NULL); 39640bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(rc, 0); 39650bd6b7f2SJonas Pfefferle num_completed = stub_complete_io(1); 39660bd6b7f2SJonas Pfefferle CU_ASSERT_EQUAL(num_completed, 1); 39670bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_done == true); 39680bd6b7f2SJonas Pfefferle CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 39690bd6b7f2SJonas Pfefferle 39700bd6b7f2SJonas Pfefferle bdev->md_len = 0; 39710bd6b7f2SJonas Pfefferle g_compare_md_buf = NULL; 39720bd6b7f2SJonas Pfefferle 39730bd6b7f2SJonas Pfefferle spdk_put_io_channel(ioch); 39740bd6b7f2SJonas Pfefferle spdk_bdev_close(desc); 39750bd6b7f2SJonas Pfefferle free_bdev(bdev); 39760bd6b7f2SJonas Pfefferle fn_table.submit_request = stub_submit_request; 3977107741fcSKonrad Sztyber ut_fini_bdev(); 39780bd6b7f2SJonas Pfefferle 39790bd6b7f2SJonas Pfefferle g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = true; 39800bd6b7f2SJonas Pfefferle 39810bd6b7f2SJonas Pfefferle g_compare_read_buf = NULL; 39820bd6b7f2SJonas Pfefferle } 39830bd6b7f2SJonas Pfefferle 39840bd6b7f2SJonas Pfefferle static void 39853eda8bf6SMaciej Szwed bdev_compare(void) 39863eda8bf6SMaciej Szwed { 3987ca0eeaabSMaciej Szwed _bdev_compare(false); 39880bd6b7f2SJonas Pfefferle _bdev_compare_with_md(false); 39890bd6b7f2SJonas Pfefferle } 39900bd6b7f2SJonas Pfefferle 39910bd6b7f2SJonas Pfefferle static void 39920bd6b7f2SJonas Pfefferle bdev_compare_emulated(void) 39930bd6b7f2SJonas Pfefferle { 39940bd6b7f2SJonas Pfefferle _bdev_compare(true); 39950bd6b7f2SJonas Pfefferle _bdev_compare_with_md(true); 39963eda8bf6SMaciej Szwed } 39973eda8bf6SMaciej Szwed 39983eda8bf6SMaciej Szwed static void 3999ae43c81aSJim Harris bdev_compare_and_write(void) 4000ae43c81aSJim Harris { 4001ae43c81aSJim Harris struct spdk_bdev *bdev; 4002ae43c81aSJim Harris struct spdk_bdev_desc *desc = NULL; 4003ae43c81aSJim Harris struct spdk_io_channel *ioch; 4004ae43c81aSJim Harris struct ut_expected_io *expected_io; 4005ae43c81aSJim Harris uint64_t offset, num_blocks; 4006ae43c81aSJim Harris uint32_t num_completed; 4007ae43c81aSJim Harris char aa_buf[512]; 4008ae43c81aSJim Harris char bb_buf[512]; 4009ae43c81aSJim Harris char cc_buf[512]; 4010ae43c81aSJim Harris char write_buf[512]; 4011ae43c81aSJim Harris struct iovec compare_iov; 4012ae43c81aSJim Harris struct iovec write_iov; 4013ae43c81aSJim Harris int rc; 4014ae43c81aSJim Harris 4015ae43c81aSJim Harris memset(aa_buf, 0xaa, sizeof(aa_buf)); 4016ae43c81aSJim Harris memset(bb_buf, 0xbb, sizeof(bb_buf)); 4017ae43c81aSJim Harris memset(cc_buf, 0xcc, sizeof(cc_buf)); 4018ae43c81aSJim Harris 4019bee042e4SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = false; 4020bee042e4SMaciej Szwed 4021107741fcSKonrad Sztyber ut_init_bdev(NULL); 4022ae43c81aSJim Harris fn_table.submit_request = stub_submit_request_get_buf; 4023ae43c81aSJim Harris bdev = allocate_bdev("bdev"); 4024ae43c81aSJim Harris 402575dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 4026ae43c81aSJim Harris CU_ASSERT_EQUAL(rc, 0); 4027ae43c81aSJim Harris SPDK_CU_ASSERT_FATAL(desc != NULL); 402875dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 4029ae43c81aSJim Harris ioch = spdk_bdev_get_io_channel(desc); 4030ae43c81aSJim Harris SPDK_CU_ASSERT_FATAL(ioch != NULL); 4031ae43c81aSJim Harris 4032ae43c81aSJim Harris fn_table.submit_request = stub_submit_request_get_buf; 4033ae43c81aSJim Harris g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 4034ae43c81aSJim Harris 4035ae43c81aSJim Harris offset = 50; 4036ae43c81aSJim Harris num_blocks = 1; 4037ae43c81aSJim Harris compare_iov.iov_base = aa_buf; 4038ae43c81aSJim Harris compare_iov.iov_len = sizeof(aa_buf); 4039ae43c81aSJim Harris write_iov.iov_base = bb_buf; 4040ae43c81aSJim Harris write_iov.iov_len = sizeof(bb_buf); 4041ae43c81aSJim Harris 4042ae43c81aSJim Harris expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, offset, num_blocks, 0); 4043ae43c81aSJim Harris TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 4044ae43c81aSJim Harris expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, offset, num_blocks, 0); 4045ae43c81aSJim Harris TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 4046ae43c81aSJim Harris 4047ae43c81aSJim Harris g_io_done = false; 4048ae43c81aSJim Harris g_compare_read_buf = aa_buf; 4049ae43c81aSJim Harris g_compare_read_buf_len = sizeof(aa_buf); 4050ae43c81aSJim Harris memset(write_buf, 0, sizeof(write_buf)); 4051ae43c81aSJim Harris g_compare_write_buf = write_buf; 4052ae43c81aSJim Harris g_compare_write_buf_len = sizeof(write_buf); 4053ae43c81aSJim Harris rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1, 4054ae43c81aSJim Harris offset, num_blocks, io_done, NULL); 4055a83644feSMaciej Szwed /* Trigger range locking */ 4056a83644feSMaciej Szwed poll_threads(); 4057ae43c81aSJim Harris CU_ASSERT_EQUAL(rc, 0); 4058ae43c81aSJim Harris num_completed = stub_complete_io(1); 4059ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 1); 4060ae43c81aSJim Harris CU_ASSERT(g_io_done == false); 4061ae43c81aSJim Harris num_completed = stub_complete_io(1); 4062a83644feSMaciej Szwed /* Trigger range unlocking */ 4063a83644feSMaciej Szwed poll_threads(); 4064ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 1); 4065ae43c81aSJim Harris CU_ASSERT(g_io_done == true); 4066ae43c81aSJim Harris CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 4067ae43c81aSJim Harris CU_ASSERT(memcmp(write_buf, bb_buf, sizeof(write_buf)) == 0); 4068ae43c81aSJim Harris 4069442e13c0SJonas Pfefferle /* Test miscompare */ 4070ae43c81aSJim Harris expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, offset, num_blocks, 0); 4071ae43c81aSJim Harris TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 4072ae43c81aSJim Harris 4073ae43c81aSJim Harris g_io_done = false; 4074ae43c81aSJim Harris g_compare_read_buf = cc_buf; 4075ae43c81aSJim Harris g_compare_read_buf_len = sizeof(cc_buf); 4076ae43c81aSJim Harris memset(write_buf, 0, sizeof(write_buf)); 4077ae43c81aSJim Harris g_compare_write_buf = write_buf; 4078ae43c81aSJim Harris g_compare_write_buf_len = sizeof(write_buf); 4079ae43c81aSJim Harris rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1, 4080ae43c81aSJim Harris offset, num_blocks, io_done, NULL); 4081a83644feSMaciej Szwed /* Trigger range locking */ 4082a83644feSMaciej Szwed poll_threads(); 4083ae43c81aSJim Harris CU_ASSERT_EQUAL(rc, 0); 4084ae43c81aSJim Harris num_completed = stub_complete_io(1); 4085a83644feSMaciej Szwed /* Trigger range unlocking earlier because we expect error here */ 4086a83644feSMaciej Szwed poll_threads(); 4087ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 1); 4088ae43c81aSJim Harris CU_ASSERT(g_io_done == true); 4089ae43c81aSJim Harris CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE); 4090ae43c81aSJim Harris num_completed = stub_complete_io(1); 4091ae43c81aSJim Harris CU_ASSERT_EQUAL(num_completed, 0); 4092ae43c81aSJim Harris 4093ae43c81aSJim Harris spdk_put_io_channel(ioch); 4094ae43c81aSJim Harris spdk_bdev_close(desc); 4095ae43c81aSJim Harris free_bdev(bdev); 4096ae43c81aSJim Harris fn_table.submit_request = stub_submit_request; 4097107741fcSKonrad Sztyber ut_fini_bdev(); 4098ae43c81aSJim Harris 4099bee042e4SMaciej Szwed g_io_types_supported[SPDK_BDEV_IO_TYPE_COMPARE] = true; 4100bee042e4SMaciej Szwed 4101ae43c81aSJim Harris g_compare_read_buf = NULL; 4102ae43c81aSJim Harris g_compare_write_buf = NULL; 4103ae43c81aSJim Harris } 4104ae43c81aSJim Harris 4105ae43c81aSJim Harris static void 4106e2918289SKonrad Sztyber bdev_write_zeroes(void) 4107e2918289SKonrad Sztyber { 4108e2918289SKonrad Sztyber struct spdk_bdev *bdev; 4109e2918289SKonrad Sztyber struct spdk_bdev_desc *desc = NULL; 4110e2918289SKonrad Sztyber struct spdk_io_channel *ioch; 4111e2918289SKonrad Sztyber struct ut_expected_io *expected_io; 4112e2918289SKonrad Sztyber uint64_t offset, num_io_blocks, num_blocks; 4113e2918289SKonrad Sztyber uint32_t num_completed, num_requests; 4114e2918289SKonrad Sztyber int rc; 4115e2918289SKonrad Sztyber 4116107741fcSKonrad Sztyber ut_init_bdev(NULL); 4117e2918289SKonrad Sztyber bdev = allocate_bdev("bdev"); 4118e2918289SKonrad Sztyber 411975dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 4120e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 4121e2918289SKonrad Sztyber SPDK_CU_ASSERT_FATAL(desc != NULL); 412275dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 4123e2918289SKonrad Sztyber ioch = spdk_bdev_get_io_channel(desc); 4124e2918289SKonrad Sztyber SPDK_CU_ASSERT_FATAL(ioch != NULL); 4125e2918289SKonrad Sztyber 4126e2918289SKonrad Sztyber fn_table.submit_request = stub_submit_request; 4127e2918289SKonrad Sztyber g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 4128e2918289SKonrad Sztyber 4129e2918289SKonrad Sztyber /* First test that if the bdev supports write_zeroes, the request won't be split */ 4130e2918289SKonrad Sztyber bdev->md_len = 0; 4131e2918289SKonrad Sztyber bdev->blocklen = 4096; 4132e2918289SKonrad Sztyber num_blocks = (ZERO_BUFFER_SIZE / bdev->blocklen) * 2; 4133e2918289SKonrad Sztyber 4134e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, 0, num_blocks, 0); 4135e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 4136e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 4137e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 4138e2918289SKonrad Sztyber num_completed = stub_complete_io(1); 4139e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, 1); 4140e2918289SKonrad Sztyber 4141e2918289SKonrad Sztyber /* Check that if write zeroes is not supported it'll be replaced by regular writes */ 4142e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, false); 4143af92c28bSShuhei Matsumoto bdev->max_write_zeroes = bdev_get_max_write(bdev, ZERO_BUFFER_SIZE); 4144e2918289SKonrad Sztyber num_io_blocks = ZERO_BUFFER_SIZE / bdev->blocklen; 4145e2918289SKonrad Sztyber num_requests = 2; 4146e2918289SKonrad Sztyber num_blocks = (ZERO_BUFFER_SIZE / bdev->blocklen) * num_requests; 4147e2918289SKonrad Sztyber 4148e2918289SKonrad Sztyber for (offset = 0; offset < num_requests; ++offset) { 4149e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 4150e2918289SKonrad Sztyber offset * num_io_blocks, num_io_blocks, 0); 4151e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 4152e2918289SKonrad Sztyber } 4153e2918289SKonrad Sztyber 4154e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 4155e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 4156e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 4157e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, num_requests); 4158e2918289SKonrad Sztyber 4159e2918289SKonrad Sztyber /* Check that the splitting is correct if bdev has interleaved metadata */ 4160e2918289SKonrad Sztyber bdev->md_interleave = true; 4161e2918289SKonrad Sztyber bdev->md_len = 64; 4162e2918289SKonrad Sztyber bdev->blocklen = 4096 + 64; 4163af92c28bSShuhei Matsumoto bdev->max_write_zeroes = bdev_get_max_write(bdev, ZERO_BUFFER_SIZE); 4164e2918289SKonrad Sztyber num_blocks = (ZERO_BUFFER_SIZE / bdev->blocklen) * 2; 4165e2918289SKonrad Sztyber 4166e2918289SKonrad Sztyber num_requests = offset = 0; 4167e2918289SKonrad Sztyber while (offset < num_blocks) { 4168e2918289SKonrad Sztyber num_io_blocks = spdk_min(ZERO_BUFFER_SIZE / bdev->blocklen, num_blocks - offset); 4169e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 4170e2918289SKonrad Sztyber offset, num_io_blocks, 0); 4171e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 4172e2918289SKonrad Sztyber offset += num_io_blocks; 4173e2918289SKonrad Sztyber num_requests++; 4174e2918289SKonrad Sztyber } 4175e2918289SKonrad Sztyber 4176e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 4177e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 4178e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 4179e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, num_requests); 4180e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 4181e2918289SKonrad Sztyber assert(num_completed == 0); 4182e2918289SKonrad Sztyber 4183e2918289SKonrad Sztyber /* Check the the same for separate metadata buffer */ 4184e2918289SKonrad Sztyber bdev->md_interleave = false; 4185e2918289SKonrad Sztyber bdev->md_len = 64; 4186e2918289SKonrad Sztyber bdev->blocklen = 4096; 4187af92c28bSShuhei Matsumoto bdev->max_write_zeroes = bdev_get_max_write(bdev, ZERO_BUFFER_SIZE); 4188e2918289SKonrad Sztyber 4189e2918289SKonrad Sztyber num_requests = offset = 0; 4190e2918289SKonrad Sztyber while (offset < num_blocks) { 4191e2918289SKonrad Sztyber num_io_blocks = spdk_min(ZERO_BUFFER_SIZE / (bdev->blocklen + bdev->md_len), num_blocks); 4192e2918289SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 4193e2918289SKonrad Sztyber offset, num_io_blocks, 0); 4194e2918289SKonrad Sztyber expected_io->md_buf = (char *)g_bdev_mgr.zero_buffer + num_io_blocks * bdev->blocklen; 4195e2918289SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 4196e2918289SKonrad Sztyber offset += num_io_blocks; 4197e2918289SKonrad Sztyber num_requests++; 4198e2918289SKonrad Sztyber } 4199e2918289SKonrad Sztyber 4200e2918289SKonrad Sztyber rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 4201e2918289SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 4202e2918289SKonrad Sztyber num_completed = stub_complete_io(num_requests); 4203e2918289SKonrad Sztyber CU_ASSERT_EQUAL(num_completed, num_requests); 4204e2918289SKonrad Sztyber 4205e2918289SKonrad Sztyber ut_enable_io_type(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, true); 4206e2918289SKonrad Sztyber spdk_put_io_channel(ioch); 4207e2918289SKonrad Sztyber spdk_bdev_close(desc); 4208e2918289SKonrad Sztyber free_bdev(bdev); 4209107741fcSKonrad Sztyber ut_fini_bdev(); 4210e2918289SKonrad Sztyber } 4211e2918289SKonrad Sztyber 4212c141bd94SMaciej Szwed static void 42136127461cSmatthewb bdev_zcopy_write(void) 42146127461cSmatthewb { 42156127461cSmatthewb struct spdk_bdev *bdev; 42166127461cSmatthewb struct spdk_bdev_desc *desc = NULL; 42176127461cSmatthewb struct spdk_io_channel *ioch; 42186127461cSmatthewb struct ut_expected_io *expected_io; 42196127461cSmatthewb uint64_t offset, num_blocks; 42206127461cSmatthewb uint32_t num_completed; 42216127461cSmatthewb char aa_buf[512]; 42226127461cSmatthewb struct iovec iov; 42236127461cSmatthewb int rc; 42246127461cSmatthewb const bool populate = false; 42256127461cSmatthewb const bool commit = true; 42266127461cSmatthewb 42276127461cSmatthewb memset(aa_buf, 0xaa, sizeof(aa_buf)); 42286127461cSmatthewb 4229107741fcSKonrad Sztyber ut_init_bdev(NULL); 42306127461cSmatthewb bdev = allocate_bdev("bdev"); 42316127461cSmatthewb 42326127461cSmatthewb rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 42336127461cSmatthewb CU_ASSERT_EQUAL(rc, 0); 42346127461cSmatthewb SPDK_CU_ASSERT_FATAL(desc != NULL); 42356127461cSmatthewb CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 42366127461cSmatthewb ioch = spdk_bdev_get_io_channel(desc); 42376127461cSmatthewb SPDK_CU_ASSERT_FATAL(ioch != NULL); 42386127461cSmatthewb 42396127461cSmatthewb g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 42406127461cSmatthewb 42416127461cSmatthewb offset = 50; 42426127461cSmatthewb num_blocks = 1; 42436127461cSmatthewb iov.iov_base = NULL; 42446127461cSmatthewb iov.iov_len = 0; 42456127461cSmatthewb 42466127461cSmatthewb g_zcopy_read_buf = (void *) 0x1122334455667788UL; 42476127461cSmatthewb g_zcopy_read_buf_len = (uint32_t) -1; 42486127461cSmatthewb /* Do a zcopy start for a write (populate=false) */ 42496127461cSmatthewb expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_ZCOPY, offset, num_blocks, 0); 42506127461cSmatthewb TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 42516127461cSmatthewb g_io_done = false; 42526127461cSmatthewb g_zcopy_write_buf = aa_buf; 42536127461cSmatthewb g_zcopy_write_buf_len = sizeof(aa_buf); 42546127461cSmatthewb g_zcopy_bdev_io = NULL; 42556127461cSmatthewb rc = spdk_bdev_zcopy_start(desc, ioch, &iov, 1, offset, num_blocks, populate, io_done, NULL); 42566127461cSmatthewb CU_ASSERT_EQUAL(rc, 0); 42576127461cSmatthewb num_completed = stub_complete_io(1); 42586127461cSmatthewb CU_ASSERT_EQUAL(num_completed, 1); 42596127461cSmatthewb CU_ASSERT(g_io_done == true); 42606127461cSmatthewb CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 42616127461cSmatthewb /* Check that the iov has been set up */ 42626127461cSmatthewb CU_ASSERT(iov.iov_base == g_zcopy_write_buf); 42636127461cSmatthewb CU_ASSERT(iov.iov_len == g_zcopy_write_buf_len); 42646127461cSmatthewb /* Check that the bdev_io has been saved */ 42656127461cSmatthewb CU_ASSERT(g_zcopy_bdev_io != NULL); 42666127461cSmatthewb /* Now do the zcopy end for a write (commit=true) */ 42676127461cSmatthewb g_io_done = false; 42686127461cSmatthewb expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_ZCOPY, offset, num_blocks, 0); 42696127461cSmatthewb TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 42706127461cSmatthewb rc = spdk_bdev_zcopy_end(g_zcopy_bdev_io, commit, io_done, NULL); 42716127461cSmatthewb CU_ASSERT_EQUAL(rc, 0); 42726127461cSmatthewb num_completed = stub_complete_io(1); 42736127461cSmatthewb CU_ASSERT_EQUAL(num_completed, 1); 42746127461cSmatthewb CU_ASSERT(g_io_done == true); 42756127461cSmatthewb CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 42766127461cSmatthewb /* Check the g_zcopy are reset by io_done */ 42776127461cSmatthewb CU_ASSERT(g_zcopy_write_buf == NULL); 42786127461cSmatthewb CU_ASSERT(g_zcopy_write_buf_len == 0); 42796127461cSmatthewb /* Check that io_done has freed the g_zcopy_bdev_io */ 42806127461cSmatthewb CU_ASSERT(g_zcopy_bdev_io == NULL); 42816127461cSmatthewb 42826127461cSmatthewb /* Check the zcopy read buffer has not been touched which 42836127461cSmatthewb * ensures that the correct buffers were used. 42846127461cSmatthewb */ 42856127461cSmatthewb CU_ASSERT(g_zcopy_read_buf == (void *) 0x1122334455667788UL); 42866127461cSmatthewb CU_ASSERT(g_zcopy_read_buf_len == (uint32_t) -1); 42876127461cSmatthewb 42886127461cSmatthewb spdk_put_io_channel(ioch); 42896127461cSmatthewb spdk_bdev_close(desc); 42906127461cSmatthewb free_bdev(bdev); 4291107741fcSKonrad Sztyber ut_fini_bdev(); 42926127461cSmatthewb } 42936127461cSmatthewb 42946127461cSmatthewb static void 42956127461cSmatthewb bdev_zcopy_read(void) 42966127461cSmatthewb { 42976127461cSmatthewb struct spdk_bdev *bdev; 42986127461cSmatthewb struct spdk_bdev_desc *desc = NULL; 42996127461cSmatthewb struct spdk_io_channel *ioch; 43006127461cSmatthewb struct ut_expected_io *expected_io; 43016127461cSmatthewb uint64_t offset, num_blocks; 43026127461cSmatthewb uint32_t num_completed; 43036127461cSmatthewb char aa_buf[512]; 43046127461cSmatthewb struct iovec iov; 43056127461cSmatthewb int rc; 43066127461cSmatthewb const bool populate = true; 43076127461cSmatthewb const bool commit = false; 43086127461cSmatthewb 43096127461cSmatthewb memset(aa_buf, 0xaa, sizeof(aa_buf)); 43106127461cSmatthewb 4311107741fcSKonrad Sztyber ut_init_bdev(NULL); 43126127461cSmatthewb bdev = allocate_bdev("bdev"); 43136127461cSmatthewb 43146127461cSmatthewb rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 43156127461cSmatthewb CU_ASSERT_EQUAL(rc, 0); 43166127461cSmatthewb SPDK_CU_ASSERT_FATAL(desc != NULL); 43176127461cSmatthewb CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 43186127461cSmatthewb ioch = spdk_bdev_get_io_channel(desc); 43196127461cSmatthewb SPDK_CU_ASSERT_FATAL(ioch != NULL); 43206127461cSmatthewb 43216127461cSmatthewb g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 43226127461cSmatthewb 43236127461cSmatthewb offset = 50; 43246127461cSmatthewb num_blocks = 1; 43256127461cSmatthewb iov.iov_base = NULL; 43266127461cSmatthewb iov.iov_len = 0; 43276127461cSmatthewb 43286127461cSmatthewb g_zcopy_write_buf = (void *) 0x1122334455667788UL; 43296127461cSmatthewb g_zcopy_write_buf_len = (uint32_t) -1; 43306127461cSmatthewb 43316127461cSmatthewb /* Do a zcopy start for a read (populate=true) */ 43326127461cSmatthewb expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_ZCOPY, offset, num_blocks, 0); 43336127461cSmatthewb TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 43346127461cSmatthewb g_io_done = false; 43356127461cSmatthewb g_zcopy_read_buf = aa_buf; 43366127461cSmatthewb g_zcopy_read_buf_len = sizeof(aa_buf); 43376127461cSmatthewb g_zcopy_bdev_io = NULL; 43386127461cSmatthewb rc = spdk_bdev_zcopy_start(desc, ioch, &iov, 1, offset, num_blocks, populate, io_done, NULL); 43396127461cSmatthewb CU_ASSERT_EQUAL(rc, 0); 43406127461cSmatthewb num_completed = stub_complete_io(1); 43416127461cSmatthewb CU_ASSERT_EQUAL(num_completed, 1); 43426127461cSmatthewb CU_ASSERT(g_io_done == true); 43436127461cSmatthewb CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 43446127461cSmatthewb /* Check that the iov has been set up */ 43456127461cSmatthewb CU_ASSERT(iov.iov_base == g_zcopy_read_buf); 43466127461cSmatthewb CU_ASSERT(iov.iov_len == g_zcopy_read_buf_len); 43476127461cSmatthewb /* Check that the bdev_io has been saved */ 43486127461cSmatthewb CU_ASSERT(g_zcopy_bdev_io != NULL); 43496127461cSmatthewb 43506127461cSmatthewb /* Now do the zcopy end for a read (commit=false) */ 43516127461cSmatthewb g_io_done = false; 43526127461cSmatthewb expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_ZCOPY, offset, num_blocks, 0); 43536127461cSmatthewb TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 43546127461cSmatthewb rc = spdk_bdev_zcopy_end(g_zcopy_bdev_io, commit, io_done, NULL); 43556127461cSmatthewb CU_ASSERT_EQUAL(rc, 0); 43566127461cSmatthewb num_completed = stub_complete_io(1); 43576127461cSmatthewb CU_ASSERT_EQUAL(num_completed, 1); 43586127461cSmatthewb CU_ASSERT(g_io_done == true); 43596127461cSmatthewb CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 43606127461cSmatthewb /* Check the g_zcopy are reset by io_done */ 43616127461cSmatthewb CU_ASSERT(g_zcopy_read_buf == NULL); 43626127461cSmatthewb CU_ASSERT(g_zcopy_read_buf_len == 0); 43636127461cSmatthewb /* Check that io_done has freed the g_zcopy_bdev_io */ 43646127461cSmatthewb CU_ASSERT(g_zcopy_bdev_io == NULL); 43656127461cSmatthewb 43666127461cSmatthewb /* Check the zcopy write buffer has not been touched which 43676127461cSmatthewb * ensures that the correct buffers were used. 43686127461cSmatthewb */ 43696127461cSmatthewb CU_ASSERT(g_zcopy_write_buf == (void *) 0x1122334455667788UL); 43706127461cSmatthewb CU_ASSERT(g_zcopy_write_buf_len == (uint32_t) -1); 43716127461cSmatthewb 43726127461cSmatthewb spdk_put_io_channel(ioch); 43736127461cSmatthewb spdk_bdev_close(desc); 43746127461cSmatthewb free_bdev(bdev); 4375107741fcSKonrad Sztyber ut_fini_bdev(); 43766127461cSmatthewb } 43776127461cSmatthewb 43786127461cSmatthewb static void 4379c141bd94SMaciej Szwed bdev_open_while_hotremove(void) 4380c141bd94SMaciej Szwed { 4381c141bd94SMaciej Szwed struct spdk_bdev *bdev; 4382c141bd94SMaciej Szwed struct spdk_bdev_desc *desc[2] = {}; 4383c141bd94SMaciej Szwed int rc; 4384c141bd94SMaciej Szwed 4385c141bd94SMaciej Szwed bdev = allocate_bdev("bdev"); 4386c141bd94SMaciej Szwed 438775dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", false, bdev_ut_event_cb, NULL, &desc[0]); 4388c141bd94SMaciej Szwed CU_ASSERT(rc == 0); 4389c141bd94SMaciej Szwed SPDK_CU_ASSERT_FATAL(desc[0] != NULL); 439075dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc[0])); 4391c141bd94SMaciej Szwed 4392c141bd94SMaciej Szwed spdk_bdev_unregister(bdev, NULL, NULL); 43937bcd316dSGangCao /* Bdev unregister is handled asynchronously. Poll thread to complete. */ 43947bcd316dSGangCao poll_threads(); 4395c141bd94SMaciej Szwed 439675dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev", false, bdev_ut_event_cb, NULL, &desc[1]); 4397c141bd94SMaciej Szwed CU_ASSERT(rc == -ENODEV); 4398c141bd94SMaciej Szwed SPDK_CU_ASSERT_FATAL(desc[1] == NULL); 4399c141bd94SMaciej Szwed 4400c141bd94SMaciej Szwed spdk_bdev_close(desc[0]); 4401c141bd94SMaciej Szwed free_bdev(bdev); 4402c141bd94SMaciej Szwed } 4403c141bd94SMaciej Szwed 440479ed1ba1SMaciej Szwed static void 440523975858SEvgeniy Kochetov bdev_close_while_hotremove(void) 440623975858SEvgeniy Kochetov { 440723975858SEvgeniy Kochetov struct spdk_bdev *bdev; 440823975858SEvgeniy Kochetov struct spdk_bdev_desc *desc = NULL; 440923975858SEvgeniy Kochetov int rc = 0; 441023975858SEvgeniy Kochetov 441123975858SEvgeniy Kochetov bdev = allocate_bdev("bdev"); 441223975858SEvgeniy Kochetov 441323975858SEvgeniy Kochetov rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb1, &desc, &desc); 441423975858SEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 441575dfecbbSShuhei Matsumoto SPDK_CU_ASSERT_FATAL(desc != NULL); 441675dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 441723975858SEvgeniy Kochetov 441823975858SEvgeniy Kochetov /* Simulate hot-unplug by unregistering bdev */ 441923975858SEvgeniy Kochetov g_event_type1 = 0xFF; 442023975858SEvgeniy Kochetov g_unregister_arg = NULL; 442123975858SEvgeniy Kochetov g_unregister_rc = -1; 442223975858SEvgeniy Kochetov spdk_bdev_unregister(bdev, bdev_unregister_cb, (void *)0x12345678); 442323975858SEvgeniy Kochetov /* Close device while remove event is in flight */ 442423975858SEvgeniy Kochetov spdk_bdev_close(desc); 442523975858SEvgeniy Kochetov 442623975858SEvgeniy Kochetov /* Ensure that unregister callback is delayed */ 442723975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_arg, NULL); 442823975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_rc, -1); 442923975858SEvgeniy Kochetov 443023975858SEvgeniy Kochetov poll_threads(); 443123975858SEvgeniy Kochetov 443223975858SEvgeniy Kochetov /* Event callback shall not be issued because device was closed */ 443323975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_event_type1, 0xFF); 443423975858SEvgeniy Kochetov /* Unregister callback is issued */ 443523975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_arg, (void *)0x12345678); 443623975858SEvgeniy Kochetov CU_ASSERT_EQUAL(g_unregister_rc, 0); 443723975858SEvgeniy Kochetov 443823975858SEvgeniy Kochetov free_bdev(bdev); 443923975858SEvgeniy Kochetov } 444023975858SEvgeniy Kochetov 444123975858SEvgeniy Kochetov static void 44426e17adcbSShuhei Matsumoto bdev_open_ext_test(void) 444379ed1ba1SMaciej Szwed { 444479ed1ba1SMaciej Szwed struct spdk_bdev *bdev; 444579ed1ba1SMaciej Szwed struct spdk_bdev_desc *desc1 = NULL; 444679ed1ba1SMaciej Szwed struct spdk_bdev_desc *desc2 = NULL; 444779ed1ba1SMaciej Szwed int rc = 0; 444879ed1ba1SMaciej Szwed 444979ed1ba1SMaciej Szwed bdev = allocate_bdev("bdev"); 445079ed1ba1SMaciej Szwed 445179ed1ba1SMaciej Szwed rc = spdk_bdev_open_ext("bdev", true, NULL, NULL, &desc1); 445279ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(rc, -EINVAL); 445379ed1ba1SMaciej Szwed 445479ed1ba1SMaciej Szwed rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb1, &desc1, &desc1); 445579ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 445679ed1ba1SMaciej Szwed 445779ed1ba1SMaciej Szwed rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb2, &desc2, &desc2); 445879ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(rc, 0); 445979ed1ba1SMaciej Szwed 446079ed1ba1SMaciej Szwed g_event_type1 = 0xFF; 446179ed1ba1SMaciej Szwed g_event_type2 = 0xFF; 446279ed1ba1SMaciej Szwed 446379ed1ba1SMaciej Szwed /* Simulate hot-unplug by unregistering bdev */ 446479ed1ba1SMaciej Szwed spdk_bdev_unregister(bdev, NULL, NULL); 446579ed1ba1SMaciej Szwed poll_threads(); 446679ed1ba1SMaciej Szwed 446779ed1ba1SMaciej Szwed /* Check if correct events have been triggered in event callback fn */ 446879ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(g_event_type1, SPDK_BDEV_EVENT_REMOVE); 446979ed1ba1SMaciej Szwed CU_ASSERT_EQUAL(g_event_type2, SPDK_BDEV_EVENT_REMOVE); 447079ed1ba1SMaciej Szwed 447179ed1ba1SMaciej Szwed free_bdev(bdev); 447279ed1ba1SMaciej Szwed poll_threads(); 447379ed1ba1SMaciej Szwed } 447479ed1ba1SMaciej Szwed 44757bcd316dSGangCao static void 44767bcd316dSGangCao bdev_open_ext_unregister(void) 44777bcd316dSGangCao { 44787bcd316dSGangCao struct spdk_bdev *bdev; 44797bcd316dSGangCao struct spdk_bdev_desc *desc1 = NULL; 44807bcd316dSGangCao struct spdk_bdev_desc *desc2 = NULL; 44817bcd316dSGangCao struct spdk_bdev_desc *desc3 = NULL; 44827bcd316dSGangCao struct spdk_bdev_desc *desc4 = NULL; 44837bcd316dSGangCao int rc = 0; 44847bcd316dSGangCao 44857bcd316dSGangCao bdev = allocate_bdev("bdev"); 44867bcd316dSGangCao 44877bcd316dSGangCao rc = spdk_bdev_open_ext("bdev", true, NULL, NULL, &desc1); 44887bcd316dSGangCao CU_ASSERT_EQUAL(rc, -EINVAL); 44897bcd316dSGangCao 44907bcd316dSGangCao rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb1, &desc1, &desc1); 44917bcd316dSGangCao CU_ASSERT_EQUAL(rc, 0); 44927bcd316dSGangCao 44937bcd316dSGangCao rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb2, &desc2, &desc2); 44947bcd316dSGangCao CU_ASSERT_EQUAL(rc, 0); 44957bcd316dSGangCao 44967bcd316dSGangCao rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb3, &desc3, &desc3); 44977bcd316dSGangCao CU_ASSERT_EQUAL(rc, 0); 44987bcd316dSGangCao 44997bcd316dSGangCao rc = spdk_bdev_open_ext("bdev", true, bdev_open_cb4, &desc4, &desc4); 45007bcd316dSGangCao CU_ASSERT_EQUAL(rc, 0); 45017bcd316dSGangCao 45027bcd316dSGangCao g_event_type1 = 0xFF; 45037bcd316dSGangCao g_event_type2 = 0xFF; 45047bcd316dSGangCao g_event_type3 = 0xFF; 45057bcd316dSGangCao g_event_type4 = 0xFF; 45067bcd316dSGangCao 45077bcd316dSGangCao g_unregister_arg = NULL; 45087bcd316dSGangCao g_unregister_rc = -1; 45097bcd316dSGangCao 45107bcd316dSGangCao /* Simulate hot-unplug by unregistering bdev */ 45117bcd316dSGangCao spdk_bdev_unregister(bdev, bdev_unregister_cb, (void *)0x12345678); 45127bcd316dSGangCao 45137bcd316dSGangCao /* 45147bcd316dSGangCao * Unregister is handled asynchronously and event callback 45157bcd316dSGangCao * (i.e., above bdev_open_cbN) will be called. 45167bcd316dSGangCao * For bdev_open_cb3 and bdev_open_cb4, it is intended to not 45177bcd316dSGangCao * close the desc3 and desc4 so that the bdev is not closed. 45187bcd316dSGangCao */ 45197bcd316dSGangCao poll_threads(); 45207bcd316dSGangCao 45217bcd316dSGangCao /* Check if correct events have been triggered in event callback fn */ 45227bcd316dSGangCao CU_ASSERT_EQUAL(g_event_type1, SPDK_BDEV_EVENT_REMOVE); 45237bcd316dSGangCao CU_ASSERT_EQUAL(g_event_type2, SPDK_BDEV_EVENT_REMOVE); 45247bcd316dSGangCao CU_ASSERT_EQUAL(g_event_type3, SPDK_BDEV_EVENT_REMOVE); 45257bcd316dSGangCao CU_ASSERT_EQUAL(g_event_type4, SPDK_BDEV_EVENT_REMOVE); 45267bcd316dSGangCao 45277bcd316dSGangCao /* Check that unregister callback is delayed */ 45287bcd316dSGangCao CU_ASSERT(g_unregister_arg == NULL); 45297bcd316dSGangCao CU_ASSERT(g_unregister_rc == -1); 45307bcd316dSGangCao 45317bcd316dSGangCao /* 45327bcd316dSGangCao * Explicitly close desc3. As desc4 is still opened there, the 45337bcd316dSGangCao * unergister callback is still delayed to execute. 45347bcd316dSGangCao */ 45357bcd316dSGangCao spdk_bdev_close(desc3); 45367bcd316dSGangCao CU_ASSERT(g_unregister_arg == NULL); 45377bcd316dSGangCao CU_ASSERT(g_unregister_rc == -1); 45387bcd316dSGangCao 45397bcd316dSGangCao /* 45407bcd316dSGangCao * Explicitly close desc4 to trigger the ongoing bdev unregister 45417bcd316dSGangCao * operation after last desc is closed. 45427bcd316dSGangCao */ 45437bcd316dSGangCao spdk_bdev_close(desc4); 45447bcd316dSGangCao 45457bcd316dSGangCao /* Poll the thread for the async unregister operation */ 45467bcd316dSGangCao poll_threads(); 45477bcd316dSGangCao 45487bcd316dSGangCao /* Check that unregister callback is executed */ 45497bcd316dSGangCao CU_ASSERT(g_unregister_arg == (void *)0x12345678); 45507bcd316dSGangCao CU_ASSERT(g_unregister_rc == 0); 45517bcd316dSGangCao 45527bcd316dSGangCao free_bdev(bdev); 45537bcd316dSGangCao poll_threads(); 45547bcd316dSGangCao } 45557bcd316dSGangCao 4556f1d47d69SJin Yu struct timeout_io_cb_arg { 4557f1d47d69SJin Yu struct iovec iov; 4558f1d47d69SJin Yu uint8_t type; 4559f1d47d69SJin Yu }; 4560f1d47d69SJin Yu 4561f1d47d69SJin Yu static int 4562f1d47d69SJin Yu bdev_channel_count_submitted_io(struct spdk_bdev_channel *ch) 4563f1d47d69SJin Yu { 4564f1d47d69SJin Yu struct spdk_bdev_io *bdev_io; 4565f1d47d69SJin Yu int n = 0; 4566f1d47d69SJin Yu 4567f1d47d69SJin Yu if (!ch) { 4568f1d47d69SJin Yu return -1; 4569f1d47d69SJin Yu } 4570f1d47d69SJin Yu 4571f1d47d69SJin Yu TAILQ_FOREACH(bdev_io, &ch->io_submitted, internal.ch_link) { 4572f1d47d69SJin Yu n++; 4573f1d47d69SJin Yu } 4574f1d47d69SJin Yu 4575f1d47d69SJin Yu return n; 4576f1d47d69SJin Yu } 4577f1d47d69SJin Yu 4578f1d47d69SJin Yu static void 4579f1d47d69SJin Yu bdev_channel_io_timeout_cb(void *cb_arg, struct spdk_bdev_io *bdev_io) 4580f1d47d69SJin Yu { 4581f1d47d69SJin Yu struct timeout_io_cb_arg *ctx = cb_arg; 4582f1d47d69SJin Yu 4583f1d47d69SJin Yu ctx->type = bdev_io->type; 4584f1d47d69SJin Yu ctx->iov.iov_base = bdev_io->iov.iov_base; 4585f1d47d69SJin Yu ctx->iov.iov_len = bdev_io->iov.iov_len; 4586f1d47d69SJin Yu } 4587f1d47d69SJin Yu 4588f1d47d69SJin Yu static void 4589f1d47d69SJin Yu bdev_set_io_timeout(void) 4590f1d47d69SJin Yu { 4591f1d47d69SJin Yu struct spdk_bdev *bdev; 4592f1d47d69SJin Yu struct spdk_bdev_desc *desc = NULL; 4593f1d47d69SJin Yu struct spdk_io_channel *io_ch = NULL; 4594f1d47d69SJin Yu struct spdk_bdev_channel *bdev_ch = NULL; 4595f1d47d69SJin Yu struct timeout_io_cb_arg cb_arg; 4596f1d47d69SJin Yu 4597107741fcSKonrad Sztyber ut_init_bdev(NULL); 4598f1d47d69SJin Yu bdev = allocate_bdev("bdev"); 4599f1d47d69SJin Yu 460075dfecbbSShuhei Matsumoto CU_ASSERT(spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc) == 0); 4601f1d47d69SJin Yu SPDK_CU_ASSERT_FATAL(desc != NULL); 460275dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 460375dfecbbSShuhei Matsumoto 4604f1d47d69SJin Yu io_ch = spdk_bdev_get_io_channel(desc); 4605f1d47d69SJin Yu CU_ASSERT(io_ch != NULL); 4606f1d47d69SJin Yu 4607f1d47d69SJin Yu bdev_ch = spdk_io_channel_get_ctx(io_ch); 4608f1d47d69SJin Yu CU_ASSERT(TAILQ_EMPTY(&bdev_ch->io_submitted)); 4609f1d47d69SJin Yu 4610f1d47d69SJin Yu /* This is the part1. 4611f1d47d69SJin Yu * We will check the bdev_ch->io_submitted list 4612f1d47d69SJin Yu * TO make sure that it can link IOs and only the user submitted IOs 4613f1d47d69SJin Yu */ 4614f1d47d69SJin Yu CU_ASSERT(spdk_bdev_read(desc, io_ch, (void *)0x1000, 0, 4096, io_done, NULL) == 0); 4615f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 4616f1d47d69SJin Yu CU_ASSERT(spdk_bdev_write(desc, io_ch, (void *)0x2000, 0, 4096, io_done, NULL) == 0); 4617f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 2); 4618f1d47d69SJin Yu stub_complete_io(1); 4619f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 4620f1d47d69SJin Yu stub_complete_io(1); 4621f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 0); 4622f1d47d69SJin Yu 4623f1d47d69SJin Yu /* Split IO */ 4624f1d47d69SJin Yu bdev->optimal_io_boundary = 16; 4625f1d47d69SJin Yu bdev->split_on_optimal_io_boundary = true; 4626f1d47d69SJin Yu 4627f1d47d69SJin Yu /* Now test that a single-vector command is split correctly. 4628f1d47d69SJin Yu * Offset 14, length 8, payload 0xF000 4629f1d47d69SJin Yu * Child - Offset 14, length 2, payload 0xF000 4630f1d47d69SJin Yu * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 4631f1d47d69SJin Yu * 4632f1d47d69SJin Yu * Set up the expected values before calling spdk_bdev_read_blocks 4633f1d47d69SJin Yu */ 4634f1d47d69SJin Yu CU_ASSERT(spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL) == 0); 4635fc3e4061SShuhei Matsumoto /* We count all submitted IOs including IO that are generated by splitting. */ 4636fc3e4061SShuhei Matsumoto CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 3); 4637f1d47d69SJin Yu stub_complete_io(1); 4638fc3e4061SShuhei Matsumoto CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 2); 4639f1d47d69SJin Yu stub_complete_io(1); 4640f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 0); 4641f1d47d69SJin Yu 4642f1d47d69SJin Yu /* Also include the reset IO */ 4643f1d47d69SJin Yu CU_ASSERT(spdk_bdev_reset(desc, io_ch, io_done, NULL) == 0); 4644f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 4645f1d47d69SJin Yu poll_threads(); 4646f1d47d69SJin Yu stub_complete_io(1); 4647f1d47d69SJin Yu poll_threads(); 4648f1d47d69SJin Yu CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 0); 4649f1d47d69SJin Yu 4650f1d47d69SJin Yu /* This is part2 4651f1d47d69SJin Yu * Test the desc timeout poller register 4652f1d47d69SJin Yu */ 4653f1d47d69SJin Yu 4654f1d47d69SJin Yu /* Successfully set the timeout */ 4655f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 30, bdev_channel_io_timeout_cb, &cb_arg) == 0); 4656f1d47d69SJin Yu CU_ASSERT(desc->io_timeout_poller != NULL); 4657f1d47d69SJin Yu CU_ASSERT(desc->timeout_in_sec == 30); 4658f1d47d69SJin Yu CU_ASSERT(desc->cb_fn == bdev_channel_io_timeout_cb); 4659f1d47d69SJin Yu CU_ASSERT(desc->cb_arg == &cb_arg); 4660f1d47d69SJin Yu 4661f1d47d69SJin Yu /* Change the timeout limit */ 4662f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 20, bdev_channel_io_timeout_cb, &cb_arg) == 0); 4663f1d47d69SJin Yu CU_ASSERT(desc->io_timeout_poller != NULL); 4664f1d47d69SJin Yu CU_ASSERT(desc->timeout_in_sec == 20); 4665f1d47d69SJin Yu CU_ASSERT(desc->cb_fn == bdev_channel_io_timeout_cb); 4666f1d47d69SJin Yu CU_ASSERT(desc->cb_arg == &cb_arg); 4667f1d47d69SJin Yu 4668f1d47d69SJin Yu /* Disable the timeout */ 4669f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 0, NULL, NULL) == 0); 4670f1d47d69SJin Yu CU_ASSERT(desc->io_timeout_poller == NULL); 4671f1d47d69SJin Yu 4672f1d47d69SJin Yu /* This the part3 4673f1d47d69SJin Yu * We will test to catch timeout IO and check whether the IO is 4674f1d47d69SJin Yu * the submitted one. 4675f1d47d69SJin Yu */ 4676f1d47d69SJin Yu memset(&cb_arg, 0, sizeof(cb_arg)); 4677f1d47d69SJin Yu CU_ASSERT(spdk_bdev_set_timeout(desc, 30, bdev_channel_io_timeout_cb, &cb_arg) == 0); 4678f1d47d69SJin Yu CU_ASSERT(spdk_bdev_write_blocks(desc, io_ch, (void *)0x1000, 0, 1, io_done, NULL) == 0); 4679f1d47d69SJin Yu 4680f1d47d69SJin Yu /* Don't reach the limit */ 4681f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 4682f1d47d69SJin Yu poll_threads(); 4683f1d47d69SJin Yu CU_ASSERT(cb_arg.type == 0); 4684f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0x0); 4685f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 0); 4686f1d47d69SJin Yu 4687f1d47d69SJin Yu /* 15 + 15 = 30 reach the limit */ 4688f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 4689f1d47d69SJin Yu poll_threads(); 4690f1d47d69SJin Yu CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_WRITE); 4691f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0x1000); 4692f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 1 * bdev->blocklen); 4693f1d47d69SJin Yu stub_complete_io(1); 4694f1d47d69SJin Yu 4695f1d47d69SJin Yu /* Use the same split IO above and check the IO */ 4696f1d47d69SJin Yu memset(&cb_arg, 0, sizeof(cb_arg)); 4697f1d47d69SJin Yu CU_ASSERT(spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, NULL) == 0); 4698f1d47d69SJin Yu 4699f1d47d69SJin Yu /* The first child complete in time */ 4700f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 4701f1d47d69SJin Yu poll_threads(); 4702f1d47d69SJin Yu stub_complete_io(1); 4703f1d47d69SJin Yu CU_ASSERT(cb_arg.type == 0); 4704f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0x0); 4705f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 0); 4706f1d47d69SJin Yu 4707f1d47d69SJin Yu /* The second child reach the limit */ 4708f1d47d69SJin Yu spdk_delay_us(15 * spdk_get_ticks_hz()); 4709f1d47d69SJin Yu poll_threads(); 4710f1d47d69SJin Yu CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_WRITE); 4711f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_base == (void *)0xF000); 4712f1d47d69SJin Yu CU_ASSERT(cb_arg.iov.iov_len == 8 * bdev->blocklen); 4713f1d47d69SJin Yu stub_complete_io(1); 4714f1d47d69SJin Yu 4715f1d47d69SJin Yu /* Also include the reset IO */ 4716f1d47d69SJin Yu memset(&cb_arg, 0, sizeof(cb_arg)); 4717f1d47d69SJin Yu CU_ASSERT(spdk_bdev_reset(desc, io_ch, io_done, NULL) == 0); 4718f1d47d69SJin Yu spdk_delay_us(30 * spdk_get_ticks_hz()); 4719f1d47d69SJin Yu poll_threads(); 4720f1d47d69SJin Yu CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_RESET); 4721f1d47d69SJin Yu stub_complete_io(1); 4722f1d47d69SJin Yu poll_threads(); 4723f1d47d69SJin Yu 4724f1d47d69SJin Yu spdk_put_io_channel(io_ch); 4725f1d47d69SJin Yu spdk_bdev_close(desc); 4726f1d47d69SJin Yu free_bdev(bdev); 4727107741fcSKonrad Sztyber ut_fini_bdev(); 4728f1d47d69SJin Yu } 4729f1d47d69SJin Yu 4730b87080efSJim Harris static void 473148ce2c97SGangCao bdev_set_qd_sampling(void) 473248ce2c97SGangCao { 473348ce2c97SGangCao struct spdk_bdev *bdev; 473448ce2c97SGangCao struct spdk_bdev_desc *desc = NULL; 473548ce2c97SGangCao struct spdk_io_channel *io_ch = NULL; 473648ce2c97SGangCao struct spdk_bdev_channel *bdev_ch = NULL; 473748ce2c97SGangCao struct timeout_io_cb_arg cb_arg; 473848ce2c97SGangCao 4739107741fcSKonrad Sztyber ut_init_bdev(NULL); 474048ce2c97SGangCao bdev = allocate_bdev("bdev"); 474148ce2c97SGangCao 474248ce2c97SGangCao CU_ASSERT(spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc) == 0); 474348ce2c97SGangCao SPDK_CU_ASSERT_FATAL(desc != NULL); 474448ce2c97SGangCao CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 474548ce2c97SGangCao 474648ce2c97SGangCao io_ch = spdk_bdev_get_io_channel(desc); 474748ce2c97SGangCao CU_ASSERT(io_ch != NULL); 474848ce2c97SGangCao 474948ce2c97SGangCao bdev_ch = spdk_io_channel_get_ctx(io_ch); 475048ce2c97SGangCao CU_ASSERT(TAILQ_EMPTY(&bdev_ch->io_submitted)); 475148ce2c97SGangCao 475248ce2c97SGangCao /* This is the part1. 475348ce2c97SGangCao * We will check the bdev_ch->io_submitted list 475448ce2c97SGangCao * TO make sure that it can link IOs and only the user submitted IOs 475548ce2c97SGangCao */ 475648ce2c97SGangCao CU_ASSERT(spdk_bdev_read(desc, io_ch, (void *)0x1000, 0, 4096, io_done, NULL) == 0); 475748ce2c97SGangCao CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 475848ce2c97SGangCao CU_ASSERT(spdk_bdev_write(desc, io_ch, (void *)0x2000, 0, 4096, io_done, NULL) == 0); 475948ce2c97SGangCao CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 2); 476048ce2c97SGangCao stub_complete_io(1); 476148ce2c97SGangCao CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 476248ce2c97SGangCao stub_complete_io(1); 476348ce2c97SGangCao CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 0); 476448ce2c97SGangCao 476548ce2c97SGangCao /* This is the part2. 476648ce2c97SGangCao * Test the bdev's qd poller register 476748ce2c97SGangCao */ 476848ce2c97SGangCao /* 1st Successfully set the qd sampling period */ 476948ce2c97SGangCao spdk_bdev_set_qd_sampling_period(bdev, 10); 477048ce2c97SGangCao CU_ASSERT(bdev->internal.new_period == 10); 477148ce2c97SGangCao CU_ASSERT(bdev->internal.period == 10); 477248ce2c97SGangCao CU_ASSERT(bdev->internal.qd_desc != NULL); 477348ce2c97SGangCao poll_threads(); 477448ce2c97SGangCao CU_ASSERT(bdev->internal.qd_poller != NULL); 477548ce2c97SGangCao 477648ce2c97SGangCao /* 2nd Change the qd sampling period */ 477748ce2c97SGangCao spdk_bdev_set_qd_sampling_period(bdev, 20); 477848ce2c97SGangCao CU_ASSERT(bdev->internal.new_period == 20); 477948ce2c97SGangCao CU_ASSERT(bdev->internal.period == 10); 478048ce2c97SGangCao CU_ASSERT(bdev->internal.qd_desc != NULL); 478148ce2c97SGangCao poll_threads(); 478248ce2c97SGangCao CU_ASSERT(bdev->internal.qd_poller != NULL); 478348ce2c97SGangCao CU_ASSERT(bdev->internal.period == bdev->internal.new_period); 478448ce2c97SGangCao 478548ce2c97SGangCao /* 3rd Change the qd sampling period and verify qd_poll_in_progress */ 478648ce2c97SGangCao spdk_delay_us(20); 478748ce2c97SGangCao poll_thread_times(0, 1); 478848ce2c97SGangCao CU_ASSERT(bdev->internal.qd_poll_in_progress == true); 478948ce2c97SGangCao spdk_bdev_set_qd_sampling_period(bdev, 30); 479048ce2c97SGangCao CU_ASSERT(bdev->internal.new_period == 30); 479148ce2c97SGangCao CU_ASSERT(bdev->internal.period == 20); 479248ce2c97SGangCao poll_threads(); 479348ce2c97SGangCao CU_ASSERT(bdev->internal.qd_poll_in_progress == false); 479448ce2c97SGangCao CU_ASSERT(bdev->internal.period == bdev->internal.new_period); 479548ce2c97SGangCao 479648ce2c97SGangCao /* 4th Disable the qd sampling period */ 479748ce2c97SGangCao spdk_bdev_set_qd_sampling_period(bdev, 0); 479848ce2c97SGangCao CU_ASSERT(bdev->internal.new_period == 0); 479948ce2c97SGangCao CU_ASSERT(bdev->internal.period == 30); 480048ce2c97SGangCao poll_threads(); 480148ce2c97SGangCao CU_ASSERT(bdev->internal.qd_poller == NULL); 480248ce2c97SGangCao CU_ASSERT(bdev->internal.period == bdev->internal.new_period); 480348ce2c97SGangCao CU_ASSERT(bdev->internal.qd_desc == NULL); 480448ce2c97SGangCao 480548ce2c97SGangCao /* This is the part3. 480648ce2c97SGangCao * We will test the submitted IO and reset works 480748ce2c97SGangCao * properly with the qd sampling. 480848ce2c97SGangCao */ 480948ce2c97SGangCao memset(&cb_arg, 0, sizeof(cb_arg)); 481048ce2c97SGangCao spdk_bdev_set_qd_sampling_period(bdev, 1); 481148ce2c97SGangCao poll_threads(); 481248ce2c97SGangCao 481348ce2c97SGangCao CU_ASSERT(spdk_bdev_write(desc, io_ch, (void *)0x2000, 0, 4096, io_done, NULL) == 0); 481448ce2c97SGangCao CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch) == 1); 481548ce2c97SGangCao 481648ce2c97SGangCao /* Also include the reset IO */ 481748ce2c97SGangCao memset(&cb_arg, 0, sizeof(cb_arg)); 481848ce2c97SGangCao CU_ASSERT(spdk_bdev_reset(desc, io_ch, io_done, NULL) == 0); 481948ce2c97SGangCao poll_threads(); 482048ce2c97SGangCao 482148ce2c97SGangCao /* Close the desc */ 482248ce2c97SGangCao spdk_put_io_channel(io_ch); 482348ce2c97SGangCao spdk_bdev_close(desc); 482448ce2c97SGangCao 482548ce2c97SGangCao /* Complete the submitted IO and reset */ 482648ce2c97SGangCao stub_complete_io(2); 482748ce2c97SGangCao poll_threads(); 482848ce2c97SGangCao 482948ce2c97SGangCao free_bdev(bdev); 4830107741fcSKonrad Sztyber ut_fini_bdev(); 483148ce2c97SGangCao } 483248ce2c97SGangCao 483348ce2c97SGangCao static void 4834b87080efSJim Harris lba_range_overlap(void) 4835b87080efSJim Harris { 4836b87080efSJim Harris struct lba_range r1, r2; 4837b87080efSJim Harris 4838b87080efSJim Harris r1.offset = 100; 4839b87080efSJim Harris r1.length = 50; 4840b87080efSJim Harris 4841b87080efSJim Harris r2.offset = 0; 4842b87080efSJim Harris r2.length = 1; 4843b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 4844b87080efSJim Harris 4845b87080efSJim Harris r2.offset = 0; 4846b87080efSJim Harris r2.length = 100; 4847b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 4848b87080efSJim Harris 4849b87080efSJim Harris r2.offset = 0; 4850b87080efSJim Harris r2.length = 110; 4851b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 4852b87080efSJim Harris 4853b87080efSJim Harris r2.offset = 100; 4854b87080efSJim Harris r2.length = 10; 4855b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 4856b87080efSJim Harris 4857b87080efSJim Harris r2.offset = 110; 4858b87080efSJim Harris r2.length = 20; 4859b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 4860b87080efSJim Harris 4861b87080efSJim Harris r2.offset = 140; 4862b87080efSJim Harris r2.length = 150; 4863b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 4864b87080efSJim Harris 4865b87080efSJim Harris r2.offset = 130; 4866b87080efSJim Harris r2.length = 200; 4867b87080efSJim Harris CU_ASSERT(bdev_lba_range_overlapped(&r1, &r2)); 4868b87080efSJim Harris 4869b87080efSJim Harris r2.offset = 150; 4870b87080efSJim Harris r2.length = 100; 4871b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 4872b87080efSJim Harris 4873b87080efSJim Harris r2.offset = 110; 4874b87080efSJim Harris r2.length = 0; 4875b87080efSJim Harris CU_ASSERT(!bdev_lba_range_overlapped(&r1, &r2)); 4876b87080efSJim Harris } 4877b87080efSJim Harris 4878d84a88c1SJim Harris static bool g_lock_lba_range_done; 4879d84a88c1SJim Harris static bool g_unlock_lba_range_done; 4880d84a88c1SJim Harris 4881d84a88c1SJim Harris static void 4882687cfd4bSArtur Paszkiewicz lock_lba_range_done(struct lba_range *range, void *ctx, int status) 4883d84a88c1SJim Harris { 4884d84a88c1SJim Harris g_lock_lba_range_done = true; 4885d84a88c1SJim Harris } 4886d84a88c1SJim Harris 4887d84a88c1SJim Harris static void 4888687cfd4bSArtur Paszkiewicz unlock_lba_range_done(struct lba_range *range, void *ctx, int status) 4889d84a88c1SJim Harris { 4890d84a88c1SJim Harris g_unlock_lba_range_done = true; 4891d84a88c1SJim Harris } 4892d84a88c1SJim Harris 4893d84a88c1SJim Harris static void 4894d84a88c1SJim Harris lock_lba_range_check_ranges(void) 4895d84a88c1SJim Harris { 4896d84a88c1SJim Harris struct spdk_bdev *bdev; 4897d84a88c1SJim Harris struct spdk_bdev_desc *desc = NULL; 4898d84a88c1SJim Harris struct spdk_io_channel *io_ch; 4899d84a88c1SJim Harris struct spdk_bdev_channel *channel; 4900d84a88c1SJim Harris struct lba_range *range; 4901d84a88c1SJim Harris int ctx1; 4902d84a88c1SJim Harris int rc; 4903d84a88c1SJim Harris 4904107741fcSKonrad Sztyber ut_init_bdev(NULL); 4905d84a88c1SJim Harris bdev = allocate_bdev("bdev0"); 4906d84a88c1SJim Harris 490775dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 4908d84a88c1SJim Harris CU_ASSERT(rc == 0); 4909d84a88c1SJim Harris CU_ASSERT(desc != NULL); 491075dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 4911d84a88c1SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 4912d84a88c1SJim Harris CU_ASSERT(io_ch != NULL); 4913d84a88c1SJim Harris channel = spdk_io_channel_get_ctx(io_ch); 4914d84a88c1SJim Harris 4915d84a88c1SJim Harris g_lock_lba_range_done = false; 4916d84a88c1SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 4917d84a88c1SJim Harris CU_ASSERT(rc == 0); 4918d84a88c1SJim Harris poll_threads(); 4919d84a88c1SJim Harris 4920d84a88c1SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 4921d84a88c1SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 4922d84a88c1SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 4923d84a88c1SJim Harris CU_ASSERT(range->offset == 20); 4924d84a88c1SJim Harris CU_ASSERT(range->length == 10); 4925d84a88c1SJim Harris CU_ASSERT(range->owner_ch == channel); 4926d84a88c1SJim Harris 4927d84a88c1SJim Harris /* Unlocks must exactly match a lock. */ 4928d84a88c1SJim Harris g_unlock_lba_range_done = false; 4929d84a88c1SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 1, unlock_lba_range_done, &ctx1); 4930d84a88c1SJim Harris CU_ASSERT(rc == -EINVAL); 4931d84a88c1SJim Harris CU_ASSERT(g_unlock_lba_range_done == false); 4932d84a88c1SJim Harris 4933d84a88c1SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, unlock_lba_range_done, &ctx1); 4934d84a88c1SJim Harris CU_ASSERT(rc == 0); 4935d84a88c1SJim Harris spdk_delay_us(100); 4936d84a88c1SJim Harris poll_threads(); 4937d84a88c1SJim Harris 4938d84a88c1SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 4939d84a88c1SJim Harris CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 4940d84a88c1SJim Harris 4941d84a88c1SJim Harris spdk_put_io_channel(io_ch); 4942d84a88c1SJim Harris spdk_bdev_close(desc); 4943d84a88c1SJim Harris free_bdev(bdev); 4944107741fcSKonrad Sztyber ut_fini_bdev(); 4945d84a88c1SJim Harris } 4946d84a88c1SJim Harris 4947b90b7ce4SJim Harris static void 4948b90b7ce4SJim Harris lock_lba_range_with_io_outstanding(void) 4949b90b7ce4SJim Harris { 4950b90b7ce4SJim Harris struct spdk_bdev *bdev; 4951b90b7ce4SJim Harris struct spdk_bdev_desc *desc = NULL; 4952b90b7ce4SJim Harris struct spdk_io_channel *io_ch; 4953b90b7ce4SJim Harris struct spdk_bdev_channel *channel; 4954b90b7ce4SJim Harris struct lba_range *range; 4955b90b7ce4SJim Harris char buf[4096]; 4956b90b7ce4SJim Harris int ctx1; 4957b90b7ce4SJim Harris int rc; 4958b90b7ce4SJim Harris 4959107741fcSKonrad Sztyber ut_init_bdev(NULL); 4960b90b7ce4SJim Harris bdev = allocate_bdev("bdev0"); 4961b90b7ce4SJim Harris 496275dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 4963b90b7ce4SJim Harris CU_ASSERT(rc == 0); 4964b90b7ce4SJim Harris CU_ASSERT(desc != NULL); 496575dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 4966b90b7ce4SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 4967b90b7ce4SJim Harris CU_ASSERT(io_ch != NULL); 4968b90b7ce4SJim Harris channel = spdk_io_channel_get_ctx(io_ch); 4969b90b7ce4SJim Harris 4970b90b7ce4SJim Harris g_io_done = false; 4971b90b7ce4SJim Harris rc = spdk_bdev_read_blocks(desc, io_ch, buf, 20, 1, io_done, &ctx1); 4972b90b7ce4SJim Harris CU_ASSERT(rc == 0); 4973b90b7ce4SJim Harris 4974b90b7ce4SJim Harris g_lock_lba_range_done = false; 4975b90b7ce4SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 4976b90b7ce4SJim Harris CU_ASSERT(rc == 0); 4977b90b7ce4SJim Harris poll_threads(); 4978b90b7ce4SJim Harris 4979b90b7ce4SJim Harris /* The lock should immediately become valid, since there are no outstanding 4980b90b7ce4SJim Harris * write I/O. 4981b90b7ce4SJim Harris */ 4982b90b7ce4SJim Harris CU_ASSERT(g_io_done == false); 4983b90b7ce4SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 4984b90b7ce4SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 4985b90b7ce4SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 4986b90b7ce4SJim Harris CU_ASSERT(range->offset == 20); 4987b90b7ce4SJim Harris CU_ASSERT(range->length == 10); 4988b90b7ce4SJim Harris CU_ASSERT(range->owner_ch == channel); 4989b90b7ce4SJim Harris CU_ASSERT(range->locked_ctx == &ctx1); 4990b90b7ce4SJim Harris 4991b90b7ce4SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 4992b90b7ce4SJim Harris CU_ASSERT(rc == 0); 4993b90b7ce4SJim Harris stub_complete_io(1); 4994b90b7ce4SJim Harris spdk_delay_us(100); 4995b90b7ce4SJim Harris poll_threads(); 4996b90b7ce4SJim Harris 4997b90b7ce4SJim Harris CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 4998b90b7ce4SJim Harris 4999b90b7ce4SJim Harris /* Now try again, but with a write I/O. */ 5000b90b7ce4SJim Harris g_io_done = false; 5001b90b7ce4SJim Harris rc = spdk_bdev_write_blocks(desc, io_ch, buf, 20, 1, io_done, &ctx1); 5002b90b7ce4SJim Harris CU_ASSERT(rc == 0); 5003b90b7ce4SJim Harris 5004b90b7ce4SJim Harris g_lock_lba_range_done = false; 5005b90b7ce4SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 5006b90b7ce4SJim Harris CU_ASSERT(rc == 0); 5007b90b7ce4SJim Harris poll_threads(); 5008b90b7ce4SJim Harris 5009b90b7ce4SJim Harris /* The lock should not be fully valid yet, since a write I/O is outstanding. 5010b90b7ce4SJim Harris * But note that the range should be on the channel's locked_list, to make sure no 5011b90b7ce4SJim Harris * new write I/O are started. 5012b90b7ce4SJim Harris */ 5013b90b7ce4SJim Harris CU_ASSERT(g_io_done == false); 5014b90b7ce4SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 5015b90b7ce4SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 5016b90b7ce4SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 5017b90b7ce4SJim Harris CU_ASSERT(range->offset == 20); 5018b90b7ce4SJim Harris CU_ASSERT(range->length == 10); 5019b90b7ce4SJim Harris 5020b90b7ce4SJim Harris /* Complete the write I/O. This should make the lock valid (checked by confirming 5021b90b7ce4SJim Harris * our callback was invoked). 5022b90b7ce4SJim Harris */ 5023b90b7ce4SJim Harris stub_complete_io(1); 5024b90b7ce4SJim Harris spdk_delay_us(100); 5025b90b7ce4SJim Harris poll_threads(); 5026b90b7ce4SJim Harris CU_ASSERT(g_io_done == true); 5027b90b7ce4SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 5028b90b7ce4SJim Harris 5029b90b7ce4SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, unlock_lba_range_done, &ctx1); 5030b90b7ce4SJim Harris CU_ASSERT(rc == 0); 5031b90b7ce4SJim Harris poll_threads(); 5032b90b7ce4SJim Harris 5033b90b7ce4SJim Harris CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 5034b90b7ce4SJim Harris 5035b90b7ce4SJim Harris spdk_put_io_channel(io_ch); 5036b90b7ce4SJim Harris spdk_bdev_close(desc); 5037b90b7ce4SJim Harris free_bdev(bdev); 5038107741fcSKonrad Sztyber ut_fini_bdev(); 5039b90b7ce4SJim Harris } 5040b90b7ce4SJim Harris 50412a2b7296SJim Harris static void 50422a2b7296SJim Harris lock_lba_range_overlapped(void) 50432a2b7296SJim Harris { 50442a2b7296SJim Harris struct spdk_bdev *bdev; 50452a2b7296SJim Harris struct spdk_bdev_desc *desc = NULL; 50462a2b7296SJim Harris struct spdk_io_channel *io_ch; 50472a2b7296SJim Harris struct spdk_bdev_channel *channel; 50482a2b7296SJim Harris struct lba_range *range; 50492a2b7296SJim Harris int ctx1; 50502a2b7296SJim Harris int rc; 50512a2b7296SJim Harris 5052107741fcSKonrad Sztyber ut_init_bdev(NULL); 50532a2b7296SJim Harris bdev = allocate_bdev("bdev0"); 50542a2b7296SJim Harris 505575dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 50562a2b7296SJim Harris CU_ASSERT(rc == 0); 50572a2b7296SJim Harris CU_ASSERT(desc != NULL); 505875dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 50592a2b7296SJim Harris io_ch = spdk_bdev_get_io_channel(desc); 50602a2b7296SJim Harris CU_ASSERT(io_ch != NULL); 50612a2b7296SJim Harris channel = spdk_io_channel_get_ctx(io_ch); 50622a2b7296SJim Harris 50632a2b7296SJim Harris /* Lock range 20-29. */ 50642a2b7296SJim Harris g_lock_lba_range_done = false; 50652a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 20, 10, lock_lba_range_done, &ctx1); 50662a2b7296SJim Harris CU_ASSERT(rc == 0); 50672a2b7296SJim Harris poll_threads(); 50682a2b7296SJim Harris 50692a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 50702a2b7296SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 50712a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 50722a2b7296SJim Harris CU_ASSERT(range->offset == 20); 50732a2b7296SJim Harris CU_ASSERT(range->length == 10); 50742a2b7296SJim Harris 50752a2b7296SJim Harris /* Try to lock range 25-39. It should not lock immediately, since it overlaps with 50762a2b7296SJim Harris * 20-29. 50772a2b7296SJim Harris */ 50782a2b7296SJim Harris g_lock_lba_range_done = false; 50792a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 25, 15, lock_lba_range_done, &ctx1); 50802a2b7296SJim Harris CU_ASSERT(rc == 0); 50812a2b7296SJim Harris poll_threads(); 50822a2b7296SJim Harris 50832a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 50842a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.pending_locked_ranges); 50852a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 50862a2b7296SJim Harris CU_ASSERT(range->offset == 25); 50872a2b7296SJim Harris CU_ASSERT(range->length == 15); 50882a2b7296SJim Harris 50892a2b7296SJim Harris /* Unlock 20-29. This should result in range 25-39 now getting locked since it 50902a2b7296SJim Harris * no longer overlaps with an active lock. 50912a2b7296SJim Harris */ 50922a2b7296SJim Harris g_unlock_lba_range_done = false; 50932a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 20, 10, unlock_lba_range_done, &ctx1); 50942a2b7296SJim Harris CU_ASSERT(rc == 0); 50952a2b7296SJim Harris poll_threads(); 50962a2b7296SJim Harris 50972a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 50982a2b7296SJim Harris CU_ASSERT(TAILQ_EMPTY(&bdev->internal.pending_locked_ranges)); 50992a2b7296SJim Harris range = TAILQ_FIRST(&channel->locked_ranges); 51002a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 51012a2b7296SJim Harris CU_ASSERT(range->offset == 25); 51022a2b7296SJim Harris CU_ASSERT(range->length == 15); 51032a2b7296SJim Harris 51042a2b7296SJim Harris /* Lock 40-59. This should immediately lock since it does not overlap with the 51052a2b7296SJim Harris * currently active 25-39 lock. 51062a2b7296SJim Harris */ 51072a2b7296SJim Harris g_lock_lba_range_done = false; 51082a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 40, 20, lock_lba_range_done, &ctx1); 51092a2b7296SJim Harris CU_ASSERT(rc == 0); 51102a2b7296SJim Harris poll_threads(); 51112a2b7296SJim Harris 51122a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 51132a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.locked_ranges); 51142a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 51152a2b7296SJim Harris range = TAILQ_NEXT(range, tailq); 51162a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 51172a2b7296SJim Harris CU_ASSERT(range->offset == 40); 51182a2b7296SJim Harris CU_ASSERT(range->length == 20); 51192a2b7296SJim Harris 51202a2b7296SJim Harris /* Try to lock 35-44. Note that this overlaps with both 25-39 and 40-59. */ 51212a2b7296SJim Harris g_lock_lba_range_done = false; 51222a2b7296SJim Harris rc = bdev_lock_lba_range(desc, io_ch, 35, 10, lock_lba_range_done, &ctx1); 51232a2b7296SJim Harris CU_ASSERT(rc == 0); 51242a2b7296SJim Harris poll_threads(); 51252a2b7296SJim Harris 51262a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 51272a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.pending_locked_ranges); 51282a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 51292a2b7296SJim Harris CU_ASSERT(range->offset == 35); 51302a2b7296SJim Harris CU_ASSERT(range->length == 10); 51312a2b7296SJim Harris 51322a2b7296SJim Harris /* Unlock 25-39. Make sure that 35-44 is still in the pending list, since 51332a2b7296SJim Harris * the 40-59 lock is still active. 51342a2b7296SJim Harris */ 51352a2b7296SJim Harris g_unlock_lba_range_done = false; 51362a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 25, 15, unlock_lba_range_done, &ctx1); 51372a2b7296SJim Harris CU_ASSERT(rc == 0); 51382a2b7296SJim Harris poll_threads(); 51392a2b7296SJim Harris 51402a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 51412a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == false); 51422a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.pending_locked_ranges); 51432a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 51442a2b7296SJim Harris CU_ASSERT(range->offset == 35); 51452a2b7296SJim Harris CU_ASSERT(range->length == 10); 51462a2b7296SJim Harris 51472a2b7296SJim Harris /* Unlock 40-59. This should result in 35-44 now getting locked, since there are 51482a2b7296SJim Harris * no longer any active overlapping locks. 51492a2b7296SJim Harris */ 51502a2b7296SJim Harris g_unlock_lba_range_done = false; 51512a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 40, 20, unlock_lba_range_done, &ctx1); 51522a2b7296SJim Harris CU_ASSERT(rc == 0); 51532a2b7296SJim Harris poll_threads(); 51542a2b7296SJim Harris 51552a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 51562a2b7296SJim Harris CU_ASSERT(g_lock_lba_range_done == true); 51572a2b7296SJim Harris CU_ASSERT(TAILQ_EMPTY(&bdev->internal.pending_locked_ranges)); 51582a2b7296SJim Harris range = TAILQ_FIRST(&bdev->internal.locked_ranges); 51592a2b7296SJim Harris SPDK_CU_ASSERT_FATAL(range != NULL); 51602a2b7296SJim Harris CU_ASSERT(range->offset == 35); 51612a2b7296SJim Harris CU_ASSERT(range->length == 10); 51622a2b7296SJim Harris 51632a2b7296SJim Harris /* Finally, unlock 35-44. */ 51642a2b7296SJim Harris g_unlock_lba_range_done = false; 51652a2b7296SJim Harris rc = bdev_unlock_lba_range(desc, io_ch, 35, 10, unlock_lba_range_done, &ctx1); 51662a2b7296SJim Harris CU_ASSERT(rc == 0); 51672a2b7296SJim Harris poll_threads(); 51682a2b7296SJim Harris 51692a2b7296SJim Harris CU_ASSERT(g_unlock_lba_range_done == true); 51702a2b7296SJim Harris CU_ASSERT(TAILQ_EMPTY(&bdev->internal.locked_ranges)); 51712a2b7296SJim Harris 51722a2b7296SJim Harris spdk_put_io_channel(io_ch); 51732a2b7296SJim Harris spdk_bdev_close(desc); 51742a2b7296SJim Harris free_bdev(bdev); 5175107741fcSKonrad Sztyber ut_fini_bdev(); 51762a2b7296SJim Harris } 51772a2b7296SJim Harris 51787cd20dd3SShuhei Matsumoto static void 51799e386832SArtur Paszkiewicz bdev_quiesce_done(void *ctx, int status) 51809e386832SArtur Paszkiewicz { 51819e386832SArtur Paszkiewicz g_lock_lba_range_done = true; 51829e386832SArtur Paszkiewicz } 51839e386832SArtur Paszkiewicz 51849e386832SArtur Paszkiewicz static void 51859e386832SArtur Paszkiewicz bdev_unquiesce_done(void *ctx, int status) 51869e386832SArtur Paszkiewicz { 51879e386832SArtur Paszkiewicz g_unlock_lba_range_done = true; 51889e386832SArtur Paszkiewicz } 51899e386832SArtur Paszkiewicz 51909e386832SArtur Paszkiewicz static void 5191e7912a28SArtur Paszkiewicz bdev_quiesce_done_unquiesce(void *ctx, int status) 5192e7912a28SArtur Paszkiewicz { 5193e7912a28SArtur Paszkiewicz struct spdk_bdev *bdev = ctx; 5194e7912a28SArtur Paszkiewicz int rc; 5195e7912a28SArtur Paszkiewicz 5196e7912a28SArtur Paszkiewicz g_lock_lba_range_done = true; 5197e7912a28SArtur Paszkiewicz 5198e7912a28SArtur Paszkiewicz rc = spdk_bdev_unquiesce(bdev, &bdev_ut_if, bdev_unquiesce_done, NULL); 5199e7912a28SArtur Paszkiewicz CU_ASSERT(rc == 0); 5200e7912a28SArtur Paszkiewicz } 5201e7912a28SArtur Paszkiewicz 5202e7912a28SArtur Paszkiewicz static void 52039e386832SArtur Paszkiewicz bdev_quiesce(void) 52049e386832SArtur Paszkiewicz { 52059e386832SArtur Paszkiewicz struct spdk_bdev *bdev; 52069e386832SArtur Paszkiewicz struct spdk_bdev_desc *desc = NULL; 52079e386832SArtur Paszkiewicz struct spdk_io_channel *io_ch; 52089e386832SArtur Paszkiewicz struct spdk_bdev_channel *channel; 52099e386832SArtur Paszkiewicz struct lba_range *range; 5210effe7a01SArtur Paszkiewicz struct spdk_bdev_io *bdev_io; 52119e386832SArtur Paszkiewicz int ctx1; 52129e386832SArtur Paszkiewicz int rc; 52139e386832SArtur Paszkiewicz 52149e386832SArtur Paszkiewicz ut_init_bdev(NULL); 52159e386832SArtur Paszkiewicz bdev = allocate_bdev("bdev0"); 52169e386832SArtur Paszkiewicz 52179e386832SArtur Paszkiewicz rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 52189e386832SArtur Paszkiewicz CU_ASSERT(rc == 0); 52199e386832SArtur Paszkiewicz CU_ASSERT(desc != NULL); 52209e386832SArtur Paszkiewicz CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 52219e386832SArtur Paszkiewicz io_ch = spdk_bdev_get_io_channel(desc); 52229e386832SArtur Paszkiewicz CU_ASSERT(io_ch != NULL); 52239e386832SArtur Paszkiewicz channel = spdk_io_channel_get_ctx(io_ch); 52249e386832SArtur Paszkiewicz 52259e386832SArtur Paszkiewicz g_lock_lba_range_done = false; 52269e386832SArtur Paszkiewicz rc = spdk_bdev_quiesce(bdev, &bdev_ut_if, bdev_quiesce_done, &ctx1); 52279e386832SArtur Paszkiewicz CU_ASSERT(rc == 0); 52289e386832SArtur Paszkiewicz poll_threads(); 52299e386832SArtur Paszkiewicz 52309e386832SArtur Paszkiewicz CU_ASSERT(g_lock_lba_range_done == true); 52319e386832SArtur Paszkiewicz range = TAILQ_FIRST(&channel->locked_ranges); 52329e386832SArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(range != NULL); 52339e386832SArtur Paszkiewicz CU_ASSERT(range->offset == 0); 52349e386832SArtur Paszkiewicz CU_ASSERT(range->length == bdev->blockcnt); 52359e386832SArtur Paszkiewicz CU_ASSERT(range->owner_ch == NULL); 52369d5dd7ccSArtur Paszkiewicz range = TAILQ_FIRST(&bdev_ut_if.internal.quiesced_ranges); 52379d5dd7ccSArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(range != NULL); 52389d5dd7ccSArtur Paszkiewicz CU_ASSERT(range->offset == 0); 52399d5dd7ccSArtur Paszkiewicz CU_ASSERT(range->length == bdev->blockcnt); 52409d5dd7ccSArtur Paszkiewicz CU_ASSERT(range->owner_ch == NULL); 52419e386832SArtur Paszkiewicz 52429e386832SArtur Paszkiewicz g_unlock_lba_range_done = false; 52439e386832SArtur Paszkiewicz rc = spdk_bdev_unquiesce(bdev, &bdev_ut_if, bdev_unquiesce_done, &ctx1); 52449e386832SArtur Paszkiewicz CU_ASSERT(rc == 0); 52459e386832SArtur Paszkiewicz spdk_delay_us(100); 52469e386832SArtur Paszkiewicz poll_threads(); 52479e386832SArtur Paszkiewicz 52489e386832SArtur Paszkiewicz CU_ASSERT(g_unlock_lba_range_done == true); 52499e386832SArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 52509d5dd7ccSArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&bdev_ut_if.internal.quiesced_ranges)); 52519e386832SArtur Paszkiewicz 52529e386832SArtur Paszkiewicz g_lock_lba_range_done = false; 52539e386832SArtur Paszkiewicz rc = spdk_bdev_quiesce_range(bdev, &bdev_ut_if, 20, 10, bdev_quiesce_done, &ctx1); 52549e386832SArtur Paszkiewicz CU_ASSERT(rc == 0); 52559e386832SArtur Paszkiewicz poll_threads(); 52569e386832SArtur Paszkiewicz 52579e386832SArtur Paszkiewicz CU_ASSERT(g_lock_lba_range_done == true); 52589e386832SArtur Paszkiewicz range = TAILQ_FIRST(&channel->locked_ranges); 52599e386832SArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(range != NULL); 52609e386832SArtur Paszkiewicz CU_ASSERT(range->offset == 20); 52619e386832SArtur Paszkiewicz CU_ASSERT(range->length == 10); 52629e386832SArtur Paszkiewicz CU_ASSERT(range->owner_ch == NULL); 52639d5dd7ccSArtur Paszkiewicz range = TAILQ_FIRST(&bdev_ut_if.internal.quiesced_ranges); 52649d5dd7ccSArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(range != NULL); 52659d5dd7ccSArtur Paszkiewicz CU_ASSERT(range->offset == 20); 52669d5dd7ccSArtur Paszkiewicz CU_ASSERT(range->length == 10); 52679d5dd7ccSArtur Paszkiewicz CU_ASSERT(range->owner_ch == NULL); 52689e386832SArtur Paszkiewicz 52699e386832SArtur Paszkiewicz /* Unlocks must exactly match a lock. */ 52709e386832SArtur Paszkiewicz g_unlock_lba_range_done = false; 52719d5dd7ccSArtur Paszkiewicz rc = spdk_bdev_unquiesce_range(bdev, &bdev_ut_if, 20, 1, bdev_unquiesce_done, &ctx1); 52729d5dd7ccSArtur Paszkiewicz CU_ASSERT(rc == -EINVAL); 52739d5dd7ccSArtur Paszkiewicz CU_ASSERT(g_unlock_lba_range_done == false); 52749d5dd7ccSArtur Paszkiewicz 52759e386832SArtur Paszkiewicz rc = spdk_bdev_unquiesce_range(bdev, &bdev_ut_if, 20, 10, bdev_unquiesce_done, &ctx1); 52769e386832SArtur Paszkiewicz CU_ASSERT(rc == 0); 52779e386832SArtur Paszkiewicz spdk_delay_us(100); 52789e386832SArtur Paszkiewicz poll_threads(); 52799e386832SArtur Paszkiewicz 52809e386832SArtur Paszkiewicz CU_ASSERT(g_unlock_lba_range_done == true); 52819e386832SArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 52829d5dd7ccSArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&bdev_ut_if.internal.quiesced_ranges)); 52839e386832SArtur Paszkiewicz 5284e7912a28SArtur Paszkiewicz /* Test unquiesce from quiesce cb */ 5285e7912a28SArtur Paszkiewicz g_lock_lba_range_done = false; 5286e7912a28SArtur Paszkiewicz g_unlock_lba_range_done = false; 5287e7912a28SArtur Paszkiewicz rc = spdk_bdev_quiesce(bdev, &bdev_ut_if, bdev_quiesce_done_unquiesce, bdev); 5288e7912a28SArtur Paszkiewicz CU_ASSERT(rc == 0); 5289e7912a28SArtur Paszkiewicz poll_threads(); 5290e7912a28SArtur Paszkiewicz 5291e7912a28SArtur Paszkiewicz CU_ASSERT(g_lock_lba_range_done == true); 5292e7912a28SArtur Paszkiewicz CU_ASSERT(g_unlock_lba_range_done == true); 5293e7912a28SArtur Paszkiewicz 5294effe7a01SArtur Paszkiewicz /* Test quiesce with read I/O */ 5295effe7a01SArtur Paszkiewicz g_lock_lba_range_done = false; 5296effe7a01SArtur Paszkiewicz g_unlock_lba_range_done = false; 5297effe7a01SArtur Paszkiewicz g_io_done = false; 5298effe7a01SArtur Paszkiewicz rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 20, 1, io_done, &ctx1); 5299effe7a01SArtur Paszkiewicz CU_ASSERT(rc == 0); 5300effe7a01SArtur Paszkiewicz 5301effe7a01SArtur Paszkiewicz rc = spdk_bdev_quiesce(bdev, &bdev_ut_if, bdev_quiesce_done, &ctx1); 5302effe7a01SArtur Paszkiewicz CU_ASSERT(rc == 0); 5303effe7a01SArtur Paszkiewicz poll_threads(); 5304effe7a01SArtur Paszkiewicz 5305effe7a01SArtur Paszkiewicz CU_ASSERT(g_io_done == false); 5306effe7a01SArtur Paszkiewicz CU_ASSERT(g_lock_lba_range_done == false); 5307effe7a01SArtur Paszkiewicz range = TAILQ_FIRST(&channel->locked_ranges); 5308effe7a01SArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(range != NULL); 5309effe7a01SArtur Paszkiewicz 5310effe7a01SArtur Paszkiewicz stub_complete_io(1); 5311effe7a01SArtur Paszkiewicz spdk_delay_us(100); 5312effe7a01SArtur Paszkiewicz poll_threads(); 5313effe7a01SArtur Paszkiewicz CU_ASSERT(g_io_done == true); 5314effe7a01SArtur Paszkiewicz CU_ASSERT(g_lock_lba_range_done == true); 5315effe7a01SArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&channel->io_locked)); 5316effe7a01SArtur Paszkiewicz 5317effe7a01SArtur Paszkiewicz g_io_done = false; 5318effe7a01SArtur Paszkiewicz rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 20, 1, io_done, &ctx1); 5319effe7a01SArtur Paszkiewicz CU_ASSERT(rc == 0); 5320effe7a01SArtur Paszkiewicz 5321effe7a01SArtur Paszkiewicz bdev_io = TAILQ_FIRST(&channel->io_locked); 5322effe7a01SArtur Paszkiewicz SPDK_CU_ASSERT_FATAL(bdev_io != NULL); 5323effe7a01SArtur Paszkiewicz CU_ASSERT(bdev_io->u.bdev.offset_blocks == 20); 5324effe7a01SArtur Paszkiewicz CU_ASSERT(bdev_io->u.bdev.num_blocks == 1); 5325effe7a01SArtur Paszkiewicz 5326effe7a01SArtur Paszkiewicz rc = spdk_bdev_unquiesce(bdev, &bdev_ut_if, bdev_unquiesce_done, &ctx1); 5327effe7a01SArtur Paszkiewicz CU_ASSERT(rc == 0); 5328effe7a01SArtur Paszkiewicz spdk_delay_us(100); 5329effe7a01SArtur Paszkiewicz poll_threads(); 5330effe7a01SArtur Paszkiewicz 5331effe7a01SArtur Paszkiewicz CU_ASSERT(g_unlock_lba_range_done == true); 5332effe7a01SArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges)); 5333effe7a01SArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&bdev_ut_if.internal.quiesced_ranges)); 5334effe7a01SArtur Paszkiewicz 5335effe7a01SArtur Paszkiewicz CU_ASSERT(TAILQ_EMPTY(&channel->io_locked)); 5336effe7a01SArtur Paszkiewicz spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 5337effe7a01SArtur Paszkiewicz poll_threads(); 5338effe7a01SArtur Paszkiewicz CU_ASSERT(g_io_done == true); 5339effe7a01SArtur Paszkiewicz 53409e386832SArtur Paszkiewicz spdk_put_io_channel(io_ch); 53419e386832SArtur Paszkiewicz spdk_bdev_close(desc); 53429e386832SArtur Paszkiewicz free_bdev(bdev); 53439e386832SArtur Paszkiewicz ut_fini_bdev(); 53449e386832SArtur Paszkiewicz } 53459e386832SArtur Paszkiewicz 53469e386832SArtur Paszkiewicz static void 53477cd20dd3SShuhei Matsumoto abort_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 53487cd20dd3SShuhei Matsumoto { 53497cd20dd3SShuhei Matsumoto g_abort_done = true; 53507cd20dd3SShuhei Matsumoto g_abort_status = bdev_io->internal.status; 53517cd20dd3SShuhei Matsumoto spdk_bdev_free_io(bdev_io); 53527cd20dd3SShuhei Matsumoto } 53537cd20dd3SShuhei Matsumoto 53547cd20dd3SShuhei Matsumoto static void 53557cd20dd3SShuhei Matsumoto bdev_io_abort(void) 53567cd20dd3SShuhei Matsumoto { 53577cd20dd3SShuhei Matsumoto struct spdk_bdev *bdev; 53587cd20dd3SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 53597cd20dd3SShuhei Matsumoto struct spdk_io_channel *io_ch; 536097a5ea57SShuhei Matsumoto struct spdk_bdev_channel *channel; 536197a5ea57SShuhei Matsumoto struct spdk_bdev_mgmt_channel *mgmt_ch; 5362f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 5363b45556e2SChangpeng Liu struct iovec iov[SPDK_BDEV_IO_NUM_CHILD_IOV * 2]; 536497a5ea57SShuhei Matsumoto uint64_t io_ctx1 = 0, io_ctx2 = 0, i; 53657cd20dd3SShuhei Matsumoto int rc; 53667cd20dd3SShuhei Matsumoto 5367f420b9efSZiye Yang spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 5368f420b9efSZiye Yang bdev_opts.bdev_io_pool_size = 7; 5369f420b9efSZiye Yang bdev_opts.bdev_io_cache_size = 2; 5370107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 53717cd20dd3SShuhei Matsumoto 53727cd20dd3SShuhei Matsumoto bdev = allocate_bdev("bdev0"); 53737cd20dd3SShuhei Matsumoto 537475dfecbbSShuhei Matsumoto rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 53757cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 53767cd20dd3SShuhei Matsumoto CU_ASSERT(desc != NULL); 537775dfecbbSShuhei Matsumoto CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 53787cd20dd3SShuhei Matsumoto io_ch = spdk_bdev_get_io_channel(desc); 53797cd20dd3SShuhei Matsumoto CU_ASSERT(io_ch != NULL); 538097a5ea57SShuhei Matsumoto channel = spdk_io_channel_get_ctx(io_ch); 538197a5ea57SShuhei Matsumoto mgmt_ch = channel->shared_resource->mgmt_ch; 53827cd20dd3SShuhei Matsumoto 53837cd20dd3SShuhei Matsumoto g_abort_done = false; 53847cd20dd3SShuhei Matsumoto 53857cd20dd3SShuhei Matsumoto ut_enable_io_type(SPDK_BDEV_IO_TYPE_ABORT, false); 53867cd20dd3SShuhei Matsumoto 53877cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 53887cd20dd3SShuhei Matsumoto CU_ASSERT(rc == -ENOTSUP); 53897cd20dd3SShuhei Matsumoto 53907cd20dd3SShuhei Matsumoto ut_enable_io_type(SPDK_BDEV_IO_TYPE_ABORT, true); 53917cd20dd3SShuhei Matsumoto 53927cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx2, abort_done, NULL); 53937cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 53947cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 53957cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_FAILED); 53967cd20dd3SShuhei Matsumoto 53977cd20dd3SShuhei Matsumoto /* Test the case that the target I/O was successfully aborted. */ 53987cd20dd3SShuhei Matsumoto g_io_done = false; 53997cd20dd3SShuhei Matsumoto 54007cd20dd3SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, &io_ctx1); 54017cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 54027cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == false); 54037cd20dd3SShuhei Matsumoto 54047cd20dd3SShuhei Matsumoto g_abort_done = false; 54057cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 54067cd20dd3SShuhei Matsumoto 54077cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 54087cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 54097cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == true); 54107cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 54117cd20dd3SShuhei Matsumoto stub_complete_io(1); 54127cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 54137cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 54147cd20dd3SShuhei Matsumoto 54157cd20dd3SShuhei Matsumoto /* Test the case that the target I/O was not aborted because it completed 54167cd20dd3SShuhei Matsumoto * in the middle of execution of the abort. 54177cd20dd3SShuhei Matsumoto */ 54187cd20dd3SShuhei Matsumoto g_io_done = false; 54197cd20dd3SShuhei Matsumoto 54207cd20dd3SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, &io_ctx1); 54217cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 54227cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == false); 54237cd20dd3SShuhei Matsumoto 54247cd20dd3SShuhei Matsumoto g_abort_done = false; 54257cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 54267cd20dd3SShuhei Matsumoto 54277cd20dd3SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 54287cd20dd3SShuhei Matsumoto CU_ASSERT(rc == 0); 54297cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == false); 54307cd20dd3SShuhei Matsumoto 54317cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 54327cd20dd3SShuhei Matsumoto stub_complete_io(1); 54337cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_done == true); 54347cd20dd3SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS); 54357cd20dd3SShuhei Matsumoto 54367cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED; 54377cd20dd3SShuhei Matsumoto stub_complete_io(1); 54387cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 54397cd20dd3SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 54407cd20dd3SShuhei Matsumoto 54417cd20dd3SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 54427cd20dd3SShuhei Matsumoto 544397a5ea57SShuhei Matsumoto bdev->optimal_io_boundary = 16; 544497a5ea57SShuhei Matsumoto bdev->split_on_optimal_io_boundary = true; 544597a5ea57SShuhei Matsumoto 544697a5ea57SShuhei Matsumoto /* Test that a single-vector command which is split is aborted correctly. 544797a5ea57SShuhei Matsumoto * Offset 14, length 8, payload 0xF000 544897a5ea57SShuhei Matsumoto * Child - Offset 14, length 2, payload 0xF000 544997a5ea57SShuhei Matsumoto * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 545097a5ea57SShuhei Matsumoto */ 545197a5ea57SShuhei Matsumoto g_io_done = false; 545297a5ea57SShuhei Matsumoto 545397a5ea57SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 8, io_done, &io_ctx1); 545497a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 545597a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == false); 545697a5ea57SShuhei Matsumoto 545797a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 545897a5ea57SShuhei Matsumoto 545997a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 546097a5ea57SShuhei Matsumoto 546197a5ea57SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 546297a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 546397a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == true); 546497a5ea57SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 546597a5ea57SShuhei Matsumoto stub_complete_io(2); 546697a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 546797a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 546897a5ea57SShuhei Matsumoto 546997a5ea57SShuhei Matsumoto /* Test that a multi-vector command that needs to be split by strip and then 547097a5ea57SShuhei Matsumoto * needs to be split is aborted correctly. Abort is requested before the second 547197a5ea57SShuhei Matsumoto * child I/O was submitted. The parent I/O should complete with failure without 547297a5ea57SShuhei Matsumoto * submitting the second child I/O. 547397a5ea57SShuhei Matsumoto */ 5474b45556e2SChangpeng Liu for (i = 0; i < SPDK_BDEV_IO_NUM_CHILD_IOV * 2; i++) { 547597a5ea57SShuhei Matsumoto iov[i].iov_base = (void *)((i + 1) * 0x10000); 547697a5ea57SShuhei Matsumoto iov[i].iov_len = 512; 547797a5ea57SShuhei Matsumoto } 547897a5ea57SShuhei Matsumoto 5479b45556e2SChangpeng Liu bdev->optimal_io_boundary = SPDK_BDEV_IO_NUM_CHILD_IOV; 548097a5ea57SShuhei Matsumoto g_io_done = false; 5481b45556e2SChangpeng Liu rc = spdk_bdev_readv_blocks(desc, io_ch, iov, SPDK_BDEV_IO_NUM_CHILD_IOV * 2, 0, 5482b45556e2SChangpeng Liu SPDK_BDEV_IO_NUM_CHILD_IOV * 2, io_done, &io_ctx1); 548397a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 548497a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == false); 548597a5ea57SShuhei Matsumoto 548697a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 548797a5ea57SShuhei Matsumoto 548897a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 548997a5ea57SShuhei Matsumoto 549097a5ea57SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 549197a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 549297a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == true); 549397a5ea57SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 549497a5ea57SShuhei Matsumoto stub_complete_io(1); 549597a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 549697a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 549797a5ea57SShuhei Matsumoto 549897a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 549997a5ea57SShuhei Matsumoto 550097a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 550197a5ea57SShuhei Matsumoto 550297a5ea57SShuhei Matsumoto bdev->optimal_io_boundary = 16; 550397a5ea57SShuhei Matsumoto g_io_done = false; 550497a5ea57SShuhei Matsumoto 5505153e3344SShuhei Matsumoto /* Test that a single-vector command which is split is aborted correctly. 550697a5ea57SShuhei Matsumoto * Differently from the above, the child abort request will be submitted 550797a5ea57SShuhei Matsumoto * sequentially due to the capacity of spdk_bdev_io. 550897a5ea57SShuhei Matsumoto */ 550997a5ea57SShuhei Matsumoto rc = spdk_bdev_read_blocks(desc, io_ch, (void *)0xF000, 14, 50, io_done, &io_ctx1); 551097a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 551197a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == false); 551297a5ea57SShuhei Matsumoto 551397a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 551497a5ea57SShuhei Matsumoto 551597a5ea57SShuhei Matsumoto g_abort_done = false; 551697a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 551797a5ea57SShuhei Matsumoto 551897a5ea57SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 551997a5ea57SShuhei Matsumoto CU_ASSERT(rc == 0); 552097a5ea57SShuhei Matsumoto CU_ASSERT(!TAILQ_EMPTY(&mgmt_ch->io_wait_queue)); 552197a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 552297a5ea57SShuhei Matsumoto 552397a5ea57SShuhei Matsumoto stub_complete_io(1); 552497a5ea57SShuhei Matsumoto CU_ASSERT(g_io_done == true); 552597a5ea57SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 552697a5ea57SShuhei Matsumoto stub_complete_io(3); 552797a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 552897a5ea57SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 552997a5ea57SShuhei Matsumoto 553097a5ea57SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 553197a5ea57SShuhei Matsumoto 553297a5ea57SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 553397a5ea57SShuhei Matsumoto 5534153e3344SShuhei Matsumoto bdev->split_on_optimal_io_boundary = false; 5535153e3344SShuhei Matsumoto bdev->split_on_write_unit = true; 5536153e3344SShuhei Matsumoto bdev->write_unit_size = 16; 5537153e3344SShuhei Matsumoto 5538153e3344SShuhei Matsumoto /* Test that a single-vector command which is split is aborted correctly. 5539153e3344SShuhei Matsumoto * Offset 16, length 32, payload 0xF000 5540153e3344SShuhei Matsumoto * Child - Offset 16, length 16, payload 0xF000 5541153e3344SShuhei Matsumoto * Child - Offset 32, length 16, payload 0xF000 + 16 * 512 5542153e3344SShuhei Matsumoto * 5543153e3344SShuhei Matsumoto * Use bdev->split_on_write_unit as a split condition. 5544153e3344SShuhei Matsumoto */ 5545153e3344SShuhei Matsumoto g_io_done = false; 5546153e3344SShuhei Matsumoto 5547153e3344SShuhei Matsumoto rc = spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 16, 32, io_done, &io_ctx1); 5548153e3344SShuhei Matsumoto CU_ASSERT(rc == 0); 5549153e3344SShuhei Matsumoto CU_ASSERT(g_io_done == false); 5550153e3344SShuhei Matsumoto 5551153e3344SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 5552153e3344SShuhei Matsumoto 5553153e3344SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5554153e3344SShuhei Matsumoto 5555153e3344SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 5556153e3344SShuhei Matsumoto CU_ASSERT(rc == 0); 5557153e3344SShuhei Matsumoto CU_ASSERT(g_io_done == true); 5558153e3344SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 5559153e3344SShuhei Matsumoto stub_complete_io(2); 5560153e3344SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 5561153e3344SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 5562153e3344SShuhei Matsumoto 5563153e3344SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5564153e3344SShuhei Matsumoto 5565153e3344SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 5566153e3344SShuhei Matsumoto 5567153e3344SShuhei Matsumoto bdev->split_on_write_unit = false; 5568153e3344SShuhei Matsumoto bdev->max_rw_size = 16; 5569153e3344SShuhei Matsumoto 5570153e3344SShuhei Matsumoto /* Test that a single-vector command which is split is aborted correctly. 5571153e3344SShuhei Matsumoto * Use bdev->max_rw_size as a split condition. 5572153e3344SShuhei Matsumoto */ 5573153e3344SShuhei Matsumoto g_io_done = false; 5574153e3344SShuhei Matsumoto 5575153e3344SShuhei Matsumoto rc = spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 0, 32, io_done, &io_ctx1); 5576153e3344SShuhei Matsumoto CU_ASSERT(rc == 0); 5577153e3344SShuhei Matsumoto CU_ASSERT(g_io_done == false); 5578153e3344SShuhei Matsumoto 5579153e3344SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 5580153e3344SShuhei Matsumoto 5581153e3344SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5582153e3344SShuhei Matsumoto 5583153e3344SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 5584153e3344SShuhei Matsumoto CU_ASSERT(rc == 0); 5585153e3344SShuhei Matsumoto CU_ASSERT(g_io_done == true); 5586153e3344SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 5587153e3344SShuhei Matsumoto stub_complete_io(2); 5588153e3344SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 5589153e3344SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 5590153e3344SShuhei Matsumoto 5591153e3344SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5592153e3344SShuhei Matsumoto 5593153e3344SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 5594153e3344SShuhei Matsumoto 5595153e3344SShuhei Matsumoto bdev->max_rw_size = 0; 5596153e3344SShuhei Matsumoto bdev->max_segment_size = 512 * 16; 5597153e3344SShuhei Matsumoto bdev->max_num_segments = 1; 5598153e3344SShuhei Matsumoto 5599153e3344SShuhei Matsumoto /* Test that a single-vector command which is split is aborted correctly. 5600153e3344SShuhei Matsumoto * Use bdev->max_segment_size and bdev->max_num_segments together as split conditions. 5601153e3344SShuhei Matsumoto * 5602153e3344SShuhei Matsumoto * One single-vector command is changed to one two-vectors command, but 5603153e3344SShuhei Matsumoto * bdev->max_num_segments is 1 and it is split into two single-vector commands. 5604153e3344SShuhei Matsumoto */ 5605153e3344SShuhei Matsumoto g_io_done = false; 5606153e3344SShuhei Matsumoto 5607153e3344SShuhei Matsumoto rc = spdk_bdev_write_blocks(desc, io_ch, (void *)0xF000, 0, 32, io_done, &io_ctx1); 5608153e3344SShuhei Matsumoto CU_ASSERT(rc == 0); 5609153e3344SShuhei Matsumoto CU_ASSERT(g_io_done == false); 5610153e3344SShuhei Matsumoto 5611153e3344SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 5612153e3344SShuhei Matsumoto 5613153e3344SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5614153e3344SShuhei Matsumoto 5615153e3344SShuhei Matsumoto rc = spdk_bdev_abort(desc, io_ch, &io_ctx1, abort_done, NULL); 5616153e3344SShuhei Matsumoto CU_ASSERT(rc == 0); 5617153e3344SShuhei Matsumoto CU_ASSERT(g_io_done == true); 5618153e3344SShuhei Matsumoto CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED); 5619153e3344SShuhei Matsumoto stub_complete_io(2); 5620153e3344SShuhei Matsumoto CU_ASSERT(g_abort_done == true); 5621153e3344SShuhei Matsumoto CU_ASSERT(g_abort_status == SPDK_BDEV_IO_STATUS_SUCCESS); 5622153e3344SShuhei Matsumoto 5623153e3344SShuhei Matsumoto g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5624153e3344SShuhei Matsumoto 5625153e3344SShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 5626153e3344SShuhei Matsumoto 56277cd20dd3SShuhei Matsumoto spdk_put_io_channel(io_ch); 56287cd20dd3SShuhei Matsumoto spdk_bdev_close(desc); 56297cd20dd3SShuhei Matsumoto free_bdev(bdev); 5630107741fcSKonrad Sztyber ut_fini_bdev(); 56317cd20dd3SShuhei Matsumoto } 56327cd20dd3SShuhei Matsumoto 5633f420b9efSZiye Yang static void 5634d0b4deabSChangpeng Liu bdev_unmap(void) 5635d0b4deabSChangpeng Liu { 5636d0b4deabSChangpeng Liu struct spdk_bdev *bdev; 5637d0b4deabSChangpeng Liu struct spdk_bdev_desc *desc = NULL; 5638d0b4deabSChangpeng Liu struct spdk_io_channel *ioch; 5639d0b4deabSChangpeng Liu struct spdk_bdev_channel *bdev_ch; 5640d0b4deabSChangpeng Liu struct ut_expected_io *expected_io; 5641d0b4deabSChangpeng Liu struct spdk_bdev_opts bdev_opts = {}; 5642d0b4deabSChangpeng Liu uint32_t i, num_outstanding; 5643d0b4deabSChangpeng Liu uint64_t offset, num_blocks, max_unmap_blocks, num_children; 5644d0b4deabSChangpeng Liu int rc; 5645d0b4deabSChangpeng Liu 5646d0b4deabSChangpeng Liu spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 5647d0b4deabSChangpeng Liu bdev_opts.bdev_io_pool_size = 512; 5648d0b4deabSChangpeng Liu bdev_opts.bdev_io_cache_size = 64; 5649107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 5650d0b4deabSChangpeng Liu 5651d0b4deabSChangpeng Liu bdev = allocate_bdev("bdev"); 5652d0b4deabSChangpeng Liu 5653d0b4deabSChangpeng Liu rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 5654d0b4deabSChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5655d0b4deabSChangpeng Liu SPDK_CU_ASSERT_FATAL(desc != NULL); 5656d0b4deabSChangpeng Liu CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 5657d0b4deabSChangpeng Liu ioch = spdk_bdev_get_io_channel(desc); 5658d0b4deabSChangpeng Liu SPDK_CU_ASSERT_FATAL(ioch != NULL); 5659d0b4deabSChangpeng Liu bdev_ch = spdk_io_channel_get_ctx(ioch); 5660d0b4deabSChangpeng Liu CU_ASSERT(TAILQ_EMPTY(&bdev_ch->io_submitted)); 5661d0b4deabSChangpeng Liu 5662d0b4deabSChangpeng Liu fn_table.submit_request = stub_submit_request; 5663d0b4deabSChangpeng Liu g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5664d0b4deabSChangpeng Liu 5665d0b4deabSChangpeng Liu /* Case 1: First test the request won't be split */ 5666d0b4deabSChangpeng Liu num_blocks = 32; 5667d0b4deabSChangpeng Liu 5668d0b4deabSChangpeng Liu g_io_done = false; 5669d0b4deabSChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_UNMAP, 0, num_blocks, 0); 5670d0b4deabSChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5671d0b4deabSChangpeng Liu rc = spdk_bdev_unmap_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 5672d0b4deabSChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5673d0b4deabSChangpeng Liu CU_ASSERT(g_io_done == false); 5674d0b4deabSChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 5675d0b4deabSChangpeng Liu stub_complete_io(1); 5676d0b4deabSChangpeng Liu CU_ASSERT(g_io_done == true); 5677d0b4deabSChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 5678d0b4deabSChangpeng Liu 5679d0b4deabSChangpeng Liu /* Case 2: Test the split with 2 children requests */ 5680d0b4deabSChangpeng Liu bdev->max_unmap = 8; 5681d0b4deabSChangpeng Liu bdev->max_unmap_segments = 2; 5682d0b4deabSChangpeng Liu max_unmap_blocks = bdev->max_unmap * bdev->max_unmap_segments; 5683d0b4deabSChangpeng Liu num_blocks = max_unmap_blocks * 2; 5684d0b4deabSChangpeng Liu offset = 0; 5685d0b4deabSChangpeng Liu 5686d0b4deabSChangpeng Liu g_io_done = false; 5687d0b4deabSChangpeng Liu for (i = 0; i < 2; i++) { 5688d0b4deabSChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_UNMAP, offset, max_unmap_blocks, 0); 5689d0b4deabSChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5690d0b4deabSChangpeng Liu offset += max_unmap_blocks; 5691d0b4deabSChangpeng Liu } 5692d0b4deabSChangpeng Liu 5693d0b4deabSChangpeng Liu rc = spdk_bdev_unmap_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 5694d0b4deabSChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5695d0b4deabSChangpeng Liu CU_ASSERT(g_io_done == false); 5696d0b4deabSChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 5697d0b4deabSChangpeng Liu stub_complete_io(2); 5698d0b4deabSChangpeng Liu CU_ASSERT(g_io_done == true); 5699d0b4deabSChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 5700d0b4deabSChangpeng Liu 5701d0b4deabSChangpeng Liu /* Case 3: Test the split with 15 children requests, will finish 8 requests first */ 5702d0b4deabSChangpeng Liu num_children = 15; 5703d0b4deabSChangpeng Liu num_blocks = max_unmap_blocks * num_children; 5704d0b4deabSChangpeng Liu g_io_done = false; 5705d0b4deabSChangpeng Liu offset = 0; 5706d0b4deabSChangpeng Liu for (i = 0; i < num_children; i++) { 5707d0b4deabSChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_UNMAP, offset, max_unmap_blocks, 0); 5708d0b4deabSChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5709d0b4deabSChangpeng Liu offset += max_unmap_blocks; 5710d0b4deabSChangpeng Liu } 5711d0b4deabSChangpeng Liu 5712d0b4deabSChangpeng Liu rc = spdk_bdev_unmap_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 5713d0b4deabSChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5714d0b4deabSChangpeng Liu CU_ASSERT(g_io_done == false); 5715d0b4deabSChangpeng Liu 5716d0b4deabSChangpeng Liu while (num_children > 0) { 5717734de260SChangpeng Liu num_outstanding = spdk_min(num_children, SPDK_BDEV_MAX_CHILDREN_UNMAP_WRITE_ZEROES_REQS); 5718d0b4deabSChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == num_outstanding); 5719d0b4deabSChangpeng Liu stub_complete_io(num_outstanding); 5720d0b4deabSChangpeng Liu num_children -= num_outstanding; 5721d0b4deabSChangpeng Liu } 5722d0b4deabSChangpeng Liu CU_ASSERT(g_io_done == true); 5723d0b4deabSChangpeng Liu 5724d0b4deabSChangpeng Liu spdk_put_io_channel(ioch); 5725d0b4deabSChangpeng Liu spdk_bdev_close(desc); 5726d0b4deabSChangpeng Liu free_bdev(bdev); 5727107741fcSKonrad Sztyber ut_fini_bdev(); 5728d0b4deabSChangpeng Liu } 5729d0b4deabSChangpeng Liu 5730d0b4deabSChangpeng Liu static void 5731e7fbdf15SChangpeng Liu bdev_write_zeroes_split_test(void) 5732e7fbdf15SChangpeng Liu { 5733e7fbdf15SChangpeng Liu struct spdk_bdev *bdev; 5734e7fbdf15SChangpeng Liu struct spdk_bdev_desc *desc = NULL; 5735e7fbdf15SChangpeng Liu struct spdk_io_channel *ioch; 5736e7fbdf15SChangpeng Liu struct spdk_bdev_channel *bdev_ch; 5737e7fbdf15SChangpeng Liu struct ut_expected_io *expected_io; 5738e7fbdf15SChangpeng Liu struct spdk_bdev_opts bdev_opts = {}; 5739e7fbdf15SChangpeng Liu uint32_t i, num_outstanding; 5740e7fbdf15SChangpeng Liu uint64_t offset, num_blocks, max_write_zeroes_blocks, num_children; 5741e7fbdf15SChangpeng Liu int rc; 5742e7fbdf15SChangpeng Liu 5743e7fbdf15SChangpeng Liu spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 5744e7fbdf15SChangpeng Liu bdev_opts.bdev_io_pool_size = 512; 5745e7fbdf15SChangpeng Liu bdev_opts.bdev_io_cache_size = 64; 5746107741fcSKonrad Sztyber ut_init_bdev(&bdev_opts); 5747e7fbdf15SChangpeng Liu 5748e7fbdf15SChangpeng Liu bdev = allocate_bdev("bdev"); 5749e7fbdf15SChangpeng Liu 5750e7fbdf15SChangpeng Liu rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 5751e7fbdf15SChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5752e7fbdf15SChangpeng Liu SPDK_CU_ASSERT_FATAL(desc != NULL); 5753e7fbdf15SChangpeng Liu CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 5754e7fbdf15SChangpeng Liu ioch = spdk_bdev_get_io_channel(desc); 5755e7fbdf15SChangpeng Liu SPDK_CU_ASSERT_FATAL(ioch != NULL); 5756e7fbdf15SChangpeng Liu bdev_ch = spdk_io_channel_get_ctx(ioch); 5757e7fbdf15SChangpeng Liu CU_ASSERT(TAILQ_EMPTY(&bdev_ch->io_submitted)); 5758e7fbdf15SChangpeng Liu 5759e7fbdf15SChangpeng Liu fn_table.submit_request = stub_submit_request; 5760e7fbdf15SChangpeng Liu g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 5761e7fbdf15SChangpeng Liu 5762e7fbdf15SChangpeng Liu /* Case 1: First test the request won't be split */ 5763e7fbdf15SChangpeng Liu num_blocks = 32; 5764e7fbdf15SChangpeng Liu 5765e7fbdf15SChangpeng Liu g_io_done = false; 5766e7fbdf15SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, 0, num_blocks, 0); 5767e7fbdf15SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5768e7fbdf15SChangpeng Liu rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 5769e7fbdf15SChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5770e7fbdf15SChangpeng Liu CU_ASSERT(g_io_done == false); 5771e7fbdf15SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 5772e7fbdf15SChangpeng Liu stub_complete_io(1); 5773e7fbdf15SChangpeng Liu CU_ASSERT(g_io_done == true); 5774e7fbdf15SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 5775e7fbdf15SChangpeng Liu 5776e7fbdf15SChangpeng Liu /* Case 2: Test the split with 2 children requests */ 5777e7fbdf15SChangpeng Liu max_write_zeroes_blocks = 8; 5778e7fbdf15SChangpeng Liu bdev->max_write_zeroes = max_write_zeroes_blocks; 5779e7fbdf15SChangpeng Liu num_blocks = max_write_zeroes_blocks * 2; 5780e7fbdf15SChangpeng Liu offset = 0; 5781e7fbdf15SChangpeng Liu 5782e7fbdf15SChangpeng Liu g_io_done = false; 5783e7fbdf15SChangpeng Liu for (i = 0; i < 2; i++) { 5784e7fbdf15SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, offset, max_write_zeroes_blocks, 5785e7fbdf15SChangpeng Liu 0); 5786e7fbdf15SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5787e7fbdf15SChangpeng Liu offset += max_write_zeroes_blocks; 5788e7fbdf15SChangpeng Liu } 5789e7fbdf15SChangpeng Liu 5790e7fbdf15SChangpeng Liu rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 5791e7fbdf15SChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5792e7fbdf15SChangpeng Liu CU_ASSERT(g_io_done == false); 5793e7fbdf15SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 5794e7fbdf15SChangpeng Liu stub_complete_io(2); 5795e7fbdf15SChangpeng Liu CU_ASSERT(g_io_done == true); 5796e7fbdf15SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 5797e7fbdf15SChangpeng Liu 5798e7fbdf15SChangpeng Liu /* Case 3: Test the split with 15 children requests, will finish 8 requests first */ 5799e7fbdf15SChangpeng Liu num_children = 15; 5800e7fbdf15SChangpeng Liu num_blocks = max_write_zeroes_blocks * num_children; 5801e7fbdf15SChangpeng Liu g_io_done = false; 5802e7fbdf15SChangpeng Liu offset = 0; 5803e7fbdf15SChangpeng Liu for (i = 0; i < num_children; i++) { 5804e7fbdf15SChangpeng Liu expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE_ZEROES, offset, max_write_zeroes_blocks, 5805e7fbdf15SChangpeng Liu 0); 5806e7fbdf15SChangpeng Liu TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5807e7fbdf15SChangpeng Liu offset += max_write_zeroes_blocks; 5808e7fbdf15SChangpeng Liu } 5809e7fbdf15SChangpeng Liu 5810e7fbdf15SChangpeng Liu rc = spdk_bdev_write_zeroes_blocks(desc, ioch, 0, num_blocks, io_done, NULL); 5811e7fbdf15SChangpeng Liu CU_ASSERT_EQUAL(rc, 0); 5812e7fbdf15SChangpeng Liu CU_ASSERT(g_io_done == false); 5813e7fbdf15SChangpeng Liu 5814e7fbdf15SChangpeng Liu while (num_children > 0) { 5815e7fbdf15SChangpeng Liu num_outstanding = spdk_min(num_children, SPDK_BDEV_MAX_CHILDREN_UNMAP_WRITE_ZEROES_REQS); 5816e7fbdf15SChangpeng Liu CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == num_outstanding); 5817e7fbdf15SChangpeng Liu stub_complete_io(num_outstanding); 5818e7fbdf15SChangpeng Liu num_children -= num_outstanding; 5819e7fbdf15SChangpeng Liu } 5820e7fbdf15SChangpeng Liu CU_ASSERT(g_io_done == true); 5821e7fbdf15SChangpeng Liu 5822e7fbdf15SChangpeng Liu spdk_put_io_channel(ioch); 5823e7fbdf15SChangpeng Liu spdk_bdev_close(desc); 5824e7fbdf15SChangpeng Liu free_bdev(bdev); 5825107741fcSKonrad Sztyber ut_fini_bdev(); 5826e7fbdf15SChangpeng Liu } 5827e7fbdf15SChangpeng Liu 5828e7fbdf15SChangpeng Liu static void 5829f420b9efSZiye Yang bdev_set_options_test(void) 5830f420b9efSZiye Yang { 5831f420b9efSZiye Yang struct spdk_bdev_opts bdev_opts = {}; 5832f420b9efSZiye Yang int rc; 5833f420b9efSZiye Yang 5834f420b9efSZiye Yang /* Case1: Do not set opts_size */ 5835f420b9efSZiye Yang rc = spdk_bdev_set_opts(&bdev_opts); 5836f420b9efSZiye Yang CU_ASSERT(rc == -1); 5837f420b9efSZiye Yang } 5838f420b9efSZiye Yang 5839c3a58489SAlexey Marchuk static struct spdk_memory_domain *g_bdev_memory_domain = (struct spdk_memory_domain *) 0xf00df00d; 5840c3a58489SAlexey Marchuk 5841c3a58489SAlexey Marchuk static int 5842c3a58489SAlexey Marchuk test_bdev_get_supported_dma_device_types_op(void *ctx, struct spdk_memory_domain **domains, 5843c3a58489SAlexey Marchuk int array_size) 5844c3a58489SAlexey Marchuk { 5845c3a58489SAlexey Marchuk if (array_size > 0 && domains) { 5846c3a58489SAlexey Marchuk domains[0] = g_bdev_memory_domain; 5847c3a58489SAlexey Marchuk } 5848c3a58489SAlexey Marchuk 5849c3a58489SAlexey Marchuk return 1; 5850c3a58489SAlexey Marchuk } 5851c3a58489SAlexey Marchuk 5852c3a58489SAlexey Marchuk static void 5853c3a58489SAlexey Marchuk bdev_get_memory_domains(void) 5854c3a58489SAlexey Marchuk { 5855c3a58489SAlexey Marchuk struct spdk_bdev_fn_table fn_table = { 5856c3a58489SAlexey Marchuk .get_memory_domains = test_bdev_get_supported_dma_device_types_op 5857c3a58489SAlexey Marchuk }; 5858c3a58489SAlexey Marchuk struct spdk_bdev bdev = { .fn_table = &fn_table }; 5859c3a58489SAlexey Marchuk struct spdk_memory_domain *domains[2] = {}; 5860c3a58489SAlexey Marchuk int rc; 5861c3a58489SAlexey Marchuk 5862c3a58489SAlexey Marchuk /* bdev is NULL */ 5863c3a58489SAlexey Marchuk rc = spdk_bdev_get_memory_domains(NULL, domains, 2); 5864c3a58489SAlexey Marchuk CU_ASSERT(rc == -EINVAL); 5865c3a58489SAlexey Marchuk 5866c3a58489SAlexey Marchuk /* domains is NULL */ 5867c3a58489SAlexey Marchuk rc = spdk_bdev_get_memory_domains(&bdev, NULL, 2); 5868c3a58489SAlexey Marchuk CU_ASSERT(rc == 1); 5869c3a58489SAlexey Marchuk 5870c3a58489SAlexey Marchuk /* array size is 0 */ 5871c3a58489SAlexey Marchuk rc = spdk_bdev_get_memory_domains(&bdev, domains, 0); 5872c3a58489SAlexey Marchuk CU_ASSERT(rc == 1); 5873c3a58489SAlexey Marchuk 5874c3a58489SAlexey Marchuk /* get_supported_dma_device_types op is set */ 5875c3a58489SAlexey Marchuk rc = spdk_bdev_get_memory_domains(&bdev, domains, 2); 5876c3a58489SAlexey Marchuk CU_ASSERT(rc == 1); 5877c3a58489SAlexey Marchuk CU_ASSERT(domains[0] == g_bdev_memory_domain); 5878c3a58489SAlexey Marchuk 5879c3a58489SAlexey Marchuk /* get_supported_dma_device_types op is not set */ 5880c3a58489SAlexey Marchuk fn_table.get_memory_domains = NULL; 5881c3a58489SAlexey Marchuk rc = spdk_bdev_get_memory_domains(&bdev, domains, 2); 5882c3a58489SAlexey Marchuk CU_ASSERT(rc == 0); 5883c3a58489SAlexey Marchuk } 5884c3a58489SAlexey Marchuk 5885ac6f2bddSAlexey Marchuk static void 5886442e13c0SJonas Pfefferle _bdev_io_ext(struct spdk_bdev_ext_io_opts *ext_io_opts) 5887442e13c0SJonas Pfefferle { 5888442e13c0SJonas Pfefferle struct spdk_bdev *bdev; 5889442e13c0SJonas Pfefferle struct spdk_bdev_desc *desc = NULL; 5890442e13c0SJonas Pfefferle struct spdk_io_channel *io_ch; 5891442e13c0SJonas Pfefferle char io_buf[512]; 5892442e13c0SJonas Pfefferle struct iovec iov = { .iov_base = io_buf, .iov_len = 512 }; 5893442e13c0SJonas Pfefferle struct ut_expected_io *expected_io; 5894442e13c0SJonas Pfefferle int rc; 5895442e13c0SJonas Pfefferle 5896107741fcSKonrad Sztyber ut_init_bdev(NULL); 5897442e13c0SJonas Pfefferle 5898442e13c0SJonas Pfefferle bdev = allocate_bdev("bdev0"); 5899442e13c0SJonas Pfefferle bdev->md_interleave = false; 5900442e13c0SJonas Pfefferle bdev->md_len = 8; 5901442e13c0SJonas Pfefferle 5902442e13c0SJonas Pfefferle rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 5903442e13c0SJonas Pfefferle CU_ASSERT(rc == 0); 5904442e13c0SJonas Pfefferle SPDK_CU_ASSERT_FATAL(desc != NULL); 5905442e13c0SJonas Pfefferle CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 5906442e13c0SJonas Pfefferle io_ch = spdk_bdev_get_io_channel(desc); 5907442e13c0SJonas Pfefferle CU_ASSERT(io_ch != NULL); 5908442e13c0SJonas Pfefferle 5909442e13c0SJonas Pfefferle /* read */ 5910442e13c0SJonas Pfefferle g_io_done = false; 5911442e13c0SJonas Pfefferle expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 32, 14, 1); 5912442e13c0SJonas Pfefferle if (ext_io_opts) { 5913442e13c0SJonas Pfefferle expected_io->md_buf = ext_io_opts->metadata; 5914442e13c0SJonas Pfefferle } 5915442e13c0SJonas Pfefferle ut_expected_io_set_iov(expected_io, 0, iov.iov_base, iov.iov_len); 5916442e13c0SJonas Pfefferle TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5917442e13c0SJonas Pfefferle 5918442e13c0SJonas Pfefferle rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, ext_io_opts); 5919442e13c0SJonas Pfefferle 5920442e13c0SJonas Pfefferle CU_ASSERT(rc == 0); 5921442e13c0SJonas Pfefferle CU_ASSERT(g_io_done == false); 5922442e13c0SJonas Pfefferle CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 5923442e13c0SJonas Pfefferle stub_complete_io(1); 5924442e13c0SJonas Pfefferle CU_ASSERT(g_io_done == true); 5925442e13c0SJonas Pfefferle 5926442e13c0SJonas Pfefferle /* write */ 5927442e13c0SJonas Pfefferle g_io_done = false; 5928442e13c0SJonas Pfefferle expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 1); 5929442e13c0SJonas Pfefferle if (ext_io_opts) { 5930442e13c0SJonas Pfefferle expected_io->md_buf = ext_io_opts->metadata; 5931442e13c0SJonas Pfefferle } 5932442e13c0SJonas Pfefferle ut_expected_io_set_iov(expected_io, 0, iov.iov_base, iov.iov_len); 5933442e13c0SJonas Pfefferle TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 5934442e13c0SJonas Pfefferle 5935442e13c0SJonas Pfefferle rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, ext_io_opts); 5936442e13c0SJonas Pfefferle 5937442e13c0SJonas Pfefferle CU_ASSERT(rc == 0); 5938442e13c0SJonas Pfefferle CU_ASSERT(g_io_done == false); 5939442e13c0SJonas Pfefferle CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 5940442e13c0SJonas Pfefferle stub_complete_io(1); 5941442e13c0SJonas Pfefferle CU_ASSERT(g_io_done == true); 5942442e13c0SJonas Pfefferle 5943442e13c0SJonas Pfefferle spdk_put_io_channel(io_ch); 5944442e13c0SJonas Pfefferle spdk_bdev_close(desc); 5945442e13c0SJonas Pfefferle free_bdev(bdev); 5946107741fcSKonrad Sztyber ut_fini_bdev(); 5947442e13c0SJonas Pfefferle 5948442e13c0SJonas Pfefferle } 5949442e13c0SJonas Pfefferle 5950442e13c0SJonas Pfefferle static void 5951442e13c0SJonas Pfefferle bdev_io_ext(void) 5952442e13c0SJonas Pfefferle { 5953442e13c0SJonas Pfefferle struct spdk_bdev_ext_io_opts ext_io_opts = { 5954442e13c0SJonas Pfefferle .metadata = (void *)0xFF000000, 5955bbd27a75SSlawomir Ptak .size = sizeof(ext_io_opts), 5956bbd27a75SSlawomir Ptak .dif_check_flags_exclude_mask = 0 5957442e13c0SJonas Pfefferle }; 5958442e13c0SJonas Pfefferle 5959442e13c0SJonas Pfefferle _bdev_io_ext(&ext_io_opts); 5960442e13c0SJonas Pfefferle } 5961442e13c0SJonas Pfefferle 5962442e13c0SJonas Pfefferle static void 5963442e13c0SJonas Pfefferle bdev_io_ext_no_opts(void) 5964442e13c0SJonas Pfefferle { 5965442e13c0SJonas Pfefferle _bdev_io_ext(NULL); 5966442e13c0SJonas Pfefferle } 5967442e13c0SJonas Pfefferle 5968442e13c0SJonas Pfefferle static void 5969442e13c0SJonas Pfefferle bdev_io_ext_invalid_opts(void) 5970442e13c0SJonas Pfefferle { 5971442e13c0SJonas Pfefferle struct spdk_bdev *bdev; 5972442e13c0SJonas Pfefferle struct spdk_bdev_desc *desc = NULL; 5973442e13c0SJonas Pfefferle struct spdk_io_channel *io_ch; 5974442e13c0SJonas Pfefferle char io_buf[512]; 5975442e13c0SJonas Pfefferle struct iovec iov = { .iov_base = io_buf, .iov_len = 512 }; 5976442e13c0SJonas Pfefferle struct spdk_bdev_ext_io_opts ext_io_opts = { 5977442e13c0SJonas Pfefferle .metadata = (void *)0xFF000000, 5978bbd27a75SSlawomir Ptak .size = sizeof(ext_io_opts), 5979bbd27a75SSlawomir Ptak .dif_check_flags_exclude_mask = 0 5980442e13c0SJonas Pfefferle }; 5981442e13c0SJonas Pfefferle int rc; 5982442e13c0SJonas Pfefferle 5983107741fcSKonrad Sztyber ut_init_bdev(NULL); 5984442e13c0SJonas Pfefferle 5985442e13c0SJonas Pfefferle bdev = allocate_bdev("bdev0"); 5986442e13c0SJonas Pfefferle bdev->md_interleave = false; 5987442e13c0SJonas Pfefferle bdev->md_len = 8; 5988442e13c0SJonas Pfefferle 5989442e13c0SJonas Pfefferle rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 5990442e13c0SJonas Pfefferle CU_ASSERT(rc == 0); 5991442e13c0SJonas Pfefferle SPDK_CU_ASSERT_FATAL(desc != NULL); 5992442e13c0SJonas Pfefferle CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 5993442e13c0SJonas Pfefferle io_ch = spdk_bdev_get_io_channel(desc); 5994442e13c0SJonas Pfefferle CU_ASSERT(io_ch != NULL); 5995442e13c0SJonas Pfefferle 5996442e13c0SJonas Pfefferle /* Test invalid ext_opts size */ 5997442e13c0SJonas Pfefferle ext_io_opts.size = 0; 5998442e13c0SJonas Pfefferle rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 5999442e13c0SJonas Pfefferle CU_ASSERT(rc == -EINVAL); 6000442e13c0SJonas Pfefferle rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 6001442e13c0SJonas Pfefferle CU_ASSERT(rc == -EINVAL); 6002442e13c0SJonas Pfefferle 6003442e13c0SJonas Pfefferle ext_io_opts.size = sizeof(ext_io_opts) * 2; 6004442e13c0SJonas Pfefferle rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 6005442e13c0SJonas Pfefferle CU_ASSERT(rc == -EINVAL); 6006442e13c0SJonas Pfefferle rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 6007442e13c0SJonas Pfefferle CU_ASSERT(rc == -EINVAL); 6008442e13c0SJonas Pfefferle 6009442e13c0SJonas Pfefferle ext_io_opts.size = offsetof(struct spdk_bdev_ext_io_opts, metadata) + 6010442e13c0SJonas Pfefferle sizeof(ext_io_opts.metadata) - 1; 6011442e13c0SJonas Pfefferle rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 6012442e13c0SJonas Pfefferle CU_ASSERT(rc == -EINVAL); 6013442e13c0SJonas Pfefferle rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 6014442e13c0SJonas Pfefferle CU_ASSERT(rc == -EINVAL); 6015442e13c0SJonas Pfefferle 6016442e13c0SJonas Pfefferle spdk_put_io_channel(io_ch); 6017442e13c0SJonas Pfefferle spdk_bdev_close(desc); 6018442e13c0SJonas Pfefferle free_bdev(bdev); 6019107741fcSKonrad Sztyber ut_fini_bdev(); 6020442e13c0SJonas Pfefferle } 6021442e13c0SJonas Pfefferle 6022442e13c0SJonas Pfefferle static void 6023442e13c0SJonas Pfefferle bdev_io_ext_split(void) 6024ac6f2bddSAlexey Marchuk { 6025ac6f2bddSAlexey Marchuk struct spdk_bdev *bdev; 6026ac6f2bddSAlexey Marchuk struct spdk_bdev_desc *desc = NULL; 6027ac6f2bddSAlexey Marchuk struct spdk_io_channel *io_ch; 60281299439fSAlexey Marchuk char io_buf[512]; 60291299439fSAlexey Marchuk struct iovec iov = { .iov_base = io_buf, .iov_len = 512 }; 6030ac6f2bddSAlexey Marchuk struct ut_expected_io *expected_io; 6031ac6f2bddSAlexey Marchuk struct spdk_bdev_ext_io_opts ext_io_opts = { 60328e7688c5SAlexey Marchuk .metadata = (void *)0xFF000000, 6033bbd27a75SSlawomir Ptak .size = sizeof(ext_io_opts), 6034bbd27a75SSlawomir Ptak .dif_check_flags_exclude_mask = 0 6035ac6f2bddSAlexey Marchuk }; 6036ac6f2bddSAlexey Marchuk int rc; 6037ac6f2bddSAlexey Marchuk 6038107741fcSKonrad Sztyber ut_init_bdev(NULL); 6039ac6f2bddSAlexey Marchuk 6040ac6f2bddSAlexey Marchuk bdev = allocate_bdev("bdev0"); 6041ac6f2bddSAlexey Marchuk bdev->md_interleave = false; 6042ac6f2bddSAlexey Marchuk bdev->md_len = 8; 6043ac6f2bddSAlexey Marchuk 6044ac6f2bddSAlexey Marchuk rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 6045ac6f2bddSAlexey Marchuk CU_ASSERT(rc == 0); 6046ac6f2bddSAlexey Marchuk SPDK_CU_ASSERT_FATAL(desc != NULL); 6047ac6f2bddSAlexey Marchuk CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 6048ac6f2bddSAlexey Marchuk io_ch = spdk_bdev_get_io_channel(desc); 6049ac6f2bddSAlexey Marchuk CU_ASSERT(io_ch != NULL); 6050ac6f2bddSAlexey Marchuk 6051442e13c0SJonas Pfefferle /* Check that IO request with ext_opts and metadata is split correctly 60528e7688c5SAlexey Marchuk * Offset 14, length 8, payload 0xF000 60538e7688c5SAlexey Marchuk * Child - Offset 14, length 2, payload 0xF000 60548e7688c5SAlexey Marchuk * Child - Offset 16, length 6, payload 0xF000 + 2 * 512 60558e7688c5SAlexey Marchuk */ 60568e7688c5SAlexey Marchuk bdev->optimal_io_boundary = 16; 60578e7688c5SAlexey Marchuk bdev->split_on_optimal_io_boundary = true; 60588e7688c5SAlexey Marchuk bdev->md_interleave = false; 60598e7688c5SAlexey Marchuk bdev->md_len = 8; 60608e7688c5SAlexey Marchuk 60618e7688c5SAlexey Marchuk iov.iov_base = (void *)0xF000; 60628e7688c5SAlexey Marchuk iov.iov_len = 4096; 60638e7688c5SAlexey Marchuk memset(&ext_io_opts, 0, sizeof(ext_io_opts)); 60648e7688c5SAlexey Marchuk ext_io_opts.metadata = (void *)0xFF000000; 60658e7688c5SAlexey Marchuk ext_io_opts.size = sizeof(ext_io_opts); 60668e7688c5SAlexey Marchuk g_io_done = false; 60678e7688c5SAlexey Marchuk 60688e7688c5SAlexey Marchuk /* read */ 60698e7688c5SAlexey Marchuk expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1); 60708e7688c5SAlexey Marchuk expected_io->md_buf = ext_io_opts.metadata; 60718e7688c5SAlexey Marchuk ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512); 60728e7688c5SAlexey Marchuk TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 60738e7688c5SAlexey Marchuk 60748e7688c5SAlexey Marchuk expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1); 60758e7688c5SAlexey Marchuk expected_io->md_buf = ext_io_opts.metadata + 2 * 8; 60768e7688c5SAlexey Marchuk ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512); 60778e7688c5SAlexey Marchuk TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 60788e7688c5SAlexey Marchuk 60798e7688c5SAlexey Marchuk rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 14, 8, io_done, NULL, &ext_io_opts); 60808e7688c5SAlexey Marchuk CU_ASSERT(rc == 0); 60818e7688c5SAlexey Marchuk CU_ASSERT(g_io_done == false); 60828e7688c5SAlexey Marchuk 60838e7688c5SAlexey Marchuk CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 60848e7688c5SAlexey Marchuk stub_complete_io(2); 60858e7688c5SAlexey Marchuk CU_ASSERT(g_io_done == true); 60868e7688c5SAlexey Marchuk CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 60878e7688c5SAlexey Marchuk 60888e7688c5SAlexey Marchuk /* write */ 60898e7688c5SAlexey Marchuk g_io_done = false; 60908e7688c5SAlexey Marchuk expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 1); 60918e7688c5SAlexey Marchuk expected_io->md_buf = ext_io_opts.metadata; 60928e7688c5SAlexey Marchuk ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512); 60938e7688c5SAlexey Marchuk TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 60948e7688c5SAlexey Marchuk 60958e7688c5SAlexey Marchuk expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 6, 1); 60968e7688c5SAlexey Marchuk expected_io->md_buf = ext_io_opts.metadata + 2 * 8; 60978e7688c5SAlexey Marchuk ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512); 60988e7688c5SAlexey Marchuk TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 60998e7688c5SAlexey Marchuk 61008e7688c5SAlexey Marchuk rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 14, 8, io_done, NULL, &ext_io_opts); 61018e7688c5SAlexey Marchuk CU_ASSERT(rc == 0); 61028e7688c5SAlexey Marchuk CU_ASSERT(g_io_done == false); 61038e7688c5SAlexey Marchuk 61048e7688c5SAlexey Marchuk CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 61058e7688c5SAlexey Marchuk stub_complete_io(2); 61068e7688c5SAlexey Marchuk CU_ASSERT(g_io_done == true); 61078e7688c5SAlexey Marchuk CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 61088e7688c5SAlexey Marchuk 6109442e13c0SJonas Pfefferle spdk_put_io_channel(io_ch); 6110442e13c0SJonas Pfefferle spdk_bdev_close(desc); 6111442e13c0SJonas Pfefferle free_bdev(bdev); 6112107741fcSKonrad Sztyber ut_fini_bdev(); 6113442e13c0SJonas Pfefferle } 6114442e13c0SJonas Pfefferle 6115442e13c0SJonas Pfefferle static void 6116442e13c0SJonas Pfefferle bdev_io_ext_bounce_buffer(void) 6117442e13c0SJonas Pfefferle { 6118442e13c0SJonas Pfefferle struct spdk_bdev *bdev; 6119442e13c0SJonas Pfefferle struct spdk_bdev_desc *desc = NULL; 6120442e13c0SJonas Pfefferle struct spdk_io_channel *io_ch; 6121442e13c0SJonas Pfefferle char io_buf[512]; 6122442e13c0SJonas Pfefferle struct iovec iov = { .iov_base = io_buf, .iov_len = 512 }; 612328bcf6a7SKonrad Sztyber struct ut_expected_io *expected_io, *aux_io; 6124442e13c0SJonas Pfefferle struct spdk_bdev_ext_io_opts ext_io_opts = { 6125442e13c0SJonas Pfefferle .metadata = (void *)0xFF000000, 6126bbd27a75SSlawomir Ptak .size = sizeof(ext_io_opts), 6127bbd27a75SSlawomir Ptak .dif_check_flags_exclude_mask = 0 6128442e13c0SJonas Pfefferle }; 6129442e13c0SJonas Pfefferle int rc; 6130442e13c0SJonas Pfefferle 6131107741fcSKonrad Sztyber ut_init_bdev(NULL); 6132442e13c0SJonas Pfefferle 6133442e13c0SJonas Pfefferle bdev = allocate_bdev("bdev0"); 6134442e13c0SJonas Pfefferle bdev->md_interleave = false; 6135442e13c0SJonas Pfefferle bdev->md_len = 8; 6136442e13c0SJonas Pfefferle 6137442e13c0SJonas Pfefferle rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 6138442e13c0SJonas Pfefferle CU_ASSERT(rc == 0); 6139442e13c0SJonas Pfefferle SPDK_CU_ASSERT_FATAL(desc != NULL); 6140442e13c0SJonas Pfefferle CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 6141442e13c0SJonas Pfefferle io_ch = spdk_bdev_get_io_channel(desc); 6142442e13c0SJonas Pfefferle CU_ASSERT(io_ch != NULL); 6143442e13c0SJonas Pfefferle 6144442e13c0SJonas Pfefferle /* Verify data pull/push 6145442e13c0SJonas Pfefferle * bdev doesn't support memory domains, so buffers from bdev memory pool will be used */ 61461299439fSAlexey Marchuk ext_io_opts.memory_domain = (struct spdk_memory_domain *)0xdeadbeef; 61471299439fSAlexey Marchuk 6148442e13c0SJonas Pfefferle /* read */ 61491299439fSAlexey Marchuk g_io_done = false; 61501299439fSAlexey Marchuk expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 32, 14, 1); 61511299439fSAlexey Marchuk ut_expected_io_set_iov(expected_io, 0, iov.iov_base, iov.iov_len); 61521299439fSAlexey Marchuk TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 61531299439fSAlexey Marchuk 61541299439fSAlexey Marchuk rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 61551299439fSAlexey Marchuk 61561299439fSAlexey Marchuk CU_ASSERT(rc == 0); 61571299439fSAlexey Marchuk CU_ASSERT(g_io_done == false); 61581299439fSAlexey Marchuk CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 61591299439fSAlexey Marchuk stub_complete_io(1); 61601299439fSAlexey Marchuk CU_ASSERT(g_memory_domain_push_data_called == true); 61611299439fSAlexey Marchuk CU_ASSERT(g_io_done == true); 61621299439fSAlexey Marchuk 6163442e13c0SJonas Pfefferle /* write */ 61641299439fSAlexey Marchuk g_io_done = false; 61651299439fSAlexey Marchuk expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 1); 61661299439fSAlexey Marchuk ut_expected_io_set_iov(expected_io, 0, iov.iov_base, iov.iov_len); 61671299439fSAlexey Marchuk TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 61681299439fSAlexey Marchuk 61691299439fSAlexey Marchuk rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 61701299439fSAlexey Marchuk 61711299439fSAlexey Marchuk CU_ASSERT(rc == 0); 61721299439fSAlexey Marchuk CU_ASSERT(g_memory_domain_pull_data_called == true); 61731299439fSAlexey Marchuk CU_ASSERT(g_io_done == false); 61741299439fSAlexey Marchuk CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 61751299439fSAlexey Marchuk stub_complete_io(1); 61761299439fSAlexey Marchuk CU_ASSERT(g_io_done == true); 61771299439fSAlexey Marchuk 617828bcf6a7SKonrad Sztyber /* Verify the request is queued after receiving ENOMEM from pull */ 617928bcf6a7SKonrad Sztyber g_io_done = false; 618028bcf6a7SKonrad Sztyber aux_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 1); 618128bcf6a7SKonrad Sztyber ut_expected_io_set_iov(aux_io, 0, iov.iov_base, iov.iov_len); 618228bcf6a7SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, aux_io, link); 618328bcf6a7SKonrad Sztyber rc = spdk_bdev_writev_blocks(desc, io_ch, &iov, 1, 32, 14, io_done, NULL); 618428bcf6a7SKonrad Sztyber CU_ASSERT(rc == 0); 618528bcf6a7SKonrad Sztyber CU_ASSERT(g_io_done == false); 618628bcf6a7SKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 618728bcf6a7SKonrad Sztyber 618828bcf6a7SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 1); 618928bcf6a7SKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, iov.iov_base, iov.iov_len); 619028bcf6a7SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 619128bcf6a7SKonrad Sztyber 619228bcf6a7SKonrad Sztyber MOCK_SET(spdk_memory_domain_pull_data, -ENOMEM); 619328bcf6a7SKonrad Sztyber rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 619428bcf6a7SKonrad Sztyber CU_ASSERT(rc == 0); 619528bcf6a7SKonrad Sztyber CU_ASSERT(g_io_done == false); 619628bcf6a7SKonrad Sztyber /* The second IO has been queued */ 619728bcf6a7SKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 619828bcf6a7SKonrad Sztyber 619928bcf6a7SKonrad Sztyber MOCK_CLEAR(spdk_memory_domain_pull_data); 620028bcf6a7SKonrad Sztyber g_memory_domain_pull_data_called = false; 620128bcf6a7SKonrad Sztyber stub_complete_io(1); 620228bcf6a7SKonrad Sztyber CU_ASSERT(g_io_done == true); 620328bcf6a7SKonrad Sztyber CU_ASSERT(g_memory_domain_pull_data_called == true); 620428bcf6a7SKonrad Sztyber /* The second IO should be submitted now */ 620528bcf6a7SKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 620628bcf6a7SKonrad Sztyber g_io_done = false; 620728bcf6a7SKonrad Sztyber stub_complete_io(1); 620828bcf6a7SKonrad Sztyber CU_ASSERT(g_io_done == true); 620928bcf6a7SKonrad Sztyber 6210f8a33650SKonrad Sztyber /* Verify the request is queued after receiving ENOMEM from push */ 6211f8a33650SKonrad Sztyber g_io_done = false; 6212f8a33650SKonrad Sztyber expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 32, 14, 1); 6213f8a33650SKonrad Sztyber ut_expected_io_set_iov(expected_io, 0, iov.iov_base, iov.iov_len); 6214f8a33650SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 6215f8a33650SKonrad Sztyber 6216f8a33650SKonrad Sztyber MOCK_SET(spdk_memory_domain_push_data, -ENOMEM); 6217f8a33650SKonrad Sztyber rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts); 6218f8a33650SKonrad Sztyber CU_ASSERT(rc == 0); 6219f8a33650SKonrad Sztyber CU_ASSERT(g_io_done == false); 6220f8a33650SKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 6221f8a33650SKonrad Sztyber 6222f8a33650SKonrad Sztyber aux_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 1); 6223f8a33650SKonrad Sztyber ut_expected_io_set_iov(aux_io, 0, iov.iov_base, iov.iov_len); 6224f8a33650SKonrad Sztyber TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, aux_io, link); 6225f8a33650SKonrad Sztyber rc = spdk_bdev_writev_blocks(desc, io_ch, &iov, 1, 32, 14, io_done, NULL); 6226f8a33650SKonrad Sztyber CU_ASSERT(rc == 0); 6227f8a33650SKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2); 6228f8a33650SKonrad Sztyber 6229f8a33650SKonrad Sztyber stub_complete_io(1); 6230f8a33650SKonrad Sztyber /* The IO isn't done yet, it's still waiting on push */ 6231f8a33650SKonrad Sztyber CU_ASSERT(g_io_done == false); 6232f8a33650SKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 6233f8a33650SKonrad Sztyber MOCK_CLEAR(spdk_memory_domain_push_data); 6234f8a33650SKonrad Sztyber g_memory_domain_push_data_called = false; 6235f8a33650SKonrad Sztyber /* Completing the second IO should also trigger push on the first one */ 6236f8a33650SKonrad Sztyber stub_complete_io(1); 6237f8a33650SKonrad Sztyber CU_ASSERT(g_io_done == true); 6238f8a33650SKonrad Sztyber CU_ASSERT(g_memory_domain_push_data_called == true); 6239f8a33650SKonrad Sztyber CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 6240f8a33650SKonrad Sztyber 6241ac6f2bddSAlexey Marchuk spdk_put_io_channel(io_ch); 6242ac6f2bddSAlexey Marchuk spdk_bdev_close(desc); 6243ac6f2bddSAlexey Marchuk free_bdev(bdev); 6244107741fcSKonrad Sztyber ut_fini_bdev(); 6245ac6f2bddSAlexey Marchuk } 6246ac6f2bddSAlexey Marchuk 624779415753SKonrad Sztyber static void 624879415753SKonrad Sztyber bdev_register_uuid_alias(void) 624979415753SKonrad Sztyber { 625079415753SKonrad Sztyber struct spdk_bdev *bdev, *second; 625179415753SKonrad Sztyber char uuid[SPDK_UUID_STRING_LEN]; 625279415753SKonrad Sztyber int rc; 625379415753SKonrad Sztyber 6254107741fcSKonrad Sztyber ut_init_bdev(NULL); 625579415753SKonrad Sztyber bdev = allocate_bdev("bdev0"); 625679415753SKonrad Sztyber 625779415753SKonrad Sztyber /* Make sure an UUID was generated */ 625895a367d6SArtur Paszkiewicz CU_ASSERT_FALSE(spdk_uuid_is_null(&bdev->uuid)); 625979415753SKonrad Sztyber 626079415753SKonrad Sztyber /* Check that an UUID alias was registered */ 626179415753SKonrad Sztyber spdk_uuid_fmt_lower(uuid, sizeof(uuid), &bdev->uuid); 626279415753SKonrad Sztyber CU_ASSERT_EQUAL(spdk_bdev_get_by_name(uuid), bdev); 626379415753SKonrad Sztyber 626479415753SKonrad Sztyber /* Unregister the bdev */ 626579415753SKonrad Sztyber spdk_bdev_unregister(bdev, NULL, NULL); 626679415753SKonrad Sztyber poll_threads(); 626779415753SKonrad Sztyber CU_ASSERT_PTR_NULL(spdk_bdev_get_by_name(uuid)); 626879415753SKonrad Sztyber 626979415753SKonrad Sztyber /* Check the same, but this time register the bdev with non-zero UUID */ 627079415753SKonrad Sztyber rc = spdk_bdev_register(bdev); 627179415753SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 627279415753SKonrad Sztyber CU_ASSERT_EQUAL(spdk_bdev_get_by_name(uuid), bdev); 627379415753SKonrad Sztyber 627479415753SKonrad Sztyber /* Unregister the bdev */ 627579415753SKonrad Sztyber spdk_bdev_unregister(bdev, NULL, NULL); 627679415753SKonrad Sztyber poll_threads(); 627779415753SKonrad Sztyber CU_ASSERT_PTR_NULL(spdk_bdev_get_by_name(uuid)); 627879415753SKonrad Sztyber 627934edd9f1SKamil Godzwon /* Register the bdev using UUID as the name */ 628079415753SKonrad Sztyber bdev->name = uuid; 628179415753SKonrad Sztyber rc = spdk_bdev_register(bdev); 628279415753SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 628379415753SKonrad Sztyber CU_ASSERT_EQUAL(spdk_bdev_get_by_name(uuid), bdev); 628479415753SKonrad Sztyber 628579415753SKonrad Sztyber /* Unregister the bdev */ 628679415753SKonrad Sztyber spdk_bdev_unregister(bdev, NULL, NULL); 628779415753SKonrad Sztyber poll_threads(); 628879415753SKonrad Sztyber CU_ASSERT_PTR_NULL(spdk_bdev_get_by_name(uuid)); 628979415753SKonrad Sztyber 629079415753SKonrad Sztyber /* Check that it's not possible to register two bdevs with the same UUIDs */ 629179415753SKonrad Sztyber bdev->name = "bdev0"; 629279415753SKonrad Sztyber second = allocate_bdev("bdev1"); 629379415753SKonrad Sztyber spdk_uuid_copy(&bdev->uuid, &second->uuid); 629479415753SKonrad Sztyber rc = spdk_bdev_register(bdev); 629579415753SKonrad Sztyber CU_ASSERT_EQUAL(rc, -EEXIST); 629679415753SKonrad Sztyber 629779415753SKonrad Sztyber /* Regenerate the UUID and re-check */ 629879415753SKonrad Sztyber spdk_uuid_generate(&bdev->uuid); 629979415753SKonrad Sztyber rc = spdk_bdev_register(bdev); 630079415753SKonrad Sztyber CU_ASSERT_EQUAL(rc, 0); 630179415753SKonrad Sztyber 630279415753SKonrad Sztyber /* And check that both bdevs can be retrieved through their UUIDs */ 630379415753SKonrad Sztyber spdk_uuid_fmt_lower(uuid, sizeof(uuid), &bdev->uuid); 630479415753SKonrad Sztyber CU_ASSERT_EQUAL(spdk_bdev_get_by_name(uuid), bdev); 630579415753SKonrad Sztyber spdk_uuid_fmt_lower(uuid, sizeof(uuid), &second->uuid); 630679415753SKonrad Sztyber CU_ASSERT_EQUAL(spdk_bdev_get_by_name(uuid), second); 630779415753SKonrad Sztyber 630879415753SKonrad Sztyber free_bdev(second); 630979415753SKonrad Sztyber free_bdev(bdev); 6310107741fcSKonrad Sztyber ut_fini_bdev(); 631179415753SKonrad Sztyber } 631279415753SKonrad Sztyber 631396c007d3SShuhei Matsumoto static void 631496c007d3SShuhei Matsumoto bdev_unregister_by_name(void) 631596c007d3SShuhei Matsumoto { 631696c007d3SShuhei Matsumoto struct spdk_bdev *bdev; 631796c007d3SShuhei Matsumoto int rc; 631896c007d3SShuhei Matsumoto 631996c007d3SShuhei Matsumoto bdev = allocate_bdev("bdev"); 632096c007d3SShuhei Matsumoto 632196c007d3SShuhei Matsumoto g_event_type1 = 0xFF; 632296c007d3SShuhei Matsumoto g_unregister_arg = NULL; 632396c007d3SShuhei Matsumoto g_unregister_rc = -1; 632496c007d3SShuhei Matsumoto 632596c007d3SShuhei Matsumoto rc = spdk_bdev_unregister_by_name("bdev1", &bdev_ut_if, bdev_unregister_cb, (void *)0x12345678); 632696c007d3SShuhei Matsumoto CU_ASSERT(rc == -ENODEV); 632796c007d3SShuhei Matsumoto 632896c007d3SShuhei Matsumoto rc = spdk_bdev_unregister_by_name("bdev", &vbdev_ut_if, bdev_unregister_cb, (void *)0x12345678); 632996c007d3SShuhei Matsumoto CU_ASSERT(rc == -ENODEV); 633096c007d3SShuhei Matsumoto 633196c007d3SShuhei Matsumoto rc = spdk_bdev_unregister_by_name("bdev", &bdev_ut_if, bdev_unregister_cb, (void *)0x12345678); 633296c007d3SShuhei Matsumoto CU_ASSERT(rc == 0); 633396c007d3SShuhei Matsumoto 633496c007d3SShuhei Matsumoto /* Check that unregister callback is delayed */ 633596c007d3SShuhei Matsumoto CU_ASSERT(g_unregister_arg == NULL); 633696c007d3SShuhei Matsumoto CU_ASSERT(g_unregister_rc == -1); 633796c007d3SShuhei Matsumoto 633896c007d3SShuhei Matsumoto poll_threads(); 633996c007d3SShuhei Matsumoto 634096c007d3SShuhei Matsumoto /* Event callback shall not be issued because device was closed */ 634196c007d3SShuhei Matsumoto CU_ASSERT(g_event_type1 == 0xFF); 634296c007d3SShuhei Matsumoto /* Unregister callback is issued */ 634396c007d3SShuhei Matsumoto CU_ASSERT(g_unregister_arg == (void *)0x12345678); 634496c007d3SShuhei Matsumoto CU_ASSERT(g_unregister_rc == 0); 634596c007d3SShuhei Matsumoto 634696c007d3SShuhei Matsumoto free_bdev(bdev); 634796c007d3SShuhei Matsumoto } 634896c007d3SShuhei Matsumoto 6349428b17a0SShuhei Matsumoto static int 6350428b17a0SShuhei Matsumoto count_bdevs(void *ctx, struct spdk_bdev *bdev) 6351428b17a0SShuhei Matsumoto { 6352428b17a0SShuhei Matsumoto int *count = ctx; 6353428b17a0SShuhei Matsumoto 6354428b17a0SShuhei Matsumoto (*count)++; 6355428b17a0SShuhei Matsumoto 6356428b17a0SShuhei Matsumoto return 0; 6357428b17a0SShuhei Matsumoto } 6358428b17a0SShuhei Matsumoto 6359428b17a0SShuhei Matsumoto static void 6360428b17a0SShuhei Matsumoto for_each_bdev_test(void) 6361428b17a0SShuhei Matsumoto { 6362428b17a0SShuhei Matsumoto struct spdk_bdev *bdev[8]; 6363428b17a0SShuhei Matsumoto int rc, count; 6364428b17a0SShuhei Matsumoto 6365428b17a0SShuhei Matsumoto bdev[0] = allocate_bdev("bdev0"); 6366c0c333e2Syupeng bdev[0]->internal.status = SPDK_BDEV_STATUS_REMOVING; 6367428b17a0SShuhei Matsumoto 6368428b17a0SShuhei Matsumoto bdev[1] = allocate_bdev("bdev1"); 6369428b17a0SShuhei Matsumoto rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if); 6370428b17a0SShuhei Matsumoto CU_ASSERT(rc == 0); 6371428b17a0SShuhei Matsumoto 6372428b17a0SShuhei Matsumoto bdev[2] = allocate_bdev("bdev2"); 6373428b17a0SShuhei Matsumoto 6374428b17a0SShuhei Matsumoto bdev[3] = allocate_bdev("bdev3"); 6375428b17a0SShuhei Matsumoto rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if); 6376428b17a0SShuhei Matsumoto CU_ASSERT(rc == 0); 6377428b17a0SShuhei Matsumoto 6378428b17a0SShuhei Matsumoto bdev[4] = allocate_bdev("bdev4"); 6379428b17a0SShuhei Matsumoto 6380428b17a0SShuhei Matsumoto bdev[5] = allocate_bdev("bdev5"); 6381428b17a0SShuhei Matsumoto rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if); 6382428b17a0SShuhei Matsumoto CU_ASSERT(rc == 0); 6383428b17a0SShuhei Matsumoto 6384428b17a0SShuhei Matsumoto bdev[6] = allocate_bdev("bdev6"); 6385428b17a0SShuhei Matsumoto 6386428b17a0SShuhei Matsumoto bdev[7] = allocate_bdev("bdev7"); 6387428b17a0SShuhei Matsumoto 6388428b17a0SShuhei Matsumoto count = 0; 6389428b17a0SShuhei Matsumoto rc = spdk_for_each_bdev(&count, count_bdevs); 6390428b17a0SShuhei Matsumoto CU_ASSERT(rc == 0); 6391c0c333e2Syupeng CU_ASSERT(count == 7); 6392428b17a0SShuhei Matsumoto 6393428b17a0SShuhei Matsumoto count = 0; 6394428b17a0SShuhei Matsumoto rc = spdk_for_each_bdev_leaf(&count, count_bdevs); 6395428b17a0SShuhei Matsumoto CU_ASSERT(rc == 0); 6396c0c333e2Syupeng CU_ASSERT(count == 4); 6397428b17a0SShuhei Matsumoto 6398c0c333e2Syupeng bdev[0]->internal.status = SPDK_BDEV_STATUS_READY; 6399428b17a0SShuhei Matsumoto free_bdev(bdev[0]); 6400428b17a0SShuhei Matsumoto free_bdev(bdev[1]); 6401428b17a0SShuhei Matsumoto free_bdev(bdev[2]); 6402428b17a0SShuhei Matsumoto free_bdev(bdev[3]); 6403428b17a0SShuhei Matsumoto free_bdev(bdev[4]); 6404428b17a0SShuhei Matsumoto free_bdev(bdev[5]); 6405428b17a0SShuhei Matsumoto free_bdev(bdev[6]); 6406428b17a0SShuhei Matsumoto free_bdev(bdev[7]); 6407428b17a0SShuhei Matsumoto } 6408428b17a0SShuhei Matsumoto 64096defafc9SDamiano static void 64106defafc9SDamiano bdev_seek_test(void) 64116defafc9SDamiano { 64126defafc9SDamiano struct spdk_bdev *bdev; 64136defafc9SDamiano struct spdk_bdev_desc *desc = NULL; 64146defafc9SDamiano struct spdk_io_channel *io_ch; 64156defafc9SDamiano int rc; 64166defafc9SDamiano 6417107741fcSKonrad Sztyber ut_init_bdev(NULL); 64186defafc9SDamiano poll_threads(); 64196defafc9SDamiano 64206defafc9SDamiano bdev = allocate_bdev("bdev0"); 64216defafc9SDamiano 64226defafc9SDamiano rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 64236defafc9SDamiano CU_ASSERT(rc == 0); 64246defafc9SDamiano poll_threads(); 64256defafc9SDamiano SPDK_CU_ASSERT_FATAL(desc != NULL); 64266defafc9SDamiano CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 64276defafc9SDamiano io_ch = spdk_bdev_get_io_channel(desc); 64286defafc9SDamiano CU_ASSERT(io_ch != NULL); 64296defafc9SDamiano 64306defafc9SDamiano /* Seek data not supported */ 64316defafc9SDamiano ut_enable_io_type(SPDK_BDEV_IO_TYPE_SEEK_DATA, false); 64326defafc9SDamiano rc = spdk_bdev_seek_data(desc, io_ch, 0, bdev_seek_cb, NULL); 64336defafc9SDamiano CU_ASSERT(rc == 0); 64346defafc9SDamiano CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 64356defafc9SDamiano poll_threads(); 64366defafc9SDamiano CU_ASSERT(g_seek_offset == 0); 64376defafc9SDamiano 64386defafc9SDamiano /* Seek hole not supported */ 64396defafc9SDamiano ut_enable_io_type(SPDK_BDEV_IO_TYPE_SEEK_HOLE, false); 64406defafc9SDamiano rc = spdk_bdev_seek_hole(desc, io_ch, 0, bdev_seek_cb, NULL); 64416defafc9SDamiano CU_ASSERT(rc == 0); 64426defafc9SDamiano CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 64436defafc9SDamiano poll_threads(); 64446defafc9SDamiano CU_ASSERT(g_seek_offset == UINT64_MAX); 64456defafc9SDamiano 64466defafc9SDamiano /* Seek data supported */ 64476defafc9SDamiano g_seek_data_offset = 12345; 64486defafc9SDamiano ut_enable_io_type(SPDK_BDEV_IO_TYPE_SEEK_DATA, true); 64496defafc9SDamiano rc = spdk_bdev_seek_data(desc, io_ch, 0, bdev_seek_cb, NULL); 64506defafc9SDamiano CU_ASSERT(rc == 0); 64516defafc9SDamiano CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 64526defafc9SDamiano stub_complete_io(1); 64536defafc9SDamiano CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 64546defafc9SDamiano CU_ASSERT(g_seek_offset == 12345); 64556defafc9SDamiano 64566defafc9SDamiano /* Seek hole supported */ 64576defafc9SDamiano g_seek_hole_offset = 67890; 64586defafc9SDamiano ut_enable_io_type(SPDK_BDEV_IO_TYPE_SEEK_HOLE, true); 64596defafc9SDamiano rc = spdk_bdev_seek_hole(desc, io_ch, 0, bdev_seek_cb, NULL); 64606defafc9SDamiano CU_ASSERT(rc == 0); 64616defafc9SDamiano CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 64626defafc9SDamiano stub_complete_io(1); 64636defafc9SDamiano CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 64646defafc9SDamiano CU_ASSERT(g_seek_offset == 67890); 64656defafc9SDamiano 64666defafc9SDamiano spdk_put_io_channel(io_ch); 64676defafc9SDamiano spdk_bdev_close(desc); 64686defafc9SDamiano free_bdev(bdev); 6469107741fcSKonrad Sztyber ut_fini_bdev(); 64706defafc9SDamiano } 64716defafc9SDamiano 64726c8702acSEvgeniy Kochetov static void 64736c8702acSEvgeniy Kochetov bdev_copy(void) 64746c8702acSEvgeniy Kochetov { 64756c8702acSEvgeniy Kochetov struct spdk_bdev *bdev; 64766c8702acSEvgeniy Kochetov struct spdk_bdev_desc *desc = NULL; 64776c8702acSEvgeniy Kochetov struct spdk_io_channel *ioch; 64786c8702acSEvgeniy Kochetov struct ut_expected_io *expected_io; 64796c8702acSEvgeniy Kochetov uint64_t src_offset, num_blocks; 64806c8702acSEvgeniy Kochetov uint32_t num_completed; 64816c8702acSEvgeniy Kochetov int rc; 64826c8702acSEvgeniy Kochetov 6483107741fcSKonrad Sztyber ut_init_bdev(NULL); 64846c8702acSEvgeniy Kochetov bdev = allocate_bdev("bdev"); 64856c8702acSEvgeniy Kochetov 64866c8702acSEvgeniy Kochetov rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 64876c8702acSEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 64886c8702acSEvgeniy Kochetov SPDK_CU_ASSERT_FATAL(desc != NULL); 64896c8702acSEvgeniy Kochetov CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 64906c8702acSEvgeniy Kochetov ioch = spdk_bdev_get_io_channel(desc); 64916c8702acSEvgeniy Kochetov SPDK_CU_ASSERT_FATAL(ioch != NULL); 64926c8702acSEvgeniy Kochetov 64936c8702acSEvgeniy Kochetov fn_table.submit_request = stub_submit_request; 64946c8702acSEvgeniy Kochetov g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 64956c8702acSEvgeniy Kochetov 64966c8702acSEvgeniy Kochetov /* First test that if the bdev supports copy, the request won't be split */ 64976c8702acSEvgeniy Kochetov bdev->md_len = 0; 649886136540SRui Chang bdev->blocklen = 512; 649986136540SRui Chang num_blocks = 128; 65006c8702acSEvgeniy Kochetov src_offset = bdev->blockcnt - num_blocks; 65016c8702acSEvgeniy Kochetov 65026c8702acSEvgeniy Kochetov expected_io = ut_alloc_expected_copy_io(SPDK_BDEV_IO_TYPE_COPY, 0, src_offset, num_blocks); 65036c8702acSEvgeniy Kochetov TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 650486136540SRui Chang 65056c8702acSEvgeniy Kochetov rc = spdk_bdev_copy_blocks(desc, ioch, 0, src_offset, num_blocks, io_done, NULL); 65066c8702acSEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 65076c8702acSEvgeniy Kochetov num_completed = stub_complete_io(1); 65086c8702acSEvgeniy Kochetov CU_ASSERT_EQUAL(num_completed, 1); 65096c8702acSEvgeniy Kochetov 651086136540SRui Chang /* Check that if copy is not supported it'll still work */ 651186136540SRui Chang expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, src_offset, num_blocks, 0); 651286136540SRui Chang TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 651386136540SRui Chang expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 0, num_blocks, 0); 651486136540SRui Chang TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 651586136540SRui Chang 65166c8702acSEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_COPY, false); 65176c8702acSEvgeniy Kochetov 65186c8702acSEvgeniy Kochetov rc = spdk_bdev_copy_blocks(desc, ioch, 0, src_offset, num_blocks, io_done, NULL); 651986136540SRui Chang CU_ASSERT_EQUAL(rc, 0); 652086136540SRui Chang num_completed = stub_complete_io(1); 652186136540SRui Chang CU_ASSERT_EQUAL(num_completed, 1); 652286136540SRui Chang num_completed = stub_complete_io(1); 652386136540SRui Chang CU_ASSERT_EQUAL(num_completed, 1); 65246c8702acSEvgeniy Kochetov 65256c8702acSEvgeniy Kochetov ut_enable_io_type(SPDK_BDEV_IO_TYPE_COPY, true); 65266c8702acSEvgeniy Kochetov spdk_put_io_channel(ioch); 65276c8702acSEvgeniy Kochetov spdk_bdev_close(desc); 65286c8702acSEvgeniy Kochetov free_bdev(bdev); 6529107741fcSKonrad Sztyber ut_fini_bdev(); 65306c8702acSEvgeniy Kochetov } 65316c8702acSEvgeniy Kochetov 65326c8702acSEvgeniy Kochetov static void 65336c8702acSEvgeniy Kochetov bdev_copy_split_test(void) 65346c8702acSEvgeniy Kochetov { 65356c8702acSEvgeniy Kochetov struct spdk_bdev *bdev; 65366c8702acSEvgeniy Kochetov struct spdk_bdev_desc *desc = NULL; 65376c8702acSEvgeniy Kochetov struct spdk_io_channel *ioch; 65386c8702acSEvgeniy Kochetov struct spdk_bdev_channel *bdev_ch; 65396c8702acSEvgeniy Kochetov struct ut_expected_io *expected_io; 65406c8702acSEvgeniy Kochetov struct spdk_bdev_opts bdev_opts = {}; 65416c8702acSEvgeniy Kochetov uint32_t i, num_outstanding; 65426c8702acSEvgeniy Kochetov uint64_t offset, src_offset, num_blocks, max_copy_blocks, num_children; 65436c8702acSEvgeniy Kochetov int rc; 65446c8702acSEvgeniy Kochetov 65456c8702acSEvgeniy Kochetov spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 65466c8702acSEvgeniy Kochetov bdev_opts.bdev_io_pool_size = 512; 65476c8702acSEvgeniy Kochetov bdev_opts.bdev_io_cache_size = 64; 65486c8702acSEvgeniy Kochetov rc = spdk_bdev_set_opts(&bdev_opts); 65496c8702acSEvgeniy Kochetov CU_ASSERT(rc == 0); 65506c8702acSEvgeniy Kochetov 6551107741fcSKonrad Sztyber ut_init_bdev(NULL); 65526c8702acSEvgeniy Kochetov bdev = allocate_bdev("bdev"); 65536c8702acSEvgeniy Kochetov 65546c8702acSEvgeniy Kochetov rc = spdk_bdev_open_ext("bdev", true, bdev_ut_event_cb, NULL, &desc); 65556c8702acSEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 65566c8702acSEvgeniy Kochetov SPDK_CU_ASSERT_FATAL(desc != NULL); 65576c8702acSEvgeniy Kochetov CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 65586c8702acSEvgeniy Kochetov ioch = spdk_bdev_get_io_channel(desc); 65596c8702acSEvgeniy Kochetov SPDK_CU_ASSERT_FATAL(ioch != NULL); 65606c8702acSEvgeniy Kochetov bdev_ch = spdk_io_channel_get_ctx(ioch); 65616c8702acSEvgeniy Kochetov CU_ASSERT(TAILQ_EMPTY(&bdev_ch->io_submitted)); 65626c8702acSEvgeniy Kochetov 65636c8702acSEvgeniy Kochetov fn_table.submit_request = stub_submit_request; 65646c8702acSEvgeniy Kochetov g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS; 65656c8702acSEvgeniy Kochetov 65666c8702acSEvgeniy Kochetov /* Case 1: First test the request won't be split */ 65676c8702acSEvgeniy Kochetov num_blocks = 32; 65686c8702acSEvgeniy Kochetov src_offset = bdev->blockcnt - num_blocks; 65696c8702acSEvgeniy Kochetov 65706c8702acSEvgeniy Kochetov g_io_done = false; 65716c8702acSEvgeniy Kochetov expected_io = ut_alloc_expected_copy_io(SPDK_BDEV_IO_TYPE_COPY, 0, src_offset, num_blocks); 65726c8702acSEvgeniy Kochetov TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 65736c8702acSEvgeniy Kochetov rc = spdk_bdev_copy_blocks(desc, ioch, 0, src_offset, num_blocks, io_done, NULL); 65746c8702acSEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 65756c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == false); 65766c8702acSEvgeniy Kochetov CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1); 65776c8702acSEvgeniy Kochetov stub_complete_io(1); 65786c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == true); 65796c8702acSEvgeniy Kochetov CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 65806c8702acSEvgeniy Kochetov 65816c8702acSEvgeniy Kochetov /* Case 2: Test the split with 2 children requests */ 65826c8702acSEvgeniy Kochetov max_copy_blocks = 8; 65836c8702acSEvgeniy Kochetov bdev->max_copy = max_copy_blocks; 65846c8702acSEvgeniy Kochetov num_children = 2; 65856c8702acSEvgeniy Kochetov num_blocks = max_copy_blocks * num_children; 65866c8702acSEvgeniy Kochetov offset = 0; 65876c8702acSEvgeniy Kochetov src_offset = bdev->blockcnt - num_blocks; 65886c8702acSEvgeniy Kochetov 65896c8702acSEvgeniy Kochetov g_io_done = false; 65906c8702acSEvgeniy Kochetov for (i = 0; i < num_children; i++) { 65916c8702acSEvgeniy Kochetov expected_io = ut_alloc_expected_copy_io(SPDK_BDEV_IO_TYPE_COPY, offset, 65926c8702acSEvgeniy Kochetov src_offset + offset, max_copy_blocks); 65936c8702acSEvgeniy Kochetov TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 65946c8702acSEvgeniy Kochetov offset += max_copy_blocks; 65956c8702acSEvgeniy Kochetov } 65966c8702acSEvgeniy Kochetov 65976c8702acSEvgeniy Kochetov rc = spdk_bdev_copy_blocks(desc, ioch, 0, src_offset, num_blocks, io_done, NULL); 65986c8702acSEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 65996c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == false); 66006c8702acSEvgeniy Kochetov CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == num_children); 66016c8702acSEvgeniy Kochetov stub_complete_io(num_children); 66026c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == true); 66036c8702acSEvgeniy Kochetov CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 66046c8702acSEvgeniy Kochetov 66056c8702acSEvgeniy Kochetov /* Case 3: Test the split with 15 children requests, will finish 8 requests first */ 66066c8702acSEvgeniy Kochetov num_children = 15; 66076c8702acSEvgeniy Kochetov num_blocks = max_copy_blocks * num_children; 66086c8702acSEvgeniy Kochetov offset = 0; 66096c8702acSEvgeniy Kochetov src_offset = bdev->blockcnt - num_blocks; 66106c8702acSEvgeniy Kochetov 66116c8702acSEvgeniy Kochetov g_io_done = false; 66126c8702acSEvgeniy Kochetov for (i = 0; i < num_children; i++) { 66136c8702acSEvgeniy Kochetov expected_io = ut_alloc_expected_copy_io(SPDK_BDEV_IO_TYPE_COPY, offset, 66146c8702acSEvgeniy Kochetov src_offset + offset, max_copy_blocks); 66156c8702acSEvgeniy Kochetov TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 66166c8702acSEvgeniy Kochetov offset += max_copy_blocks; 66176c8702acSEvgeniy Kochetov } 66186c8702acSEvgeniy Kochetov 66196c8702acSEvgeniy Kochetov rc = spdk_bdev_copy_blocks(desc, ioch, 0, src_offset, num_blocks, io_done, NULL); 66206c8702acSEvgeniy Kochetov CU_ASSERT_EQUAL(rc, 0); 66216c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == false); 66226c8702acSEvgeniy Kochetov 66236c8702acSEvgeniy Kochetov while (num_children > 0) { 66246c8702acSEvgeniy Kochetov num_outstanding = spdk_min(num_children, SPDK_BDEV_MAX_CHILDREN_COPY_REQS); 66256c8702acSEvgeniy Kochetov CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == num_outstanding); 66266c8702acSEvgeniy Kochetov stub_complete_io(num_outstanding); 66276c8702acSEvgeniy Kochetov num_children -= num_outstanding; 66286c8702acSEvgeniy Kochetov } 66296c8702acSEvgeniy Kochetov CU_ASSERT(g_io_done == true); 66306c8702acSEvgeniy Kochetov 66310c1df53eSShuhei Matsumoto /* Case 4: Same test scenario as the case 2 but the configuration is different. 66320c1df53eSShuhei Matsumoto * Copy is not supported. 66330c1df53eSShuhei Matsumoto */ 66340c1df53eSShuhei Matsumoto ut_enable_io_type(SPDK_BDEV_IO_TYPE_COPY, false); 66350c1df53eSShuhei Matsumoto 66360c1df53eSShuhei Matsumoto num_children = 2; 66370c1df53eSShuhei Matsumoto max_copy_blocks = spdk_bdev_get_max_copy(bdev); 66380c1df53eSShuhei Matsumoto num_blocks = max_copy_blocks * num_children; 66390c1df53eSShuhei Matsumoto src_offset = bdev->blockcnt - num_blocks; 66400c1df53eSShuhei Matsumoto offset = 0; 66410c1df53eSShuhei Matsumoto 66420c1df53eSShuhei Matsumoto g_io_done = false; 66430c1df53eSShuhei Matsumoto for (i = 0; i < num_children; i++) { 66440c1df53eSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, src_offset, 66450c1df53eSShuhei Matsumoto max_copy_blocks, 0); 66460c1df53eSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 66470c1df53eSShuhei Matsumoto src_offset += max_copy_blocks; 66480c1df53eSShuhei Matsumoto } 66490c1df53eSShuhei Matsumoto for (i = 0; i < num_children; i++) { 66500c1df53eSShuhei Matsumoto expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, offset, 66510c1df53eSShuhei Matsumoto max_copy_blocks, 0); 66520c1df53eSShuhei Matsumoto TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link); 66530c1df53eSShuhei Matsumoto offset += max_copy_blocks; 66540c1df53eSShuhei Matsumoto } 66550c1df53eSShuhei Matsumoto 66560c1df53eSShuhei Matsumoto src_offset = bdev->blockcnt - num_blocks; 66570c1df53eSShuhei Matsumoto offset = 0; 66580c1df53eSShuhei Matsumoto 66590c1df53eSShuhei Matsumoto rc = spdk_bdev_copy_blocks(desc, ioch, offset, src_offset, num_blocks, io_done, NULL); 66600c1df53eSShuhei Matsumoto CU_ASSERT_EQUAL(rc, 0); 66610c1df53eSShuhei Matsumoto CU_ASSERT(g_io_done == false); 66620c1df53eSShuhei Matsumoto 66630c1df53eSShuhei Matsumoto while (num_children > 0) { 66640c1df53eSShuhei Matsumoto num_outstanding = spdk_min(num_children, SPDK_BDEV_MAX_CHILDREN_COPY_REQS); 66650c1df53eSShuhei Matsumoto 66660c1df53eSShuhei Matsumoto /* One copy request is split into one read and one write requests. */ 66670c1df53eSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == num_outstanding); 66680c1df53eSShuhei Matsumoto stub_complete_io(num_outstanding); 66690c1df53eSShuhei Matsumoto CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == num_outstanding); 66700c1df53eSShuhei Matsumoto stub_complete_io(num_outstanding); 66710c1df53eSShuhei Matsumoto 66720c1df53eSShuhei Matsumoto num_children -= num_outstanding; 66730c1df53eSShuhei Matsumoto } 66740c1df53eSShuhei Matsumoto CU_ASSERT(g_io_done == true); 66750c1df53eSShuhei Matsumoto 66760c1df53eSShuhei Matsumoto ut_enable_io_type(SPDK_BDEV_IO_TYPE_COPY, true); 66770c1df53eSShuhei Matsumoto 66786c8702acSEvgeniy Kochetov spdk_put_io_channel(ioch); 66796c8702acSEvgeniy Kochetov spdk_bdev_close(desc); 66806c8702acSEvgeniy Kochetov free_bdev(bdev); 6681107741fcSKonrad Sztyber ut_fini_bdev(); 66826c8702acSEvgeniy Kochetov } 66836c8702acSEvgeniy Kochetov 6684ae215731SMike Gerdts static void 6685a7eb6187SMike Gerdts examine_claim_v1(struct spdk_bdev *bdev) 6686ae215731SMike Gerdts { 6687ae215731SMike Gerdts int rc; 6688ae215731SMike Gerdts 6689ae215731SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &vbdev_ut_if); 6690ae215731SMike Gerdts CU_ASSERT(rc == 0); 6691ae215731SMike Gerdts } 6692ae215731SMike Gerdts 6693ae215731SMike Gerdts static void 6694ae215731SMike Gerdts examine_no_lock_held(struct spdk_bdev *bdev) 6695ae215731SMike Gerdts { 6696ae215731SMike Gerdts CU_ASSERT(!spdk_spin_held(&g_bdev_mgr.spinlock)); 6697ae215731SMike Gerdts CU_ASSERT(!spdk_spin_held(&bdev->internal.spinlock)); 6698ae215731SMike Gerdts } 6699ae215731SMike Gerdts 670086bbcdb8SMike Gerdts struct examine_claim_v2_ctx { 670186bbcdb8SMike Gerdts struct ut_examine_ctx examine_ctx; 670286bbcdb8SMike Gerdts enum spdk_bdev_claim_type claim_type; 670386bbcdb8SMike Gerdts struct spdk_bdev_desc *desc; 670486bbcdb8SMike Gerdts }; 670586bbcdb8SMike Gerdts 670686bbcdb8SMike Gerdts static void 670786bbcdb8SMike Gerdts examine_claim_v2(struct spdk_bdev *bdev) 670886bbcdb8SMike Gerdts { 670986bbcdb8SMike Gerdts struct examine_claim_v2_ctx *ctx = bdev->ctxt; 671086bbcdb8SMike Gerdts int rc; 671186bbcdb8SMike Gerdts 671286bbcdb8SMike Gerdts rc = spdk_bdev_open_ext(bdev->name, false, bdev_ut_event_cb, NULL, &ctx->desc); 671386bbcdb8SMike Gerdts CU_ASSERT(rc == 0); 671486bbcdb8SMike Gerdts 671586bbcdb8SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(ctx->desc, ctx->claim_type, NULL, &vbdev_ut_if); 671686bbcdb8SMike Gerdts CU_ASSERT(rc == 0); 671786bbcdb8SMike Gerdts } 671886bbcdb8SMike Gerdts 6719ae215731SMike Gerdts static void 6720ae215731SMike Gerdts examine_locks(void) 6721ae215731SMike Gerdts { 6722ae215731SMike Gerdts struct spdk_bdev *bdev; 6723ae215731SMike Gerdts struct ut_examine_ctx ctx = { 0 }; 672486bbcdb8SMike Gerdts struct examine_claim_v2_ctx v2_ctx; 6725ae215731SMike Gerdts 6726ae215731SMike Gerdts /* Without any claims, one code path is taken */ 6727ae215731SMike Gerdts ctx.examine_config = examine_no_lock_held; 6728ae215731SMike Gerdts ctx.examine_disk = examine_no_lock_held; 6729ae215731SMike Gerdts bdev = allocate_bdev_ctx("bdev0", &ctx); 6730ae215731SMike Gerdts CU_ASSERT(ctx.examine_config_count == 1); 6731ae215731SMike Gerdts CU_ASSERT(ctx.examine_disk_count == 1); 67324bb902a6SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 67339fd2f931SMike Gerdts CU_ASSERT(bdev->internal.claim.v1.module == NULL); 6734ae215731SMike Gerdts free_bdev(bdev); 6735ae215731SMike Gerdts 673686bbcdb8SMike Gerdts /* Exercise another path that is taken when examine_config() takes a v1 claim. */ 6737ae215731SMike Gerdts memset(&ctx, 0, sizeof(ctx)); 6738a7eb6187SMike Gerdts ctx.examine_config = examine_claim_v1; 6739ae215731SMike Gerdts ctx.examine_disk = examine_no_lock_held; 6740ae215731SMike Gerdts bdev = allocate_bdev_ctx("bdev0", &ctx); 6741ae215731SMike Gerdts CU_ASSERT(ctx.examine_config_count == 1); 6742ae215731SMike Gerdts CU_ASSERT(ctx.examine_disk_count == 1); 67434bb902a6SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_EXCL_WRITE); 67449fd2f931SMike Gerdts CU_ASSERT(bdev->internal.claim.v1.module == &vbdev_ut_if); 6745ae215731SMike Gerdts spdk_bdev_module_release_bdev(bdev); 67464bb902a6SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 67479fd2f931SMike Gerdts CU_ASSERT(bdev->internal.claim.v1.module == NULL); 6748ae215731SMike Gerdts free_bdev(bdev); 674986bbcdb8SMike Gerdts 675086bbcdb8SMike Gerdts /* Exercise the final path that comes with v2 claims. */ 675186bbcdb8SMike Gerdts memset(&v2_ctx, 0, sizeof(v2_ctx)); 675286bbcdb8SMike Gerdts v2_ctx.examine_ctx.examine_config = examine_claim_v2; 675386bbcdb8SMike Gerdts v2_ctx.examine_ctx.examine_disk = examine_no_lock_held; 675486bbcdb8SMike Gerdts v2_ctx.claim_type = SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE; 675586bbcdb8SMike Gerdts bdev = allocate_bdev_ctx("bdev0", &v2_ctx); 675686bbcdb8SMike Gerdts CU_ASSERT(v2_ctx.examine_ctx.examine_config_count == 1); 675786bbcdb8SMike Gerdts CU_ASSERT(v2_ctx.examine_ctx.examine_disk_count == 1); 675886bbcdb8SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE); 675986bbcdb8SMike Gerdts spdk_bdev_close(v2_ctx.desc); 676086bbcdb8SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 676186bbcdb8SMike Gerdts free_bdev(bdev); 6762ae215731SMike Gerdts } 6763ae215731SMike Gerdts 6764a7eb6187SMike Gerdts #define UT_ASSERT_CLAIM_V2_COUNT(bdev, expect) \ 6765a7eb6187SMike Gerdts do { \ 6766a7eb6187SMike Gerdts uint32_t len = 0; \ 6767a7eb6187SMike Gerdts struct spdk_bdev_module_claim *claim; \ 6768a7eb6187SMike Gerdts TAILQ_FOREACH(claim, &bdev->internal.claim.v2.claims, link) { \ 6769a7eb6187SMike Gerdts len++; \ 6770a7eb6187SMike Gerdts } \ 6771a7eb6187SMike Gerdts CU_ASSERT(len == expect); \ 6772a7eb6187SMike Gerdts } while (0) 6773a7eb6187SMike Gerdts 6774a7eb6187SMike Gerdts static void 6775a7eb6187SMike Gerdts claim_v2_rwo(void) 6776a7eb6187SMike Gerdts { 6777a7eb6187SMike Gerdts struct spdk_bdev *bdev; 6778a7eb6187SMike Gerdts struct spdk_bdev_desc *desc; 6779a7eb6187SMike Gerdts struct spdk_bdev_desc *desc2; 6780a7eb6187SMike Gerdts struct spdk_bdev_claim_opts opts; 6781a7eb6187SMike Gerdts int rc; 6782a7eb6187SMike Gerdts 6783a7eb6187SMike Gerdts bdev = allocate_bdev("bdev0"); 6784a7eb6187SMike Gerdts 6785a7eb6187SMike Gerdts /* Claim without options */ 6786a7eb6187SMike Gerdts desc = NULL; 6787a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 6788a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6789a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 6790a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, NULL, 6791a7eb6187SMike Gerdts &bdev_ut_if); 6792a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6793a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE); 6794a7eb6187SMike Gerdts CU_ASSERT(desc->claim != NULL); 6795a7eb6187SMike Gerdts CU_ASSERT(desc->claim->module == &bdev_ut_if); 6796a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "") == 0); 6797a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 6798a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 6799a7eb6187SMike Gerdts 6800a7eb6187SMike Gerdts /* Release the claim by closing the descriptor */ 6801a7eb6187SMike Gerdts spdk_bdev_close(desc); 6802a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 6803a7eb6187SMike Gerdts CU_ASSERT(TAILQ_EMPTY(&bdev->internal.open_descs)); 6804a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 6805a7eb6187SMike Gerdts 6806a7eb6187SMike Gerdts /* Claim with options */ 6807a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 6808a7eb6187SMike Gerdts snprintf(opts.name, sizeof(opts.name), "%s", "claim with options"); 6809a7eb6187SMike Gerdts desc = NULL; 6810a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 6811a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6812a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 6813a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, &opts, 6814a7eb6187SMike Gerdts &bdev_ut_if); 6815a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6816a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE); 6817a7eb6187SMike Gerdts CU_ASSERT(desc->claim != NULL); 6818a7eb6187SMike Gerdts CU_ASSERT(desc->claim->module == &bdev_ut_if); 6819a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "claim with options") == 0); 6820a7eb6187SMike Gerdts memset(&opts, 0, sizeof(opts)); 6821a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "claim with options") == 0); 6822a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 6823a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 6824a7eb6187SMike Gerdts 6825a7eb6187SMike Gerdts /* The claim blocks new writers. */ 6826a7eb6187SMike Gerdts desc2 = NULL; 6827a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc2); 6828a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6829a7eb6187SMike Gerdts CU_ASSERT(desc2 == NULL); 6830a7eb6187SMike Gerdts 6831a7eb6187SMike Gerdts /* New readers are allowed */ 6832a7eb6187SMike Gerdts desc2 = NULL; 6833a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc2); 6834a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6835a7eb6187SMike Gerdts CU_ASSERT(desc2 != NULL); 6836a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6837a7eb6187SMike Gerdts 6838a7eb6187SMike Gerdts /* No new v2 RWO claims are allowed */ 6839a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, NULL, 6840a7eb6187SMike Gerdts &bdev_ut_if); 6841a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6842a7eb6187SMike Gerdts 6843a7eb6187SMike Gerdts /* No new v2 ROM claims are allowed */ 6844a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6845a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE, NULL, 6846a7eb6187SMike Gerdts &bdev_ut_if); 6847a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6848a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6849a7eb6187SMike Gerdts 6850a7eb6187SMike Gerdts /* No new v2 RWM claims are allowed */ 6851a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 6852a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&opts; 6853a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, &opts, 6854a7eb6187SMike Gerdts &bdev_ut_if); 6855a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6856a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6857a7eb6187SMike Gerdts 6858a7eb6187SMike Gerdts /* No new v1 claims are allowed */ 6859a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &bdev_ut_if); 6860a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6861a7eb6187SMike Gerdts 6862a7eb6187SMike Gerdts /* None of the above changed the existing claim */ 6863a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 6864a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 6865a7eb6187SMike Gerdts 6866a7eb6187SMike Gerdts /* Closing the first descriptor now allows a new claim and it is promoted to rw. */ 6867a7eb6187SMike Gerdts spdk_bdev_close(desc); 6868a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 6869a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 6870a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6871a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, NULL, 6872a7eb6187SMike Gerdts &bdev_ut_if); 6873a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6874a7eb6187SMike Gerdts CU_ASSERT(desc2->claim != NULL); 6875a7eb6187SMike Gerdts CU_ASSERT(desc2->write); 6876a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE); 6877a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc2->claim); 6878a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 6879a7eb6187SMike Gerdts spdk_bdev_close(desc2); 6880a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 6881a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 6882a7eb6187SMike Gerdts 6883a7eb6187SMike Gerdts /* Cannot claim with a key */ 6884a7eb6187SMike Gerdts desc = NULL; 6885a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc); 6886a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6887a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 6888a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 6889a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&opts; 6890a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, &opts, 6891a7eb6187SMike Gerdts &bdev_ut_if); 6892a7eb6187SMike Gerdts CU_ASSERT(rc == -EINVAL); 6893a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 6894a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 6895a7eb6187SMike Gerdts spdk_bdev_close(desc); 6896a7eb6187SMike Gerdts 6897a7eb6187SMike Gerdts /* Clean up */ 6898a7eb6187SMike Gerdts free_bdev(bdev); 6899a7eb6187SMike Gerdts } 6900a7eb6187SMike Gerdts 6901a7eb6187SMike Gerdts static void 6902a7eb6187SMike Gerdts claim_v2_rom(void) 6903a7eb6187SMike Gerdts { 6904a7eb6187SMike Gerdts struct spdk_bdev *bdev; 6905a7eb6187SMike Gerdts struct spdk_bdev_desc *desc; 6906a7eb6187SMike Gerdts struct spdk_bdev_desc *desc2; 6907a7eb6187SMike Gerdts struct spdk_bdev_claim_opts opts; 6908a7eb6187SMike Gerdts int rc; 6909a7eb6187SMike Gerdts 6910a7eb6187SMike Gerdts bdev = allocate_bdev("bdev0"); 6911a7eb6187SMike Gerdts 6912a7eb6187SMike Gerdts /* Claim without options */ 6913a7eb6187SMike Gerdts desc = NULL; 6914a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc); 6915a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6916a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 6917a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE, NULL, 6918a7eb6187SMike Gerdts &bdev_ut_if); 6919a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6920a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE); 6921a7eb6187SMike Gerdts CU_ASSERT(desc->claim != NULL); 6922a7eb6187SMike Gerdts CU_ASSERT(desc->claim->module == &bdev_ut_if); 6923a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "") == 0); 6924a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 6925a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 6926a7eb6187SMike Gerdts 6927a7eb6187SMike Gerdts /* Release the claim by closing the descriptor */ 6928a7eb6187SMike Gerdts spdk_bdev_close(desc); 6929a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 6930a7eb6187SMike Gerdts CU_ASSERT(TAILQ_EMPTY(&bdev->internal.open_descs)); 6931a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 6932a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 6933a7eb6187SMike Gerdts 6934a7eb6187SMike Gerdts /* Claim with options */ 6935a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 6936a7eb6187SMike Gerdts snprintf(opts.name, sizeof(opts.name), "%s", "claim with options"); 6937a7eb6187SMike Gerdts desc = NULL; 6938a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc); 6939a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6940a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 6941a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE, &opts, 6942a7eb6187SMike Gerdts &bdev_ut_if); 6943a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6944a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE); 6945a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc->claim != NULL); 6946a7eb6187SMike Gerdts CU_ASSERT(desc->claim->module == &bdev_ut_if); 6947a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "claim with options") == 0); 6948a7eb6187SMike Gerdts memset(&opts, 0, sizeof(opts)); 6949a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "claim with options") == 0); 6950a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 6951a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 6952a7eb6187SMike Gerdts 6953a7eb6187SMike Gerdts /* The claim blocks new writers. */ 6954a7eb6187SMike Gerdts desc2 = NULL; 6955a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc2); 6956a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6957a7eb6187SMike Gerdts CU_ASSERT(desc2 == NULL); 6958a7eb6187SMike Gerdts 6959a7eb6187SMike Gerdts /* New readers are allowed */ 6960a7eb6187SMike Gerdts desc2 = NULL; 6961a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc2); 6962a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6963a7eb6187SMike Gerdts CU_ASSERT(desc2 != NULL); 6964a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6965a7eb6187SMike Gerdts 6966a7eb6187SMike Gerdts /* No new v2 RWO claims are allowed */ 6967a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, NULL, 6968a7eb6187SMike Gerdts &bdev_ut_if); 6969a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6970a7eb6187SMike Gerdts 6971a7eb6187SMike Gerdts /* No new v2 RWM claims are allowed */ 6972a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 6973a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&opts; 6974a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, &opts, 6975a7eb6187SMike Gerdts &bdev_ut_if); 6976a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6977a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6978a7eb6187SMike Gerdts 6979a7eb6187SMike Gerdts /* No new v1 claims are allowed */ 6980a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &bdev_ut_if); 6981a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 6982a7eb6187SMike Gerdts 6983a7eb6187SMike Gerdts /* None of the above messed up the existing claim */ 6984a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 6985a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 6986a7eb6187SMike Gerdts 6987a7eb6187SMike Gerdts /* New v2 ROM claims are allowed and the descriptor stays read-only. */ 6988a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6989a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE, NULL, 6990a7eb6187SMike Gerdts &bdev_ut_if); 6991a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 6992a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 6993a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 6994a7eb6187SMike Gerdts CU_ASSERT(TAILQ_NEXT(desc->claim, link) == desc2->claim); 6995a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 2); 6996a7eb6187SMike Gerdts 6997a7eb6187SMike Gerdts /* Claim remains when closing the first descriptor */ 6998a7eb6187SMike Gerdts spdk_bdev_close(desc); 6999a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE); 7000a7eb6187SMike Gerdts CU_ASSERT(!TAILQ_EMPTY(&bdev->internal.open_descs)); 7001a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc2->claim); 7002a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 7003a7eb6187SMike Gerdts 7004a7eb6187SMike Gerdts /* Claim removed when closing the other descriptor */ 7005a7eb6187SMike Gerdts spdk_bdev_close(desc2); 7006a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7007a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 7008a7eb6187SMike Gerdts CU_ASSERT(TAILQ_EMPTY(&bdev->internal.open_descs)); 7009a7eb6187SMike Gerdts 7010a7eb6187SMike Gerdts /* Cannot claim with a key */ 7011a7eb6187SMike Gerdts desc = NULL; 7012a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc); 7013a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7014a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 7015a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7016a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&opts; 7017a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE, &opts, 7018a7eb6187SMike Gerdts &bdev_ut_if); 7019a7eb6187SMike Gerdts CU_ASSERT(rc == -EINVAL); 7020a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7021a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 7022a7eb6187SMike Gerdts spdk_bdev_close(desc); 7023a7eb6187SMike Gerdts 7024a7eb6187SMike Gerdts /* Cannot claim with a read-write descriptor */ 7025a7eb6187SMike Gerdts desc = NULL; 7026a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 7027a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7028a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 7029a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE, NULL, 7030a7eb6187SMike Gerdts &bdev_ut_if); 7031a7eb6187SMike Gerdts CU_ASSERT(rc == -EINVAL); 7032a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7033a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 7034a7eb6187SMike Gerdts spdk_bdev_close(desc); 7035a7eb6187SMike Gerdts CU_ASSERT(TAILQ_EMPTY(&bdev->internal.open_descs)); 7036a7eb6187SMike Gerdts 7037a7eb6187SMike Gerdts /* Clean up */ 7038a7eb6187SMike Gerdts free_bdev(bdev); 7039a7eb6187SMike Gerdts } 7040a7eb6187SMike Gerdts 7041a7eb6187SMike Gerdts static void 7042a7eb6187SMike Gerdts claim_v2_rwm(void) 7043a7eb6187SMike Gerdts { 7044a7eb6187SMike Gerdts struct spdk_bdev *bdev; 7045a7eb6187SMike Gerdts struct spdk_bdev_desc *desc; 7046a7eb6187SMike Gerdts struct spdk_bdev_desc *desc2; 7047a7eb6187SMike Gerdts struct spdk_bdev_claim_opts opts; 7048a7eb6187SMike Gerdts char good_key, bad_key; 7049a7eb6187SMike Gerdts int rc; 7050a7eb6187SMike Gerdts 7051a7eb6187SMike Gerdts bdev = allocate_bdev("bdev0"); 7052a7eb6187SMike Gerdts 7053a7eb6187SMike Gerdts /* Claim without options should fail */ 7054a7eb6187SMike Gerdts desc = NULL; 7055a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 7056a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7057a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 7058a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, NULL, 7059a7eb6187SMike Gerdts &bdev_ut_if); 7060a7eb6187SMike Gerdts CU_ASSERT(rc == -EINVAL); 7061a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7062a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 0); 7063a7eb6187SMike Gerdts CU_ASSERT(desc->claim == NULL); 7064a7eb6187SMike Gerdts 7065a7eb6187SMike Gerdts /* Claim with options */ 7066a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7067a7eb6187SMike Gerdts snprintf(opts.name, sizeof(opts.name), "%s", "claim with options"); 7068a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&good_key; 7069a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, &opts, 7070a7eb6187SMike Gerdts &bdev_ut_if); 7071a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7072a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED); 7073a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc->claim != NULL); 7074a7eb6187SMike Gerdts CU_ASSERT(desc->claim->module == &bdev_ut_if); 7075a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "claim with options") == 0); 7076a7eb6187SMike Gerdts memset(&opts, 0, sizeof(opts)); 7077a7eb6187SMike Gerdts CU_ASSERT(strcmp(desc->claim->name, "claim with options") == 0); 7078a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 7079a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 7080a7eb6187SMike Gerdts 7081a7eb6187SMike Gerdts /* The claim blocks new writers. */ 7082a7eb6187SMike Gerdts desc2 = NULL; 7083a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc2); 7084a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7085a7eb6187SMike Gerdts CU_ASSERT(desc2 == NULL); 7086a7eb6187SMike Gerdts 7087a7eb6187SMike Gerdts /* New readers are allowed */ 7088a7eb6187SMike Gerdts desc2 = NULL; 7089a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc2); 7090a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7091a7eb6187SMike Gerdts CU_ASSERT(desc2 != NULL); 7092a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 7093a7eb6187SMike Gerdts 7094a7eb6187SMike Gerdts /* No new v2 RWO claims are allowed */ 7095a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, NULL, 7096a7eb6187SMike Gerdts &bdev_ut_if); 7097a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7098a7eb6187SMike Gerdts 7099a7eb6187SMike Gerdts /* No new v2 ROM claims are allowed and the descriptor stays read-only. */ 7100a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 7101a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE, NULL, 7102a7eb6187SMike Gerdts &bdev_ut_if); 7103a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7104a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 7105a7eb6187SMike Gerdts 7106a7eb6187SMike Gerdts /* No new v1 claims are allowed */ 7107a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &bdev_ut_if); 7108a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7109a7eb6187SMike Gerdts 7110a7eb6187SMike Gerdts /* No new v2 RWM claims are allowed if the key does not match */ 7111a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7112a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&bad_key; 7113a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, &opts, 7114a7eb6187SMike Gerdts &bdev_ut_if); 7115a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7116a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 7117a7eb6187SMike Gerdts 7118a7eb6187SMike Gerdts /* None of the above messed up the existing claim */ 7119a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc->claim); 7120a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 7121a7eb6187SMike Gerdts 7122a7eb6187SMike Gerdts /* New v2 RWM claims are allowed and the descriptor is promoted if the key matches. */ 7123a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7124a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&good_key; 7125a7eb6187SMike Gerdts CU_ASSERT(!desc2->write); 7126a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, &opts, 7127a7eb6187SMike Gerdts &bdev_ut_if); 7128a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7129a7eb6187SMike Gerdts CU_ASSERT(desc2->write); 7130a7eb6187SMike Gerdts CU_ASSERT(TAILQ_NEXT(desc->claim, link) == desc2->claim); 7131a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 2); 7132a7eb6187SMike Gerdts 7133a7eb6187SMike Gerdts /* Claim remains when closing the first descriptor */ 7134a7eb6187SMike Gerdts spdk_bdev_close(desc); 7135a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED); 7136a7eb6187SMike Gerdts CU_ASSERT(!TAILQ_EMPTY(&bdev->internal.open_descs)); 7137a7eb6187SMike Gerdts CU_ASSERT(TAILQ_FIRST(&bdev->internal.claim.v2.claims) == desc2->claim); 7138a7eb6187SMike Gerdts UT_ASSERT_CLAIM_V2_COUNT(bdev, 1); 7139a7eb6187SMike Gerdts 7140a7eb6187SMike Gerdts /* Claim removed when closing the other descriptor */ 7141a7eb6187SMike Gerdts spdk_bdev_close(desc2); 7142a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7143a7eb6187SMike Gerdts CU_ASSERT(TAILQ_EMPTY(&bdev->internal.open_descs)); 7144a7eb6187SMike Gerdts 7145a7eb6187SMike Gerdts /* Cannot claim without a key */ 7146a7eb6187SMike Gerdts desc = NULL; 7147a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 7148a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7149a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 7150a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7151a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, &opts, 7152a7eb6187SMike Gerdts &bdev_ut_if); 7153a7eb6187SMike Gerdts CU_ASSERT(rc == -EINVAL); 7154a7eb6187SMike Gerdts spdk_bdev_close(desc); 7155a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7156a7eb6187SMike Gerdts CU_ASSERT(TAILQ_EMPTY(&bdev->internal.open_descs)); 7157a7eb6187SMike Gerdts 7158a7eb6187SMike Gerdts /* Clean up */ 7159a7eb6187SMike Gerdts free_bdev(bdev); 7160a7eb6187SMike Gerdts } 7161a7eb6187SMike Gerdts 7162a7eb6187SMike Gerdts static void 7163a7eb6187SMike Gerdts claim_v2_existing_writer(void) 7164a7eb6187SMike Gerdts { 7165a7eb6187SMike Gerdts struct spdk_bdev *bdev; 7166a7eb6187SMike Gerdts struct spdk_bdev_desc *desc; 7167a7eb6187SMike Gerdts struct spdk_bdev_desc *desc2; 7168a7eb6187SMike Gerdts struct spdk_bdev_claim_opts opts; 7169a7eb6187SMike Gerdts enum spdk_bdev_claim_type type; 7170a7eb6187SMike Gerdts enum spdk_bdev_claim_type types[] = { 7171a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, 7172a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, 7173a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE 7174a7eb6187SMike Gerdts }; 7175a7eb6187SMike Gerdts size_t i; 7176a7eb6187SMike Gerdts int rc; 7177a7eb6187SMike Gerdts 7178a7eb6187SMike Gerdts bdev = allocate_bdev("bdev0"); 7179a7eb6187SMike Gerdts 7180a7eb6187SMike Gerdts desc = NULL; 7181a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc); 7182a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7183a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 7184a7eb6187SMike Gerdts desc2 = NULL; 7185a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc2); 7186a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7187a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc2 != NULL); 7188a7eb6187SMike Gerdts 7189a7eb6187SMike Gerdts for (i = 0; i < SPDK_COUNTOF(types); i++) { 7190a7eb6187SMike Gerdts type = types[i]; 7191a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7192a7eb6187SMike Gerdts if (type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED) { 7193a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&opts; 7194a7eb6187SMike Gerdts } 7195a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, type, &opts, &bdev_ut_if); 7196a7eb6187SMike Gerdts if (type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE) { 7197a7eb6187SMike Gerdts CU_ASSERT(rc == -EINVAL); 7198a7eb6187SMike Gerdts } else { 7199a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7200a7eb6187SMike Gerdts } 7201a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7202a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc2, type, &opts, &bdev_ut_if); 7203a7eb6187SMike Gerdts if (type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE) { 7204a7eb6187SMike Gerdts CU_ASSERT(rc == -EINVAL); 7205a7eb6187SMike Gerdts } else { 7206a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7207a7eb6187SMike Gerdts } 7208a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_NONE); 7209a7eb6187SMike Gerdts } 7210a7eb6187SMike Gerdts 7211a7eb6187SMike Gerdts spdk_bdev_close(desc); 7212a7eb6187SMike Gerdts spdk_bdev_close(desc2); 7213a7eb6187SMike Gerdts 7214a7eb6187SMike Gerdts /* Clean up */ 7215a7eb6187SMike Gerdts free_bdev(bdev); 7216a7eb6187SMike Gerdts } 7217a7eb6187SMike Gerdts 7218a7eb6187SMike Gerdts static void 7219a7eb6187SMike Gerdts claim_v2_existing_v1(void) 7220a7eb6187SMike Gerdts { 7221a7eb6187SMike Gerdts struct spdk_bdev *bdev; 7222a7eb6187SMike Gerdts struct spdk_bdev_desc *desc; 7223a7eb6187SMike Gerdts struct spdk_bdev_claim_opts opts; 7224a7eb6187SMike Gerdts enum spdk_bdev_claim_type type; 7225a7eb6187SMike Gerdts enum spdk_bdev_claim_type types[] = { 7226a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, 7227a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, 7228a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE 7229a7eb6187SMike Gerdts }; 7230a7eb6187SMike Gerdts size_t i; 7231a7eb6187SMike Gerdts int rc; 7232a7eb6187SMike Gerdts 7233a7eb6187SMike Gerdts bdev = allocate_bdev("bdev0"); 7234a7eb6187SMike Gerdts 7235a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &bdev_ut_if); 7236a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7237a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_EXCL_WRITE); 7238a7eb6187SMike Gerdts 7239a7eb6187SMike Gerdts desc = NULL; 7240a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc); 7241a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7242a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 7243a7eb6187SMike Gerdts 7244a7eb6187SMike Gerdts for (i = 0; i < SPDK_COUNTOF(types); i++) { 7245a7eb6187SMike Gerdts type = types[i]; 7246a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7247a7eb6187SMike Gerdts if (type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED) { 7248a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&opts; 7249a7eb6187SMike Gerdts } 7250a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, type, &opts, &bdev_ut_if); 7251a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7252a7eb6187SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_EXCL_WRITE); 7253a7eb6187SMike Gerdts } 7254a7eb6187SMike Gerdts 7255a7eb6187SMike Gerdts spdk_bdev_module_release_bdev(bdev); 7256a7eb6187SMike Gerdts spdk_bdev_close(desc); 7257a7eb6187SMike Gerdts 7258a7eb6187SMike Gerdts /* Clean up */ 7259a7eb6187SMike Gerdts free_bdev(bdev); 7260a7eb6187SMike Gerdts } 7261a7eb6187SMike Gerdts 7262a7eb6187SMike Gerdts static void 7263a7eb6187SMike Gerdts claim_v1_existing_v2(void) 7264a7eb6187SMike Gerdts { 7265a7eb6187SMike Gerdts struct spdk_bdev *bdev; 7266a7eb6187SMike Gerdts struct spdk_bdev_desc *desc; 7267a7eb6187SMike Gerdts struct spdk_bdev_claim_opts opts; 7268a7eb6187SMike Gerdts enum spdk_bdev_claim_type type; 7269a7eb6187SMike Gerdts enum spdk_bdev_claim_type types[] = { 7270a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE, 7271a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED, 7272a7eb6187SMike Gerdts SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE 7273a7eb6187SMike Gerdts }; 7274a7eb6187SMike Gerdts size_t i; 7275a7eb6187SMike Gerdts int rc; 7276a7eb6187SMike Gerdts 7277a7eb6187SMike Gerdts bdev = allocate_bdev("bdev0"); 7278a7eb6187SMike Gerdts 7279a7eb6187SMike Gerdts for (i = 0; i < SPDK_COUNTOF(types); i++) { 7280a7eb6187SMike Gerdts type = types[i]; 7281a7eb6187SMike Gerdts 7282a7eb6187SMike Gerdts desc = NULL; 7283a7eb6187SMike Gerdts rc = spdk_bdev_open_ext("bdev0", false, bdev_ut_event_cb, NULL, &desc); 7284a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7285a7eb6187SMike Gerdts SPDK_CU_ASSERT_FATAL(desc != NULL); 7286a7eb6187SMike Gerdts 7287a7eb6187SMike Gerdts /* Get a v2 claim */ 7288a7eb6187SMike Gerdts spdk_bdev_claim_opts_init(&opts, sizeof(opts)); 7289a7eb6187SMike Gerdts if (type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_SHARED) { 7290a7eb6187SMike Gerdts opts.shared_claim_key = (uint64_t)&opts; 7291a7eb6187SMike Gerdts } 7292a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(desc, type, &opts, &bdev_ut_if); 7293a7eb6187SMike Gerdts CU_ASSERT(rc == 0); 7294a7eb6187SMike Gerdts 7295a7eb6187SMike Gerdts /* Fail to get a v1 claim */ 7296a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &bdev_ut_if); 7297a7eb6187SMike Gerdts CU_ASSERT(rc == -EPERM); 7298a7eb6187SMike Gerdts 7299a7eb6187SMike Gerdts spdk_bdev_close(desc); 7300a7eb6187SMike Gerdts 7301a7eb6187SMike Gerdts /* Now v1 succeeds */ 7302a7eb6187SMike Gerdts rc = spdk_bdev_module_claim_bdev(bdev, NULL, &bdev_ut_if); 7303a7eb6187SMike Gerdts CU_ASSERT(rc == 0) 7304a7eb6187SMike Gerdts spdk_bdev_module_release_bdev(bdev); 7305a7eb6187SMike Gerdts } 7306a7eb6187SMike Gerdts 7307a7eb6187SMike Gerdts /* Clean up */ 7308a7eb6187SMike Gerdts free_bdev(bdev); 7309a7eb6187SMike Gerdts } 7310a7eb6187SMike Gerdts 7311cd7064c7SNathan Claudel static int ut_examine_claimed_init0(void); 7312cd7064c7SNathan Claudel static int ut_examine_claimed_init1(void); 731386bbcdb8SMike Gerdts static void ut_examine_claimed_config0(struct spdk_bdev *bdev); 731486bbcdb8SMike Gerdts static void ut_examine_claimed_disk0(struct spdk_bdev *bdev); 731586bbcdb8SMike Gerdts static void ut_examine_claimed_config1(struct spdk_bdev *bdev); 731686bbcdb8SMike Gerdts static void ut_examine_claimed_disk1(struct spdk_bdev *bdev); 731786bbcdb8SMike Gerdts 731886bbcdb8SMike Gerdts #define UT_MAX_EXAMINE_MODS 2 731986bbcdb8SMike Gerdts struct spdk_bdev_module examine_claimed_mods[UT_MAX_EXAMINE_MODS] = { 732086bbcdb8SMike Gerdts { 732186bbcdb8SMike Gerdts .name = "vbdev_ut_examine0", 7322cd7064c7SNathan Claudel .module_init = ut_examine_claimed_init0, 732386bbcdb8SMike Gerdts .module_fini = vbdev_ut_module_fini, 732486bbcdb8SMike Gerdts .examine_config = ut_examine_claimed_config0, 732586bbcdb8SMike Gerdts .examine_disk = ut_examine_claimed_disk0, 732686bbcdb8SMike Gerdts }, 732786bbcdb8SMike Gerdts { 732886bbcdb8SMike Gerdts .name = "vbdev_ut_examine1", 7329cd7064c7SNathan Claudel .module_init = ut_examine_claimed_init1, 733086bbcdb8SMike Gerdts .module_fini = vbdev_ut_module_fini, 733186bbcdb8SMike Gerdts .examine_config = ut_examine_claimed_config1, 733286bbcdb8SMike Gerdts .examine_disk = ut_examine_claimed_disk1, 733386bbcdb8SMike Gerdts } 733486bbcdb8SMike Gerdts }; 733586bbcdb8SMike Gerdts 733686bbcdb8SMike Gerdts SPDK_BDEV_MODULE_REGISTER(bdev_ut_claimed0, &examine_claimed_mods[0]) 733786bbcdb8SMike Gerdts SPDK_BDEV_MODULE_REGISTER(bdev_ut_claimed1, &examine_claimed_mods[1]) 733886bbcdb8SMike Gerdts 733986bbcdb8SMike Gerdts struct ut_examine_claimed_ctx { 734086bbcdb8SMike Gerdts uint32_t examine_config_count; 734186bbcdb8SMike Gerdts uint32_t examine_disk_count; 734286bbcdb8SMike Gerdts 734386bbcdb8SMike Gerdts /* Claim type to take, with these options */ 734486bbcdb8SMike Gerdts enum spdk_bdev_claim_type claim_type; 734586bbcdb8SMike Gerdts struct spdk_bdev_claim_opts claim_opts; 734686bbcdb8SMike Gerdts 734786bbcdb8SMike Gerdts /* Expected return value from spdk_bdev_module_claim_bdev_desc() */ 734886bbcdb8SMike Gerdts int expect_claim_err; 734986bbcdb8SMike Gerdts 735086bbcdb8SMike Gerdts /* Descriptor used for a claim */ 735186bbcdb8SMike Gerdts struct spdk_bdev_desc *desc; 735286bbcdb8SMike Gerdts } examine_claimed_ctx[UT_MAX_EXAMINE_MODS]; 735386bbcdb8SMike Gerdts 735486bbcdb8SMike Gerdts bool ut_testing_examine_claimed; 735586bbcdb8SMike Gerdts 7356cd7064c7SNathan Claudel /* 7357cd7064c7SNathan Claudel * Store the order in which the modules were initialized, 7358cd7064c7SNathan Claudel * since we have no guarantee on the order of execution of the constructors. 7359cd7064c7SNathan Claudel * Modules are examined in reverse order of their initialization. 7360cd7064c7SNathan Claudel */ 7361cd7064c7SNathan Claudel static int g_ut_examine_claimed_order[UT_MAX_EXAMINE_MODS]; 7362cd7064c7SNathan Claudel static int 7363cd7064c7SNathan Claudel ut_examine_claimed_init(uint32_t modnum) 7364cd7064c7SNathan Claudel { 7365cd7064c7SNathan Claudel static int current = UT_MAX_EXAMINE_MODS; 7366cd7064c7SNathan Claudel 736734edd9f1SKamil Godzwon /* Only do this for the first initialization of the bdev framework */ 7368cd7064c7SNathan Claudel if (current == 0) { 7369cd7064c7SNathan Claudel return 0; 7370cd7064c7SNathan Claudel } 7371cd7064c7SNathan Claudel g_ut_examine_claimed_order[modnum] = --current; 7372cd7064c7SNathan Claudel 7373cd7064c7SNathan Claudel return 0; 7374cd7064c7SNathan Claudel } 7375cd7064c7SNathan Claudel 7376cd7064c7SNathan Claudel static int 7377cd7064c7SNathan Claudel ut_examine_claimed_init0(void) 7378cd7064c7SNathan Claudel { 7379cd7064c7SNathan Claudel return ut_examine_claimed_init(0); 7380cd7064c7SNathan Claudel } 7381cd7064c7SNathan Claudel 7382cd7064c7SNathan Claudel static int 7383cd7064c7SNathan Claudel ut_examine_claimed_init1(void) 7384cd7064c7SNathan Claudel { 7385cd7064c7SNathan Claudel return ut_examine_claimed_init(1); 7386cd7064c7SNathan Claudel } 7387cd7064c7SNathan Claudel 738886bbcdb8SMike Gerdts static void 738986bbcdb8SMike Gerdts reset_examine_claimed_ctx(void) 739086bbcdb8SMike Gerdts { 739186bbcdb8SMike Gerdts struct ut_examine_claimed_ctx *ctx; 739286bbcdb8SMike Gerdts uint32_t i; 739386bbcdb8SMike Gerdts 739486bbcdb8SMike Gerdts for (i = 0; i < SPDK_COUNTOF(examine_claimed_ctx); i++) { 739586bbcdb8SMike Gerdts ctx = &examine_claimed_ctx[i]; 739686bbcdb8SMike Gerdts if (ctx->desc != NULL) { 739786bbcdb8SMike Gerdts spdk_bdev_close(ctx->desc); 739886bbcdb8SMike Gerdts } 739986bbcdb8SMike Gerdts memset(ctx, 0, sizeof(*ctx)); 740086bbcdb8SMike Gerdts spdk_bdev_claim_opts_init(&ctx->claim_opts, sizeof(ctx->claim_opts)); 740186bbcdb8SMike Gerdts } 740286bbcdb8SMike Gerdts } 740386bbcdb8SMike Gerdts 740486bbcdb8SMike Gerdts static void 740586bbcdb8SMike Gerdts examine_claimed_config(struct spdk_bdev *bdev, uint32_t modnum) 740686bbcdb8SMike Gerdts { 740786bbcdb8SMike Gerdts SPDK_CU_ASSERT_FATAL(modnum < UT_MAX_EXAMINE_MODS); 740886bbcdb8SMike Gerdts struct spdk_bdev_module *module = &examine_claimed_mods[modnum]; 740986bbcdb8SMike Gerdts struct ut_examine_claimed_ctx *ctx = &examine_claimed_ctx[modnum]; 741086bbcdb8SMike Gerdts int rc; 741186bbcdb8SMike Gerdts 741286bbcdb8SMike Gerdts if (!ut_testing_examine_claimed) { 741386bbcdb8SMike Gerdts spdk_bdev_module_examine_done(module); 741486bbcdb8SMike Gerdts return; 741586bbcdb8SMike Gerdts } 741686bbcdb8SMike Gerdts 741786bbcdb8SMike Gerdts ctx->examine_config_count++; 741886bbcdb8SMike Gerdts 741986bbcdb8SMike Gerdts if (ctx->claim_type != SPDK_BDEV_CLAIM_NONE) { 742086bbcdb8SMike Gerdts rc = spdk_bdev_open_ext(bdev->name, false, bdev_ut_event_cb, &ctx->claim_opts, 742186bbcdb8SMike Gerdts &ctx->desc); 742286bbcdb8SMike Gerdts CU_ASSERT(rc == 0); 742386bbcdb8SMike Gerdts 742486bbcdb8SMike Gerdts rc = spdk_bdev_module_claim_bdev_desc(ctx->desc, ctx->claim_type, NULL, module); 742586bbcdb8SMike Gerdts CU_ASSERT(rc == ctx->expect_claim_err); 742686bbcdb8SMike Gerdts } 742786bbcdb8SMike Gerdts spdk_bdev_module_examine_done(module); 742886bbcdb8SMike Gerdts } 742986bbcdb8SMike Gerdts 743086bbcdb8SMike Gerdts static void 743186bbcdb8SMike Gerdts ut_examine_claimed_config0(struct spdk_bdev *bdev) 743286bbcdb8SMike Gerdts { 7433cd7064c7SNathan Claudel examine_claimed_config(bdev, g_ut_examine_claimed_order[0]); 743486bbcdb8SMike Gerdts } 743586bbcdb8SMike Gerdts 743686bbcdb8SMike Gerdts static void 743786bbcdb8SMike Gerdts ut_examine_claimed_config1(struct spdk_bdev *bdev) 743886bbcdb8SMike Gerdts { 7439cd7064c7SNathan Claudel examine_claimed_config(bdev, g_ut_examine_claimed_order[1]); 744086bbcdb8SMike Gerdts } 744186bbcdb8SMike Gerdts 744286bbcdb8SMike Gerdts static void 744386bbcdb8SMike Gerdts examine_claimed_disk(struct spdk_bdev *bdev, uint32_t modnum) 744486bbcdb8SMike Gerdts { 744586bbcdb8SMike Gerdts SPDK_CU_ASSERT_FATAL(modnum < UT_MAX_EXAMINE_MODS); 744686bbcdb8SMike Gerdts struct spdk_bdev_module *module = &examine_claimed_mods[modnum]; 744786bbcdb8SMike Gerdts struct ut_examine_claimed_ctx *ctx = &examine_claimed_ctx[modnum]; 744886bbcdb8SMike Gerdts 744986bbcdb8SMike Gerdts if (!ut_testing_examine_claimed) { 745086bbcdb8SMike Gerdts spdk_bdev_module_examine_done(module); 745186bbcdb8SMike Gerdts return; 745286bbcdb8SMike Gerdts } 745386bbcdb8SMike Gerdts 745486bbcdb8SMike Gerdts ctx->examine_disk_count++; 745586bbcdb8SMike Gerdts 745686bbcdb8SMike Gerdts spdk_bdev_module_examine_done(module); 745786bbcdb8SMike Gerdts } 745886bbcdb8SMike Gerdts 745986bbcdb8SMike Gerdts static void 746086bbcdb8SMike Gerdts ut_examine_claimed_disk0(struct spdk_bdev *bdev) 746186bbcdb8SMike Gerdts { 746286bbcdb8SMike Gerdts examine_claimed_disk(bdev, 0); 746386bbcdb8SMike Gerdts } 746486bbcdb8SMike Gerdts 746586bbcdb8SMike Gerdts static void 746686bbcdb8SMike Gerdts ut_examine_claimed_disk1(struct spdk_bdev *bdev) 746786bbcdb8SMike Gerdts { 746886bbcdb8SMike Gerdts examine_claimed_disk(bdev, 1); 746986bbcdb8SMike Gerdts } 747086bbcdb8SMike Gerdts 747102935561SEd Reed static bool g_examine_done = false; 747202935561SEd Reed 747386bbcdb8SMike Gerdts static void 747402935561SEd Reed ut_examine_done_cb(void *ctx) 747502935561SEd Reed { 747602935561SEd Reed g_examine_done = true; 747702935561SEd Reed } 747802935561SEd Reed 747902935561SEd Reed static void 748002935561SEd Reed examine_claimed_common(bool autoexamine) 748186bbcdb8SMike Gerdts { 748286bbcdb8SMike Gerdts struct spdk_bdev *bdev; 748386bbcdb8SMike Gerdts struct spdk_bdev_module *mod = examine_claimed_mods; 748486bbcdb8SMike Gerdts struct ut_examine_claimed_ctx *ctx = examine_claimed_ctx; 748502935561SEd Reed struct spdk_bdev_opts bdev_opts = {}; 748602935561SEd Reed int rc; 748702935561SEd Reed 748802935561SEd Reed spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 748902935561SEd Reed bdev_opts.bdev_auto_examine = autoexamine; 749002935561SEd Reed ut_init_bdev(&bdev_opts); 749186bbcdb8SMike Gerdts 749286bbcdb8SMike Gerdts ut_testing_examine_claimed = true; 749386bbcdb8SMike Gerdts reset_examine_claimed_ctx(); 749486bbcdb8SMike Gerdts 749586bbcdb8SMike Gerdts /* 749686bbcdb8SMike Gerdts * With one module claiming, both modules' examine_config should be called, but only the 749786bbcdb8SMike Gerdts * claiming module's examine_disk should be called. 749886bbcdb8SMike Gerdts */ 749986bbcdb8SMike Gerdts ctx[0].claim_type = SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE; 750002935561SEd Reed g_examine_done = false; 750186bbcdb8SMike Gerdts bdev = allocate_bdev("bdev0"); 750202935561SEd Reed 750302935561SEd Reed if (!autoexamine) { 750402935561SEd Reed rc = spdk_bdev_examine("bdev0"); 750502935561SEd Reed CU_ASSERT(rc == 0); 750602935561SEd Reed rc = spdk_bdev_wait_for_examine(ut_examine_done_cb, NULL); 750702935561SEd Reed CU_ASSERT(rc == 0); 750802935561SEd Reed CU_ASSERT(!g_examine_done); 750902935561SEd Reed poll_threads(); 751002935561SEd Reed CU_ASSERT(g_examine_done); 751102935561SEd Reed } 751202935561SEd Reed 751386bbcdb8SMike Gerdts CU_ASSERT(ctx[0].examine_config_count == 1); 751486bbcdb8SMike Gerdts CU_ASSERT(ctx[0].examine_disk_count == 1); 751586bbcdb8SMike Gerdts SPDK_CU_ASSERT_FATAL(ctx[0].desc != NULL); 751686bbcdb8SMike Gerdts CU_ASSERT(ctx[0].desc->claim->module == &mod[0]); 751786bbcdb8SMike Gerdts CU_ASSERT(ctx[1].examine_config_count == 1); 751886bbcdb8SMike Gerdts CU_ASSERT(ctx[1].examine_disk_count == 0); 751986bbcdb8SMike Gerdts CU_ASSERT(ctx[1].desc == NULL); 752086bbcdb8SMike Gerdts reset_examine_claimed_ctx(); 752186bbcdb8SMike Gerdts free_bdev(bdev); 752286bbcdb8SMike Gerdts 752386bbcdb8SMike Gerdts /* 752486bbcdb8SMike Gerdts * With two modules claiming, both modules' examine_config and examine_disk should be 752586bbcdb8SMike Gerdts * called. 752686bbcdb8SMike Gerdts */ 752786bbcdb8SMike Gerdts ctx[0].claim_type = SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE; 752886bbcdb8SMike Gerdts ctx[1].claim_type = SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE; 752902935561SEd Reed g_examine_done = false; 753086bbcdb8SMike Gerdts bdev = allocate_bdev("bdev0"); 753102935561SEd Reed 753202935561SEd Reed if (!autoexamine) { 753302935561SEd Reed rc = spdk_bdev_examine("bdev0"); 753402935561SEd Reed CU_ASSERT(rc == 0); 753502935561SEd Reed rc = spdk_bdev_wait_for_examine(ut_examine_done_cb, NULL); 753602935561SEd Reed CU_ASSERT(rc == 0); 753702935561SEd Reed CU_ASSERT(!g_examine_done); 753802935561SEd Reed poll_threads(); 753902935561SEd Reed CU_ASSERT(g_examine_done); 754002935561SEd Reed } 754102935561SEd Reed 754286bbcdb8SMike Gerdts CU_ASSERT(ctx[0].examine_config_count == 1); 754386bbcdb8SMike Gerdts CU_ASSERT(ctx[0].examine_disk_count == 1); 754486bbcdb8SMike Gerdts SPDK_CU_ASSERT_FATAL(ctx[0].desc != NULL); 754586bbcdb8SMike Gerdts CU_ASSERT(ctx[0].desc->claim->module == &mod[0]); 754686bbcdb8SMike Gerdts CU_ASSERT(ctx[1].examine_config_count == 1); 754786bbcdb8SMike Gerdts CU_ASSERT(ctx[1].examine_disk_count == 1); 754886bbcdb8SMike Gerdts SPDK_CU_ASSERT_FATAL(ctx[1].desc != NULL); 754986bbcdb8SMike Gerdts CU_ASSERT(ctx[1].desc->claim->module == &mod[1]); 755086bbcdb8SMike Gerdts reset_examine_claimed_ctx(); 755186bbcdb8SMike Gerdts free_bdev(bdev); 755286bbcdb8SMike Gerdts 755386bbcdb8SMike Gerdts /* 755486bbcdb8SMike Gerdts * If two vbdev modules try to claim with conflicting claim types, the module that was added 755586bbcdb8SMike Gerdts * last wins. The winner gets the claim and is the only one that has its examine_disk 755686bbcdb8SMike Gerdts * callback invoked. 755786bbcdb8SMike Gerdts */ 755886bbcdb8SMike Gerdts ctx[0].claim_type = SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE; 755986bbcdb8SMike Gerdts ctx[0].expect_claim_err = -EPERM; 756086bbcdb8SMike Gerdts ctx[1].claim_type = SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE; 756102935561SEd Reed g_examine_done = false; 756286bbcdb8SMike Gerdts bdev = allocate_bdev("bdev0"); 756302935561SEd Reed 756402935561SEd Reed if (!autoexamine) { 756502935561SEd Reed rc = spdk_bdev_examine("bdev0"); 756602935561SEd Reed CU_ASSERT(rc == 0); 756702935561SEd Reed rc = spdk_bdev_wait_for_examine(ut_examine_done_cb, NULL); 756802935561SEd Reed CU_ASSERT(rc == 0); 756902935561SEd Reed CU_ASSERT(!g_examine_done); 757002935561SEd Reed poll_threads(); 757102935561SEd Reed CU_ASSERT(g_examine_done); 757202935561SEd Reed } 757302935561SEd Reed 757486bbcdb8SMike Gerdts CU_ASSERT(ctx[0].examine_config_count == 1); 757586bbcdb8SMike Gerdts CU_ASSERT(ctx[0].examine_disk_count == 0); 757686bbcdb8SMike Gerdts CU_ASSERT(ctx[1].examine_config_count == 1); 757786bbcdb8SMike Gerdts CU_ASSERT(ctx[1].examine_disk_count == 1); 757886bbcdb8SMike Gerdts SPDK_CU_ASSERT_FATAL(ctx[1].desc != NULL); 757986bbcdb8SMike Gerdts CU_ASSERT(ctx[1].desc->claim->module == &mod[1]); 758086bbcdb8SMike Gerdts CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE); 758186bbcdb8SMike Gerdts reset_examine_claimed_ctx(); 758286bbcdb8SMike Gerdts free_bdev(bdev); 758386bbcdb8SMike Gerdts 758486bbcdb8SMike Gerdts ut_testing_examine_claimed = false; 758502935561SEd Reed 758602935561SEd Reed ut_fini_bdev(); 758702935561SEd Reed } 758802935561SEd Reed 758902935561SEd Reed static void 759002935561SEd Reed examine_claimed(void) 759102935561SEd Reed { 759202935561SEd Reed examine_claimed_common(true); 759302935561SEd Reed } 759402935561SEd Reed 759502935561SEd Reed static void 759602935561SEd Reed examine_claimed_manual(void) 759702935561SEd Reed { 759802935561SEd Reed examine_claimed_common(false); 759986bbcdb8SMike Gerdts } 760086bbcdb8SMike Gerdts 7601fee788f6SJim Harris static void 7602fee788f6SJim Harris get_numa_id(void) 7603fee788f6SJim Harris { 7604fee788f6SJim Harris struct spdk_bdev bdev = {}; 7605fee788f6SJim Harris 7606fee788f6SJim Harris bdev.numa.id = 0; 7607fee788f6SJim Harris bdev.numa.id_valid = 0; 7608fee788f6SJim Harris CU_ASSERT(spdk_bdev_get_numa_id(&bdev) == SPDK_ENV_NUMA_ID_ANY); 7609fee788f6SJim Harris 7610fee788f6SJim Harris bdev.numa.id_valid = 1; 7611fee788f6SJim Harris CU_ASSERT(spdk_bdev_get_numa_id(&bdev) == 0); 7612fee788f6SJim Harris 7613fee788f6SJim Harris bdev.numa.id = SPDK_ENV_NUMA_ID_ANY; 7614fee788f6SJim Harris CU_ASSERT(spdk_bdev_get_numa_id(&bdev) == SPDK_ENV_NUMA_ID_ANY); 7615fee788f6SJim Harris } 7616fee788f6SJim Harris 761763e0c25dSVasilii Ivanov static void 761863e0c25dSVasilii Ivanov get_device_stat_with_reset_cb(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, void *cb_arg, 761963e0c25dSVasilii Ivanov int rc) 762063e0c25dSVasilii Ivanov { 762163e0c25dSVasilii Ivanov *(bool *)cb_arg = true; 762263e0c25dSVasilii Ivanov } 762363e0c25dSVasilii Ivanov 762463e0c25dSVasilii Ivanov static void 762563e0c25dSVasilii Ivanov get_device_stat_with_given_reset(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, 762663e0c25dSVasilii Ivanov enum spdk_bdev_reset_stat_mode mode) 762763e0c25dSVasilii Ivanov { 762863e0c25dSVasilii Ivanov bool done = false; 762963e0c25dSVasilii Ivanov 763063e0c25dSVasilii Ivanov spdk_bdev_get_device_stat(bdev, stat, mode, get_device_stat_with_reset_cb, &done); 763163e0c25dSVasilii Ivanov while (!done) { poll_threads(); } 763263e0c25dSVasilii Ivanov } 763363e0c25dSVasilii Ivanov 763463e0c25dSVasilii Ivanov static void 763563e0c25dSVasilii Ivanov get_device_stat_with_reset(void) 763663e0c25dSVasilii Ivanov { 763763e0c25dSVasilii Ivanov struct spdk_bdev *bdev; 763863e0c25dSVasilii Ivanov struct spdk_bdev_desc *desc = NULL; 763963e0c25dSVasilii Ivanov struct spdk_io_channel *io_ch; 764063e0c25dSVasilii Ivanov struct spdk_bdev_opts bdev_opts = {}; 764163e0c25dSVasilii Ivanov struct spdk_bdev_io_stat *stat; 764263e0c25dSVasilii Ivanov 764363e0c25dSVasilii Ivanov spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 764463e0c25dSVasilii Ivanov bdev_opts.bdev_io_pool_size = 2; 764563e0c25dSVasilii Ivanov bdev_opts.bdev_io_cache_size = 1; 764663e0c25dSVasilii Ivanov ut_init_bdev(&bdev_opts); 764763e0c25dSVasilii Ivanov bdev = allocate_bdev("bdev0"); 764863e0c25dSVasilii Ivanov 764963e0c25dSVasilii Ivanov CU_ASSERT(spdk_bdev_open_ext("bdev0", true, bdev_ut_event_cb, NULL, &desc) == 0); 765063e0c25dSVasilii Ivanov SPDK_CU_ASSERT_FATAL(desc != NULL); 765163e0c25dSVasilii Ivanov CU_ASSERT(bdev == spdk_bdev_desc_get_bdev(desc)); 765263e0c25dSVasilii Ivanov io_ch = spdk_bdev_get_io_channel(desc); 765363e0c25dSVasilii Ivanov CU_ASSERT(io_ch != NULL); 765463e0c25dSVasilii Ivanov 765563e0c25dSVasilii Ivanov g_io_done = false; 765663e0c25dSVasilii Ivanov CU_ASSERT(spdk_bdev_read(desc, io_ch, (void *)0x1000, 0, 4096, io_done, NULL) == 0); 765763e0c25dSVasilii Ivanov spdk_delay_us(10); 765863e0c25dSVasilii Ivanov stub_complete_io(1); 765963e0c25dSVasilii Ivanov CU_ASSERT(g_io_done == true); 766063e0c25dSVasilii Ivanov 766163e0c25dSVasilii Ivanov stat = calloc(1, sizeof(struct spdk_bdev_io_stat)); 766263e0c25dSVasilii Ivanov SPDK_CU_ASSERT_FATAL(stat != NULL); 766363e0c25dSVasilii Ivanov 766463e0c25dSVasilii Ivanov /* Get stat without resetting and check that it is correct */ 766563e0c25dSVasilii Ivanov get_device_stat_with_given_reset(bdev, stat, SPDK_BDEV_RESET_STAT_NONE); 766663e0c25dSVasilii Ivanov CU_ASSERT(stat->bytes_read == 4096); 766763e0c25dSVasilii Ivanov CU_ASSERT(stat->max_read_latency_ticks == 10); 766863e0c25dSVasilii Ivanov 766963e0c25dSVasilii Ivanov /** 767063e0c25dSVasilii Ivanov * Check that stat was not reseted after previous step, 767163e0c25dSVasilii Ivanov * send get request with resetting maxmin stats 767263e0c25dSVasilii Ivanov */ 767363e0c25dSVasilii Ivanov get_device_stat_with_given_reset(bdev, stat, SPDK_BDEV_RESET_STAT_MAXMIN); 767463e0c25dSVasilii Ivanov CU_ASSERT(stat->bytes_read == 4096); 767563e0c25dSVasilii Ivanov CU_ASSERT(stat->max_read_latency_ticks == 10); 767663e0c25dSVasilii Ivanov 767763e0c25dSVasilii Ivanov /** 767863e0c25dSVasilii Ivanov * Check that maxmins stats are reseted after previous step, 767963e0c25dSVasilii Ivanov * send get request with resetting all stats 768063e0c25dSVasilii Ivanov */ 768163e0c25dSVasilii Ivanov get_device_stat_with_given_reset(bdev, stat, SPDK_BDEV_RESET_STAT_ALL); 768263e0c25dSVasilii Ivanov CU_ASSERT(stat->bytes_read == 4096); 768363e0c25dSVasilii Ivanov CU_ASSERT(stat->max_read_latency_ticks == 0); 768463e0c25dSVasilii Ivanov 768563e0c25dSVasilii Ivanov /* Check that all stats are reseted after previous step */ 768663e0c25dSVasilii Ivanov get_device_stat_with_given_reset(bdev, stat, SPDK_BDEV_RESET_STAT_NONE); 768763e0c25dSVasilii Ivanov CU_ASSERT(stat->bytes_read == 0); 768863e0c25dSVasilii Ivanov CU_ASSERT(stat->max_read_latency_ticks == 0); 768963e0c25dSVasilii Ivanov 769063e0c25dSVasilii Ivanov free(stat); 769163e0c25dSVasilii Ivanov spdk_put_io_channel(io_ch); 769263e0c25dSVasilii Ivanov spdk_bdev_close(desc); 769363e0c25dSVasilii Ivanov free_bdev(bdev); 769463e0c25dSVasilii Ivanov ut_fini_bdev(); 769563e0c25dSVasilii Ivanov } 769663e0c25dSVasilii Ivanov 769716e5e505SShuhei Matsumoto static void 769816e5e505SShuhei Matsumoto open_ext_v2_test(void) 769916e5e505SShuhei Matsumoto { 770016e5e505SShuhei Matsumoto struct spdk_bdev_open_opts opts; 770116e5e505SShuhei Matsumoto struct spdk_bdev *bdev; 770216e5e505SShuhei Matsumoto struct spdk_bdev_desc *desc; 770316e5e505SShuhei Matsumoto int rc; 770416e5e505SShuhei Matsumoto 770516e5e505SShuhei Matsumoto bdev = allocate_bdev("bdev0"); 770616e5e505SShuhei Matsumoto 770716e5e505SShuhei Matsumoto rc = spdk_bdev_open_ext_v2("bdev0", true, bdev_ut_event_cb, NULL, NULL, &desc); 770816e5e505SShuhei Matsumoto CU_ASSERT(rc == 0); 770916e5e505SShuhei Matsumoto SPDK_CU_ASSERT_FATAL(desc != NULL); 771016e5e505SShuhei Matsumoto CU_ASSERT(desc->write == true); 771116e5e505SShuhei Matsumoto CU_ASSERT(desc->opts.hide_metadata == false); 771216e5e505SShuhei Matsumoto 771316e5e505SShuhei Matsumoto spdk_bdev_close(desc); 771416e5e505SShuhei Matsumoto 771516e5e505SShuhei Matsumoto spdk_bdev_open_opts_init(&opts, sizeof(opts)); 771616e5e505SShuhei Matsumoto opts.hide_metadata = true; 771716e5e505SShuhei Matsumoto 771816e5e505SShuhei Matsumoto rc = spdk_bdev_open_ext_v2("bdev0", true, bdev_ut_event_cb, NULL, &opts, &desc); 771916e5e505SShuhei Matsumoto CU_ASSERT(rc == 0); 772016e5e505SShuhei Matsumoto CU_ASSERT(desc->write == true); 772116e5e505SShuhei Matsumoto CU_ASSERT(desc->opts.hide_metadata == true); 772216e5e505SShuhei Matsumoto 772316e5e505SShuhei Matsumoto spdk_bdev_close(desc); 772416e5e505SShuhei Matsumoto 772516e5e505SShuhei Matsumoto free_bdev(bdev); 772616e5e505SShuhei Matsumoto } 772716e5e505SShuhei Matsumoto 77280836dccdSShuhei Matsumoto static void 77290836dccdSShuhei Matsumoto bdev_io_init_dif_ctx_test(void) 77300836dccdSShuhei Matsumoto { 77310836dccdSShuhei Matsumoto struct spdk_bdev *bdev; 77320836dccdSShuhei Matsumoto struct spdk_bdev_io bdev_io; 77330836dccdSShuhei Matsumoto int rc; 77340836dccdSShuhei Matsumoto 77350836dccdSShuhei Matsumoto bdev = allocate_bdev("bdev0"); 77360836dccdSShuhei Matsumoto 77370836dccdSShuhei Matsumoto /* This is invalid because md_len should be larger than PI size. */ 77380836dccdSShuhei Matsumoto bdev->dif_pi_format = SPDK_DIF_PI_FORMAT_32; 77390836dccdSShuhei Matsumoto bdev->blocklen = 4096 + 8; 77400836dccdSShuhei Matsumoto bdev->md_len = 8; 77410836dccdSShuhei Matsumoto bdev->md_interleave = true; 77420836dccdSShuhei Matsumoto 77430836dccdSShuhei Matsumoto bdev_io.bdev = bdev; 77440836dccdSShuhei Matsumoto 77450836dccdSShuhei Matsumoto /* Check if initialization detects error. */ 77460836dccdSShuhei Matsumoto rc = bdev_io_init_dif_ctx(&bdev_io); 77470836dccdSShuhei Matsumoto CU_ASSERT(rc != 0); 77480836dccdSShuhei Matsumoto 77490836dccdSShuhei Matsumoto /* Increase md_len to pass initialization check. */ 77500836dccdSShuhei Matsumoto bdev->blocklen = 4096 + 16; 77510836dccdSShuhei Matsumoto bdev->md_len = 16; 77520836dccdSShuhei Matsumoto 77530836dccdSShuhei Matsumoto rc = bdev_io_init_dif_ctx(&bdev_io); 77540836dccdSShuhei Matsumoto CU_ASSERT(rc == 0); 77550836dccdSShuhei Matsumoto 77560836dccdSShuhei Matsumoto free_bdev(bdev); 77570836dccdSShuhei Matsumoto } 77580836dccdSShuhei Matsumoto 77594ee51dcbSJim Harris int 77604ee51dcbSJim Harris main(int argc, char **argv) 77614ee51dcbSJim Harris { 77624ee51dcbSJim Harris CU_pSuite suite = NULL; 77634ee51dcbSJim Harris unsigned int num_failures; 77644ee51dcbSJim Harris 776578b696bcSVitaliy Mysak CU_initialize_registry(); 77664ee51dcbSJim Harris 776780b22cf3SKonrad Sztyber suite = CU_add_suite("bdev", ut_bdev_setup, ut_bdev_teardown); 77684ee51dcbSJim Harris 7769dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bytes_to_blocks_test); 7770dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, num_blocks_test); 7771dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, io_valid_test); 7772dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, open_write_test); 77739f9c7161SMike Gerdts CU_ADD_TEST(suite, claim_test); 7774dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, alias_add_del_test); 7775dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, get_device_stat_test); 7776dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_types_test); 7777dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_wait_test); 77783b616c0fSJin Yu CU_ADD_TEST(suite, bdev_io_spans_split_test); 77799697d84fSJin Yu CU_ADD_TEST(suite, bdev_io_boundary_split_test); 77809697d84fSJin Yu CU_ADD_TEST(suite, bdev_io_max_size_and_segment_split_test); 77811fae3687SJin Yu CU_ADD_TEST(suite, bdev_io_mix_split_test); 7782dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_split_with_io_wait); 7783d6e9827eSArtur Paszkiewicz CU_ADD_TEST(suite, bdev_io_write_unit_split_test); 7784dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_alignment_with_boundary); 7785dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_io_alignment); 7786dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_histograms); 7787dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_write_zeroes); 7788dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_compare_and_write); 7789dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_compare); 77900bd6b7f2SJonas Pfefferle CU_ADD_TEST(suite, bdev_compare_emulated); 77916127461cSmatthewb CU_ADD_TEST(suite, bdev_zcopy_write); 77926127461cSmatthewb CU_ADD_TEST(suite, bdev_zcopy_read); 7793dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_open_while_hotremove); 7794dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_close_while_hotremove); 77956e17adcbSShuhei Matsumoto CU_ADD_TEST(suite, bdev_open_ext_test); 77967bcd316dSGangCao CU_ADD_TEST(suite, bdev_open_ext_unregister); 7797dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, bdev_set_io_timeout); 779848ce2c97SGangCao CU_ADD_TEST(suite, bdev_set_qd_sampling); 7799dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lba_range_overlap); 7800dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lock_lba_range_check_ranges); 7801dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lock_lba_range_with_io_outstanding); 7802dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, lock_lba_range_overlapped); 78039e386832SArtur Paszkiewicz CU_ADD_TEST(suite, bdev_quiesce); 78047cd20dd3SShuhei Matsumoto CU_ADD_TEST(suite, bdev_io_abort); 7805d0b4deabSChangpeng Liu CU_ADD_TEST(suite, bdev_unmap); 7806e7fbdf15SChangpeng Liu CU_ADD_TEST(suite, bdev_write_zeroes_split_test); 7807f420b9efSZiye Yang CU_ADD_TEST(suite, bdev_set_options_test); 7808c3a58489SAlexey Marchuk CU_ADD_TEST(suite, bdev_get_memory_domains); 7809442e13c0SJonas Pfefferle CU_ADD_TEST(suite, bdev_io_ext); 7810442e13c0SJonas Pfefferle CU_ADD_TEST(suite, bdev_io_ext_no_opts); 7811442e13c0SJonas Pfefferle CU_ADD_TEST(suite, bdev_io_ext_invalid_opts); 7812442e13c0SJonas Pfefferle CU_ADD_TEST(suite, bdev_io_ext_split); 7813442e13c0SJonas Pfefferle CU_ADD_TEST(suite, bdev_io_ext_bounce_buffer); 781479415753SKonrad Sztyber CU_ADD_TEST(suite, bdev_register_uuid_alias); 781596c007d3SShuhei Matsumoto CU_ADD_TEST(suite, bdev_unregister_by_name); 7816428b17a0SShuhei Matsumoto CU_ADD_TEST(suite, for_each_bdev_test); 78176defafc9SDamiano CU_ADD_TEST(suite, bdev_seek_test); 78186c8702acSEvgeniy Kochetov CU_ADD_TEST(suite, bdev_copy); 78196c8702acSEvgeniy Kochetov CU_ADD_TEST(suite, bdev_copy_split_test); 7820ae215731SMike Gerdts CU_ADD_TEST(suite, examine_locks); 7821a7eb6187SMike Gerdts CU_ADD_TEST(suite, claim_v2_rwo); 7822a7eb6187SMike Gerdts CU_ADD_TEST(suite, claim_v2_rom); 7823a7eb6187SMike Gerdts CU_ADD_TEST(suite, claim_v2_rwm); 7824a7eb6187SMike Gerdts CU_ADD_TEST(suite, claim_v2_existing_writer); 7825a7eb6187SMike Gerdts CU_ADD_TEST(suite, claim_v2_existing_v1); 7826a7eb6187SMike Gerdts CU_ADD_TEST(suite, claim_v1_existing_v2); 782786bbcdb8SMike Gerdts CU_ADD_TEST(suite, examine_claimed); 782802935561SEd Reed CU_ADD_TEST(suite, examine_claimed_manual); 7829fee788f6SJim Harris CU_ADD_TEST(suite, get_numa_id); 783063e0c25dSVasilii Ivanov CU_ADD_TEST(suite, get_device_stat_with_reset); 783116e5e505SShuhei Matsumoto CU_ADD_TEST(suite, open_ext_v2_test); 78320836dccdSShuhei Matsumoto CU_ADD_TEST(suite, bdev_io_init_dif_ctx_test); 78334ee51dcbSJim Harris 7834972b3ae3SShuhei Matsumoto allocate_cores(1); 7835270a25dfSBen Walker allocate_threads(1); 7836270a25dfSBen Walker set_thread(0); 7837270a25dfSBen Walker 7838ea941caeSKonrad Sztyber num_failures = spdk_ut_run_tests(argc, argv, NULL); 78394ee51dcbSJim Harris CU_cleanup_registry(); 7840270a25dfSBen Walker 7841270a25dfSBen Walker free_threads(); 7842972b3ae3SShuhei Matsumoto free_cores(); 7843270a25dfSBen Walker 78444ee51dcbSJim Harris return num_failures; 78454ee51dcbSJim Harris } 7846