1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2019 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk_internal/cunit.h" 8 #include "spdk/env.h" 9 #include "spdk_internal/mock.h" 10 11 #include "bdev/bdev_zone.c" 12 13 DEFINE_STUB_V(bdev_io_init, (struct spdk_bdev_io *bdev_io, 14 struct spdk_bdev *bdev, void *cb_arg, 15 spdk_bdev_io_completion_cb cb)); 16 17 DEFINE_STUB_V(bdev_io_submit, (struct spdk_bdev_io *bdev_io)); 18 19 /* Construct zone_io_operation structure */ 20 struct zone_io_operation { 21 struct spdk_bdev_desc *desc; 22 struct spdk_io_channel *ch; 23 struct iovec iov; 24 union { 25 struct { 26 uint64_t zone_id; 27 size_t num_zones; 28 enum spdk_bdev_zone_action zone_action; 29 void *buf; 30 struct spdk_bdev_zone_info *info_; 31 } zone_mgmt; 32 struct { 33 void *md_buf; 34 struct iovec *iovs; 35 int iovcnt; 36 uint64_t num_blocks; 37 uint64_t offset_blocks; 38 uint64_t start_lba; 39 } bdev; 40 }; 41 spdk_bdev_io_completion_cb cb; 42 void *cb_arg; 43 enum spdk_bdev_io_type io_type; 44 }; 45 46 /* Global variables */ 47 struct zone_io_operation *g_zone_op = NULL; 48 static struct spdk_bdev *g_bdev = NULL; 49 static struct spdk_bdev_io *g_bdev_io = NULL; 50 static struct spdk_bdev_zone_info g_zone_info = {0}; 51 static enum spdk_bdev_zone_action g_zone_action = SPDK_BDEV_ZONE_OPEN; 52 static enum spdk_bdev_zone_action g_unexpected_zone_action = SPDK_BDEV_ZONE_CLOSE; 53 static enum spdk_bdev_io_type g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO; 54 55 static uint64_t g_expected_zone_id; 56 static uint64_t g_expected_num_zones; 57 static uint64_t g_unexpected_zone_id; 58 static uint64_t g_unexpected_num_zones; 59 static uint64_t g_num_blocks; 60 static uint64_t g_unexpected_num_blocks; 61 static uint64_t g_start_lba; 62 static uint64_t g_unexpected_start_lba; 63 static uint64_t g_bdev_blocklen; 64 static uint64_t g_unexpected_bdev_blocklen; 65 static int g_unexpected_iovcnt; 66 static void *g_md_buf; 67 static void *g_unexpected_md_buf; 68 static void *g_buf; 69 static void *g_unexpected_buf; 70 71 static int 72 test_setup(void) 73 { 74 /* Initiate expected and unexpected value here */ 75 g_expected_zone_id = 0x1000; 76 g_expected_num_zones = 1024; 77 g_unexpected_zone_id = 0xFFFF; 78 g_unexpected_num_zones = 0; 79 g_num_blocks = 4096 * 1024; 80 g_unexpected_num_blocks = 0; 81 g_start_lba = 4096; 82 g_unexpected_start_lba = 0; 83 g_bdev_blocklen = 4096; 84 g_unexpected_bdev_blocklen = 0; 85 g_unexpected_iovcnt = 1000; 86 g_md_buf = (void *)0xEFDCFEDE; 87 g_unexpected_md_buf = (void *)0xFECDEFDC; 88 g_buf = (void *)0xFEEDBEEF; 89 g_unexpected_buf = (void *)0xDEADBEEF; 90 91 return 0; 92 } 93 94 static int 95 test_cleanup(void) 96 { 97 return 0; 98 } 99 100 static void 101 start_operation(void) 102 { 103 g_zone_op = calloc(1, sizeof(struct zone_io_operation)); 104 SPDK_CU_ASSERT_FATAL(g_zone_op != NULL); 105 106 switch (g_io_type) { 107 case SPDK_BDEV_IO_TYPE_ZONE_APPEND: 108 g_zone_op->bdev.iovs = &g_zone_op->iov; 109 g_zone_op->bdev.iovs[0].iov_base = g_unexpected_buf; 110 g_zone_op->bdev.iovs[0].iov_len = g_unexpected_num_blocks * g_unexpected_bdev_blocklen; 111 g_zone_op->bdev.iovcnt = g_unexpected_iovcnt; 112 g_zone_op->bdev.md_buf = g_unexpected_md_buf; 113 g_zone_op->bdev.num_blocks = g_unexpected_num_blocks; 114 g_zone_op->bdev.offset_blocks = g_unexpected_zone_id; 115 g_zone_op->bdev.start_lba = g_unexpected_start_lba; 116 break; 117 default: 118 g_zone_op->bdev.iovcnt = 0; 119 g_zone_op->zone_mgmt.zone_id = g_unexpected_zone_id; 120 g_zone_op->zone_mgmt.num_zones = g_unexpected_num_zones; 121 g_zone_op->zone_mgmt.zone_action = g_unexpected_zone_action; 122 g_zone_op->zone_mgmt.buf = g_unexpected_buf; 123 break; 124 } 125 } 126 127 static void 128 stop_operation(void) 129 { 130 free(g_bdev_io); 131 free(g_bdev); 132 free(g_zone_op); 133 g_bdev_io = NULL; 134 g_bdev = NULL; 135 g_zone_op = NULL; 136 } 137 138 struct spdk_bdev_io * 139 bdev_channel_get_io(struct spdk_bdev_channel *channel) 140 { 141 struct spdk_bdev_io *bdev_io; 142 143 bdev_io = calloc(1, sizeof(struct spdk_bdev_io)); 144 SPDK_CU_ASSERT_FATAL(bdev_io != NULL); 145 146 bdev_io->internal.ch = channel; 147 bdev_io->type = g_io_type; 148 149 CU_ASSERT(g_zone_op != NULL); 150 151 switch (g_io_type) { 152 case SPDK_BDEV_IO_TYPE_GET_ZONE_INFO: 153 case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT: 154 bdev_io->u.bdev.iovcnt = 0; 155 bdev_io->u.zone_mgmt.zone_id = g_zone_op->zone_mgmt.zone_id; 156 bdev_io->u.zone_mgmt.num_zones = g_zone_op->zone_mgmt.num_zones; 157 bdev_io->u.zone_mgmt.zone_action = g_zone_op->zone_mgmt.zone_action; 158 bdev_io->u.zone_mgmt.buf = g_zone_op->zone_mgmt.buf; 159 break; 160 case SPDK_BDEV_IO_TYPE_ZONE_APPEND: 161 bdev_io->u.bdev.iovs = g_zone_op->bdev.iovs; 162 bdev_io->u.bdev.iovs[0].iov_base = g_zone_op->bdev.iovs[0].iov_base; 163 bdev_io->u.bdev.iovs[0].iov_len = g_zone_op->bdev.iovs[0].iov_len; 164 bdev_io->u.bdev.iovcnt = g_zone_op->bdev.iovcnt; 165 bdev_io->u.bdev.md_buf = g_zone_op->bdev.md_buf; 166 bdev_io->u.bdev.num_blocks = g_zone_op->bdev.num_blocks; 167 bdev_io->u.bdev.offset_blocks = g_zone_op->bdev.offset_blocks; 168 break; 169 default: 170 CU_ASSERT(0); 171 } 172 173 g_bdev_io = bdev_io; 174 175 return bdev_io; 176 } 177 178 int 179 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb, 180 void *event_ctx, struct spdk_bdev_desc **_desc) 181 { 182 *_desc = (void *)0x1; 183 return 0; 184 } 185 186 struct spdk_io_channel * 187 spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc) 188 { 189 return (struct spdk_io_channel *)0x1; 190 } 191 192 void 193 spdk_put_io_channel(struct spdk_io_channel *ch) 194 { 195 CU_ASSERT(ch == (void *)1); 196 } 197 198 struct spdk_bdev * 199 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc) 200 { 201 struct spdk_bdev *bdev; 202 203 bdev = calloc(1, sizeof(struct spdk_bdev)); 204 SPDK_CU_ASSERT_FATAL(bdev != NULL); 205 206 if (g_io_type == SPDK_BDEV_IO_TYPE_ZONE_APPEND) { 207 bdev->blocklen = g_bdev_blocklen; 208 } 209 210 g_bdev = bdev; 211 212 return bdev; 213 } 214 215 static void 216 test_get_zone_size(void) 217 { 218 struct spdk_bdev bdev = {}; 219 uint64_t get_zone_size; 220 221 bdev.zone_size = 1024 * 4096; 222 223 get_zone_size = spdk_bdev_get_zone_size(&bdev); 224 CU_ASSERT(get_zone_size == 1024 * 4096); 225 } 226 227 static void 228 test_get_num_zones(void) 229 { 230 struct spdk_bdev bdev = {}; 231 uint64_t get_num_zones; 232 233 bdev.blockcnt = 1024 * 1024 * 1024; 234 bdev.zone_size = 1024 * 4096; 235 236 get_num_zones = spdk_bdev_get_num_zones(&bdev); 237 CU_ASSERT(get_num_zones == 256); 238 } 239 240 static void 241 test_get_zone_id(void) 242 { 243 struct spdk_bdev bdev = {}; 244 uint64_t get_zone_id; 245 246 bdev.blockcnt = 1024 * 1024 * 1024; 247 bdev.zone_size = 1024 * 4096; 248 249 get_zone_id = spdk_bdev_get_zone_id(&bdev, 0x800032); 250 CU_ASSERT(get_zone_id == 0x800000); 251 } 252 253 static void 254 test_get_max_zone_append_size(void) 255 { 256 struct spdk_bdev bdev = {}; 257 uint32_t get_max_zone_append_size; 258 259 bdev.max_zone_append_size = 32; 260 261 get_max_zone_append_size = spdk_bdev_get_max_zone_append_size(&bdev); 262 CU_ASSERT(get_max_zone_append_size == 32); 263 } 264 265 static void 266 test_get_max_open_zones(void) 267 { 268 struct spdk_bdev bdev = {}; 269 uint32_t get_max_open_zones; 270 271 bdev.max_open_zones = 8192; 272 273 get_max_open_zones = spdk_bdev_get_max_open_zones(&bdev); 274 CU_ASSERT(get_max_open_zones == 8192); 275 } 276 277 static void 278 test_get_max_active_zones(void) 279 { 280 struct spdk_bdev bdev = {}; 281 uint32_t get_max_active_zones; 282 283 bdev.max_active_zones = 9216; 284 285 get_max_active_zones = spdk_bdev_get_max_active_zones(&bdev); 286 CU_ASSERT(get_max_active_zones == 9216); 287 } 288 289 static void 290 test_get_optimal_open_zones(void) 291 { 292 struct spdk_bdev bdev = {}; 293 uint32_t get_optimal_open_zones; 294 295 bdev.optimal_open_zones = 4096; 296 297 get_optimal_open_zones = spdk_bdev_get_optimal_open_zones(&bdev); 298 CU_ASSERT(get_optimal_open_zones == 4096); 299 } 300 301 static void 302 test_bdev_io_get_append_location(void) 303 { 304 struct spdk_bdev_io bdev_io = {}; 305 uint64_t get_offset_blocks; 306 307 bdev_io.u.bdev.offset_blocks = 1024 * 10; 308 309 get_offset_blocks = spdk_bdev_io_get_append_location(&bdev_io); 310 CU_ASSERT(get_offset_blocks == 1024 * 10); 311 } 312 313 static void 314 test_zone_get_operation(void) 315 { 316 test_get_zone_size(); 317 test_get_num_zones(); 318 test_get_zone_id(); 319 test_get_max_zone_append_size(); 320 test_get_max_open_zones(); 321 test_get_max_active_zones(); 322 test_get_optimal_open_zones(); 323 } 324 325 #define DECLARE_VIRTUAL_BDEV_START() \ 326 struct spdk_bdev bdev; \ 327 struct spdk_io_channel *ch; \ 328 struct spdk_bdev_desc *desc = NULL; \ 329 int rc; \ 330 memset(&bdev, 0, sizeof(bdev)); \ 331 bdev.name = "bdev_zone_ut"; \ 332 rc = spdk_bdev_open_ext(bdev.name, true, NULL, NULL, &desc); \ 333 CU_ASSERT(rc == 0); \ 334 SPDK_CU_ASSERT_FATAL(desc != NULL); \ 335 ch = spdk_bdev_get_io_channel(desc); \ 336 CU_ASSERT(ch != NULL);\ 337 338 static void 339 test_bdev_zone_get_info(void) 340 { 341 DECLARE_VIRTUAL_BDEV_START(); 342 343 g_zone_info.zone_id = g_expected_zone_id; 344 g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO; 345 346 start_operation(); 347 348 rc = spdk_bdev_get_zone_info(desc, ch, g_expected_zone_id, g_expected_num_zones, &g_zone_info, NULL, 349 NULL); 350 CU_ASSERT(rc == 0); 351 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_GET_ZONE_INFO); 352 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id); 353 CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == g_expected_num_zones); 354 CU_ASSERT(g_bdev_io->u.zone_mgmt.buf == &g_zone_info); 355 356 stop_operation(); 357 } 358 359 static void 360 test_bdev_zone_management(void) 361 { 362 DECLARE_VIRTUAL_BDEV_START(); 363 364 g_zone_info.zone_id = g_expected_zone_id; 365 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT; 366 367 start_operation(); 368 369 rc = spdk_bdev_zone_management(desc, ch, g_expected_zone_id, g_zone_action, NULL, 370 NULL); 371 CU_ASSERT(rc == 0); 372 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT); 373 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id); 374 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_action == g_zone_action); 375 CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == 1); 376 377 stop_operation(); 378 } 379 380 static void 381 test_bdev_zone_append(void) 382 { 383 DECLARE_VIRTUAL_BDEV_START(); 384 385 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 386 387 start_operation(); 388 389 rc = spdk_bdev_zone_append(desc, ch, g_buf, g_start_lba, g_num_blocks, NULL, NULL); 390 391 CU_ASSERT(rc == 0); 392 CU_ASSERT(g_bdev_io->internal.desc == desc); 393 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 394 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf); 395 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen); 396 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1); 397 CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL); 398 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 399 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 400 401 stop_operation(); 402 } 403 404 static void 405 test_bdev_zone_append_with_md(void) 406 { 407 DECLARE_VIRTUAL_BDEV_START(); 408 409 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 410 411 start_operation(); 412 413 rc = spdk_bdev_zone_append_with_md(desc, ch, g_buf, g_md_buf, g_start_lba, g_num_blocks, NULL, 414 NULL); 415 416 CU_ASSERT(rc == 0); 417 CU_ASSERT(g_bdev_io->internal.desc == desc); 418 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 419 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf); 420 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen); 421 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1); 422 CU_ASSERT(g_bdev_io->u.bdev.md_buf == g_md_buf); 423 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 424 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 425 426 stop_operation(); 427 } 428 429 static void 430 test_bdev_zone_appendv(void) 431 { 432 DECLARE_VIRTUAL_BDEV_START(); 433 434 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 435 436 start_operation(); 437 438 rc = spdk_bdev_zone_appendv(desc, ch, g_zone_op->bdev.iovs, g_unexpected_iovcnt, g_start_lba, 439 g_num_blocks, NULL, NULL); 440 441 CU_ASSERT(rc == 0); 442 CU_ASSERT(g_bdev_io->internal.desc == desc); 443 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 444 CU_ASSERT(g_bdev_io->u.bdev.iovs == g_zone_op->bdev.iovs); 445 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == g_unexpected_iovcnt); 446 CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL); 447 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 448 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 449 450 stop_operation(); 451 } 452 453 static void 454 test_bdev_zone_appendv_with_md(void) 455 { 456 DECLARE_VIRTUAL_BDEV_START(); 457 458 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 459 460 start_operation(); 461 462 rc = spdk_bdev_zone_appendv_with_md(desc, ch, g_zone_op->bdev.iovs, g_unexpected_iovcnt, g_md_buf, 463 g_start_lba, g_num_blocks, NULL, NULL); 464 465 CU_ASSERT(rc == 0); 466 CU_ASSERT(g_bdev_io->internal.desc == desc); 467 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 468 CU_ASSERT(g_bdev_io->u.bdev.iovs == g_zone_op->bdev.iovs); 469 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == g_unexpected_iovcnt); 470 CU_ASSERT(g_bdev_io->u.bdev.md_buf == g_md_buf); 471 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 472 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 473 474 stop_operation(); 475 } 476 477 int 478 main(int argc, char **argv) 479 { 480 CU_pSuite suite = NULL; 481 unsigned int num_failures; 482 483 CU_initialize_registry(); 484 485 suite = CU_add_suite("zone", test_setup, test_cleanup); 486 CU_ADD_TEST(suite, test_zone_get_operation); 487 CU_ADD_TEST(suite, test_bdev_zone_get_info); 488 CU_ADD_TEST(suite, test_bdev_zone_management); 489 CU_ADD_TEST(suite, test_bdev_zone_append); 490 CU_ADD_TEST(suite, test_bdev_zone_append_with_md); 491 CU_ADD_TEST(suite, test_bdev_zone_appendv); 492 CU_ADD_TEST(suite, test_bdev_zone_appendv_with_md); 493 CU_ADD_TEST(suite, test_bdev_io_get_append_location); 494 495 num_failures = spdk_ut_run_tests(argc, argv, NULL); 496 CU_cleanup_registry(); 497 return num_failures; 498 } 499