1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE AiRE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 #include "spdk_cunit.h" 36 #include "spdk/env.h" 37 #include "spdk_internal/mock.h" 38 39 #include "bdev/bdev_zone.c" 40 41 DEFINE_STUB_V(bdev_io_init, (struct spdk_bdev_io *bdev_io, 42 struct spdk_bdev *bdev, void *cb_arg, 43 spdk_bdev_io_completion_cb cb)); 44 45 DEFINE_STUB_V(bdev_io_submit, (struct spdk_bdev_io *bdev_io)); 46 47 /* Construct zone_io_operation structure */ 48 struct zone_io_operation { 49 struct spdk_bdev_desc *desc; 50 struct spdk_io_channel *ch; 51 struct iovec iov; 52 union { 53 struct { 54 uint64_t zone_id; 55 size_t num_zones; 56 enum spdk_bdev_zone_action zone_action; 57 void *buf; 58 struct spdk_bdev_zone_info *info_; 59 } zone_mgmt; 60 struct { 61 void *md_buf; 62 struct iovec *iovs; 63 int iovcnt; 64 uint64_t num_blocks; 65 uint64_t offset_blocks; 66 uint64_t start_lba; 67 } bdev; 68 }; 69 spdk_bdev_io_completion_cb cb; 70 void *cb_arg; 71 enum spdk_bdev_io_type io_type; 72 }; 73 74 /* Global variables */ 75 struct zone_io_operation *g_zone_op = NULL; 76 static struct spdk_bdev *g_bdev = NULL; 77 static struct spdk_bdev_io *g_bdev_io = NULL; 78 static struct spdk_bdev_zone_info g_zone_info = {0}; 79 static enum spdk_bdev_zone_action g_zone_action = SPDK_BDEV_ZONE_OPEN; 80 static enum spdk_bdev_zone_action g_unexpected_zone_action = SPDK_BDEV_ZONE_CLOSE; 81 static enum spdk_bdev_io_type g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO; 82 83 static uint64_t g_expected_zone_id; 84 static uint64_t g_expected_num_zones; 85 static uint64_t g_unexpected_zone_id; 86 static uint64_t g_unexpected_num_zones; 87 static uint64_t g_num_blocks; 88 static uint64_t g_unexpected_num_blocks; 89 static uint64_t g_start_lba; 90 static uint64_t g_unexpected_start_lba; 91 static uint64_t g_bdev_blocklen; 92 static uint64_t g_unexpected_bdev_blocklen; 93 static bool g_append_with_md; 94 static int g_unexpected_iovcnt; 95 static void *g_md_buf; 96 static void *g_unexpetced_md_buf; 97 static void *g_buf; 98 static void *g_unexpected_buf; 99 100 static int 101 test_setup(void) 102 { 103 /* Initiate expected and unexpected value here */ 104 g_expected_zone_id = 0x1000; 105 g_expected_num_zones = 1024; 106 g_unexpected_zone_id = 0xFFFF; 107 g_unexpected_num_zones = 0; 108 g_num_blocks = 4096 * 1024; 109 g_unexpected_num_blocks = 0; 110 g_start_lba = 4096; 111 g_unexpected_start_lba = 0; 112 g_bdev_blocklen = 4096; 113 g_unexpected_bdev_blocklen = 0; 114 g_append_with_md = false; 115 g_unexpected_iovcnt = 1000; 116 g_md_buf = (void *)0xEFDCFEDE; 117 g_unexpetced_md_buf = (void *)0xFECDEFDC; 118 g_buf = (void *)0xFEEDBEEF; 119 g_unexpected_buf = (void *)0xDEADBEEF; 120 121 return 0; 122 } 123 124 static int 125 test_cleanup(void) 126 { 127 return 0; 128 } 129 130 static void 131 start_operation(void) 132 { 133 g_zone_op = calloc(1, sizeof(struct zone_io_operation)); 134 SPDK_CU_ASSERT_FATAL(g_zone_op != NULL); 135 136 switch (g_io_type) { 137 case SPDK_BDEV_IO_TYPE_ZONE_APPEND: 138 g_zone_op->bdev.iovs = &g_zone_op->iov; 139 g_zone_op->bdev.iovs[0].iov_base = g_unexpected_buf; 140 g_zone_op->bdev.iovs[0].iov_len = g_unexpected_num_blocks * g_unexpected_bdev_blocklen; 141 g_zone_op->bdev.iovcnt = g_unexpected_iovcnt; 142 g_zone_op->bdev.md_buf = g_unexpetced_md_buf; 143 g_zone_op->bdev.num_blocks = g_unexpected_num_blocks; 144 g_zone_op->bdev.offset_blocks = g_unexpected_zone_id; 145 g_zone_op->bdev.start_lba = g_unexpected_start_lba; 146 break; 147 default: 148 g_zone_op->bdev.iovcnt = 0; 149 g_zone_op->zone_mgmt.zone_id = g_unexpected_zone_id; 150 g_zone_op->zone_mgmt.num_zones = g_unexpected_num_zones; 151 g_zone_op->zone_mgmt.zone_action = g_unexpected_zone_action; 152 g_zone_op->zone_mgmt.buf = g_unexpected_buf; 153 break; 154 } 155 } 156 157 static void 158 stop_operation(void) 159 { 160 free(g_bdev_io); 161 free(g_bdev); 162 free(g_zone_op); 163 g_bdev_io = NULL; 164 g_bdev = NULL; 165 g_zone_op = NULL; 166 } 167 168 struct spdk_bdev_io * 169 bdev_channel_get_io(struct spdk_bdev_channel *channel) 170 { 171 struct spdk_bdev_io *bdev_io; 172 173 bdev_io = calloc(1, sizeof(struct spdk_bdev_io)); 174 SPDK_CU_ASSERT_FATAL(bdev_io != NULL); 175 176 bdev_io->internal.ch = channel; 177 bdev_io->type = g_io_type; 178 179 CU_ASSERT(g_zone_op != NULL); 180 181 switch (g_io_type) { 182 case SPDK_BDEV_IO_TYPE_GET_ZONE_INFO: 183 case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT: 184 bdev_io->u.bdev.iovcnt = 0; 185 bdev_io->u.zone_mgmt.zone_id = g_zone_op->zone_mgmt.zone_id; 186 bdev_io->u.zone_mgmt.num_zones = g_zone_op->zone_mgmt.num_zones; 187 bdev_io->u.zone_mgmt.zone_action = g_zone_op->zone_mgmt.zone_action; 188 bdev_io->u.zone_mgmt.buf = g_zone_op->zone_mgmt.buf; 189 break; 190 case SPDK_BDEV_IO_TYPE_ZONE_APPEND: 191 bdev_io->u.bdev.iovs = g_zone_op->bdev.iovs; 192 bdev_io->u.bdev.iovs[0].iov_base = g_zone_op->bdev.iovs[0].iov_base; 193 bdev_io->u.bdev.iovs[0].iov_len = g_zone_op->bdev.iovs[0].iov_len; 194 bdev_io->u.bdev.iovcnt = g_zone_op->bdev.iovcnt; 195 bdev_io->u.bdev.md_buf = g_zone_op->bdev.md_buf; 196 bdev_io->u.bdev.num_blocks = g_zone_op->bdev.num_blocks; 197 bdev_io->u.bdev.offset_blocks = g_zone_op->bdev.offset_blocks; 198 break; 199 default: 200 CU_ASSERT(0); 201 } 202 203 g_bdev_io = bdev_io; 204 205 return bdev_io; 206 } 207 208 int 209 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb, 210 void *event_ctx, struct spdk_bdev_desc **_desc) 211 { 212 *_desc = (void *)0x1; 213 return 0; 214 } 215 216 struct spdk_io_channel * 217 spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc) 218 { 219 return (struct spdk_io_channel *)0x1; 220 } 221 222 void 223 spdk_put_io_channel(struct spdk_io_channel *ch) 224 { 225 CU_ASSERT(ch == (void *)1); 226 } 227 228 struct spdk_bdev * 229 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc) 230 { 231 struct spdk_bdev *bdev; 232 233 bdev = calloc(1, sizeof(struct spdk_bdev)); 234 SPDK_CU_ASSERT_FATAL(bdev != NULL); 235 236 if (g_io_type == SPDK_BDEV_IO_TYPE_ZONE_APPEND) { 237 bdev->blocklen = g_bdev_blocklen; 238 } 239 240 g_bdev = bdev; 241 242 return bdev; 243 } 244 245 static void 246 test_get_zone_size(void) 247 { 248 struct spdk_bdev bdev = {}; 249 uint64_t get_zone_size; 250 251 bdev.zone_size = 1024 * 4096; 252 253 get_zone_size = spdk_bdev_get_zone_size(&bdev); 254 CU_ASSERT(get_zone_size == 1024 * 4096); 255 } 256 257 static void 258 test_get_max_zone_append_size(void) 259 { 260 struct spdk_bdev bdev = {}; 261 uint32_t get_max_zone_append_size; 262 263 bdev.max_zone_append_size = 32; 264 265 get_max_zone_append_size = spdk_bdev_get_max_zone_append_size(&bdev); 266 CU_ASSERT(get_max_zone_append_size == 32); 267 } 268 269 static void 270 test_get_max_open_zones(void) 271 { 272 struct spdk_bdev bdev = {}; 273 uint32_t get_max_open_zones; 274 275 bdev.max_open_zones = 8192; 276 277 get_max_open_zones = spdk_bdev_get_max_open_zones(&bdev); 278 CU_ASSERT(get_max_open_zones == 8192); 279 } 280 281 static void 282 test_get_max_active_zones(void) 283 { 284 struct spdk_bdev bdev = {}; 285 uint32_t get_max_active_zones; 286 287 bdev.max_active_zones = 9216; 288 289 get_max_active_zones = spdk_bdev_get_max_active_zones(&bdev); 290 CU_ASSERT(get_max_active_zones == 9216); 291 } 292 293 static void 294 test_get_optimal_open_zones(void) 295 { 296 struct spdk_bdev bdev = {}; 297 uint32_t get_optimal_open_zones; 298 299 bdev.optimal_open_zones = 4096; 300 301 get_optimal_open_zones = spdk_bdev_get_optimal_open_zones(&bdev); 302 CU_ASSERT(get_optimal_open_zones == 4096); 303 } 304 305 static void 306 test_bdev_io_get_append_location(void) 307 { 308 struct spdk_bdev_io bdev_io = {}; 309 uint64_t get_offset_blocks; 310 311 bdev_io.u.bdev.offset_blocks = 1024 * 10; 312 313 get_offset_blocks = spdk_bdev_io_get_append_location(&bdev_io); 314 CU_ASSERT(get_offset_blocks == 1024 * 10); 315 } 316 317 static void 318 test_zone_get_operation(void) 319 { 320 test_get_zone_size(); 321 test_get_max_zone_append_size(); 322 test_get_max_open_zones(); 323 test_get_max_active_zones(); 324 test_get_optimal_open_zones(); 325 } 326 327 #define DECLARE_VIRTUAL_BDEV_START() \ 328 struct spdk_bdev bdev; \ 329 struct spdk_io_channel *ch; \ 330 struct spdk_bdev_desc *desc = NULL; \ 331 int rc; \ 332 memset(&bdev, 0, sizeof(bdev)); \ 333 bdev.name = "bdev_zone_ut"; \ 334 rc = spdk_bdev_open_ext(bdev.name, true, NULL, NULL, &desc); \ 335 CU_ASSERT(rc == 0); \ 336 SPDK_CU_ASSERT_FATAL(desc != NULL); \ 337 ch = spdk_bdev_get_io_channel(desc); \ 338 CU_ASSERT(ch != NULL);\ 339 340 static void 341 test_bdev_zone_get_info(void) 342 { 343 DECLARE_VIRTUAL_BDEV_START(); 344 345 g_zone_info.zone_id = g_expected_zone_id; 346 g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO; 347 348 start_operation(); 349 350 rc = spdk_bdev_get_zone_info(desc, ch, g_expected_zone_id, g_expected_num_zones, &g_zone_info, NULL, 351 NULL); 352 CU_ASSERT(rc == 0); 353 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_GET_ZONE_INFO); 354 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id); 355 CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == g_expected_num_zones); 356 CU_ASSERT(g_bdev_io->u.zone_mgmt.buf == &g_zone_info); 357 358 stop_operation(); 359 } 360 361 static void 362 test_bdev_zone_management(void) 363 { 364 DECLARE_VIRTUAL_BDEV_START(); 365 366 g_zone_info.zone_id = g_expected_zone_id; 367 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT; 368 369 start_operation(); 370 371 rc = spdk_bdev_zone_management(desc, ch, g_expected_zone_id, g_zone_action, NULL, 372 NULL); 373 CU_ASSERT(rc == 0); 374 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT); 375 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id); 376 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_action == g_zone_action); 377 CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == 1); 378 379 stop_operation(); 380 } 381 382 static void 383 test_bdev_zone_append(void) 384 { 385 DECLARE_VIRTUAL_BDEV_START(); 386 387 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 388 g_append_with_md = false; 389 390 start_operation(); 391 392 rc = spdk_bdev_zone_append(desc, ch, g_buf, g_start_lba, g_num_blocks, NULL, NULL); 393 394 CU_ASSERT(rc == 0); 395 CU_ASSERT(g_bdev_io->internal.desc == desc); 396 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 397 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf); 398 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen); 399 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1); 400 CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL); 401 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 402 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 403 404 stop_operation(); 405 } 406 407 static void 408 test_bdev_zone_append_with_md(void) 409 { 410 DECLARE_VIRTUAL_BDEV_START(); 411 412 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 413 g_append_with_md = true; 414 415 start_operation(); 416 417 rc = spdk_bdev_zone_append_with_md(desc, ch, g_buf, g_md_buf, g_start_lba, g_num_blocks, NULL, 418 NULL); 419 420 CU_ASSERT(rc == 0); 421 CU_ASSERT(g_bdev_io->internal.desc == desc); 422 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 423 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf); 424 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen); 425 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1); 426 CU_ASSERT(g_bdev_io->u.bdev.md_buf == g_md_buf); 427 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 428 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 429 430 stop_operation(); 431 } 432 433 int 434 main(int argc, char **argv) 435 { 436 CU_pSuite suite = NULL; 437 unsigned int num_failures; 438 439 CU_set_error_action(CUEA_ABORT); 440 CU_initialize_registry(); 441 442 suite = CU_add_suite("zone", test_setup, test_cleanup); 443 CU_ADD_TEST(suite, test_zone_get_operation); 444 CU_ADD_TEST(suite, test_bdev_zone_get_info); 445 CU_ADD_TEST(suite, test_bdev_zone_management); 446 CU_ADD_TEST(suite, test_bdev_zone_append); 447 CU_ADD_TEST(suite, test_bdev_zone_append_with_md); 448 CU_ADD_TEST(suite, test_bdev_io_get_append_location); 449 450 CU_basic_set_mode(CU_BRM_VERBOSE); 451 CU_basic_run_tests(); 452 num_failures = CU_get_number_of_failures(); 453 CU_cleanup_registry(); 454 return num_failures; 455 } 456