1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk_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 bool g_append_with_md; 66 static int g_unexpected_iovcnt; 67 static void *g_md_buf; 68 static void *g_unexpected_md_buf; 69 static void *g_buf; 70 static void *g_unexpected_buf; 71 72 static int 73 test_setup(void) 74 { 75 /* Initiate expected and unexpected value here */ 76 g_expected_zone_id = 0x1000; 77 g_expected_num_zones = 1024; 78 g_unexpected_zone_id = 0xFFFF; 79 g_unexpected_num_zones = 0; 80 g_num_blocks = 4096 * 1024; 81 g_unexpected_num_blocks = 0; 82 g_start_lba = 4096; 83 g_unexpected_start_lba = 0; 84 g_bdev_blocklen = 4096; 85 g_unexpected_bdev_blocklen = 0; 86 g_append_with_md = false; 87 g_unexpected_iovcnt = 1000; 88 g_md_buf = (void *)0xEFDCFEDE; 89 g_unexpected_md_buf = (void *)0xFECDEFDC; 90 g_buf = (void *)0xFEEDBEEF; 91 g_unexpected_buf = (void *)0xDEADBEEF; 92 93 return 0; 94 } 95 96 static int 97 test_cleanup(void) 98 { 99 return 0; 100 } 101 102 static void 103 start_operation(void) 104 { 105 g_zone_op = calloc(1, sizeof(struct zone_io_operation)); 106 SPDK_CU_ASSERT_FATAL(g_zone_op != NULL); 107 108 switch (g_io_type) { 109 case SPDK_BDEV_IO_TYPE_ZONE_APPEND: 110 g_zone_op->bdev.iovs = &g_zone_op->iov; 111 g_zone_op->bdev.iovs[0].iov_base = g_unexpected_buf; 112 g_zone_op->bdev.iovs[0].iov_len = g_unexpected_num_blocks * g_unexpected_bdev_blocklen; 113 g_zone_op->bdev.iovcnt = g_unexpected_iovcnt; 114 g_zone_op->bdev.md_buf = g_unexpected_md_buf; 115 g_zone_op->bdev.num_blocks = g_unexpected_num_blocks; 116 g_zone_op->bdev.offset_blocks = g_unexpected_zone_id; 117 g_zone_op->bdev.start_lba = g_unexpected_start_lba; 118 break; 119 default: 120 g_zone_op->bdev.iovcnt = 0; 121 g_zone_op->zone_mgmt.zone_id = g_unexpected_zone_id; 122 g_zone_op->zone_mgmt.num_zones = g_unexpected_num_zones; 123 g_zone_op->zone_mgmt.zone_action = g_unexpected_zone_action; 124 g_zone_op->zone_mgmt.buf = g_unexpected_buf; 125 break; 126 } 127 } 128 129 static void 130 stop_operation(void) 131 { 132 free(g_bdev_io); 133 free(g_bdev); 134 free(g_zone_op); 135 g_bdev_io = NULL; 136 g_bdev = NULL; 137 g_zone_op = NULL; 138 } 139 140 struct spdk_bdev_io * 141 bdev_channel_get_io(struct spdk_bdev_channel *channel) 142 { 143 struct spdk_bdev_io *bdev_io; 144 145 bdev_io = calloc(1, sizeof(struct spdk_bdev_io)); 146 SPDK_CU_ASSERT_FATAL(bdev_io != NULL); 147 148 bdev_io->internal.ch = channel; 149 bdev_io->type = g_io_type; 150 151 CU_ASSERT(g_zone_op != NULL); 152 153 switch (g_io_type) { 154 case SPDK_BDEV_IO_TYPE_GET_ZONE_INFO: 155 case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT: 156 bdev_io->u.bdev.iovcnt = 0; 157 bdev_io->u.zone_mgmt.zone_id = g_zone_op->zone_mgmt.zone_id; 158 bdev_io->u.zone_mgmt.num_zones = g_zone_op->zone_mgmt.num_zones; 159 bdev_io->u.zone_mgmt.zone_action = g_zone_op->zone_mgmt.zone_action; 160 bdev_io->u.zone_mgmt.buf = g_zone_op->zone_mgmt.buf; 161 break; 162 case SPDK_BDEV_IO_TYPE_ZONE_APPEND: 163 bdev_io->u.bdev.iovs = g_zone_op->bdev.iovs; 164 bdev_io->u.bdev.iovs[0].iov_base = g_zone_op->bdev.iovs[0].iov_base; 165 bdev_io->u.bdev.iovs[0].iov_len = g_zone_op->bdev.iovs[0].iov_len; 166 bdev_io->u.bdev.iovcnt = g_zone_op->bdev.iovcnt; 167 bdev_io->u.bdev.md_buf = g_zone_op->bdev.md_buf; 168 bdev_io->u.bdev.num_blocks = g_zone_op->bdev.num_blocks; 169 bdev_io->u.bdev.offset_blocks = g_zone_op->bdev.offset_blocks; 170 break; 171 default: 172 CU_ASSERT(0); 173 } 174 175 g_bdev_io = bdev_io; 176 177 return bdev_io; 178 } 179 180 int 181 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb, 182 void *event_ctx, struct spdk_bdev_desc **_desc) 183 { 184 *_desc = (void *)0x1; 185 return 0; 186 } 187 188 struct spdk_io_channel * 189 spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc) 190 { 191 return (struct spdk_io_channel *)0x1; 192 } 193 194 void 195 spdk_put_io_channel(struct spdk_io_channel *ch) 196 { 197 CU_ASSERT(ch == (void *)1); 198 } 199 200 struct spdk_bdev * 201 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc) 202 { 203 struct spdk_bdev *bdev; 204 205 bdev = calloc(1, sizeof(struct spdk_bdev)); 206 SPDK_CU_ASSERT_FATAL(bdev != NULL); 207 208 if (g_io_type == SPDK_BDEV_IO_TYPE_ZONE_APPEND) { 209 bdev->blocklen = g_bdev_blocklen; 210 } 211 212 g_bdev = bdev; 213 214 return bdev; 215 } 216 217 static void 218 test_get_zone_size(void) 219 { 220 struct spdk_bdev bdev = {}; 221 uint64_t get_zone_size; 222 223 bdev.zone_size = 1024 * 4096; 224 225 get_zone_size = spdk_bdev_get_zone_size(&bdev); 226 CU_ASSERT(get_zone_size == 1024 * 4096); 227 } 228 229 static void 230 test_get_num_zones(void) 231 { 232 struct spdk_bdev bdev = {}; 233 uint64_t get_num_zones; 234 235 bdev.blockcnt = 1024 * 1024 * 1024; 236 bdev.zone_size = 1024 * 4096; 237 238 get_num_zones = spdk_bdev_get_num_zones(&bdev); 239 CU_ASSERT(get_num_zones == 256); 240 } 241 242 static void 243 test_get_zone_id(void) 244 { 245 struct spdk_bdev bdev = {}; 246 uint64_t get_zone_id; 247 248 bdev.blockcnt = 1024 * 1024 * 1024; 249 bdev.zone_size = 1024 * 4096; 250 251 get_zone_id = spdk_bdev_get_zone_id(&bdev, 0x800032); 252 CU_ASSERT(get_zone_id == 0x800000); 253 } 254 255 static void 256 test_get_max_zone_append_size(void) 257 { 258 struct spdk_bdev bdev = {}; 259 uint32_t get_max_zone_append_size; 260 261 bdev.max_zone_append_size = 32; 262 263 get_max_zone_append_size = spdk_bdev_get_max_zone_append_size(&bdev); 264 CU_ASSERT(get_max_zone_append_size == 32); 265 } 266 267 static void 268 test_get_max_open_zones(void) 269 { 270 struct spdk_bdev bdev = {}; 271 uint32_t get_max_open_zones; 272 273 bdev.max_open_zones = 8192; 274 275 get_max_open_zones = spdk_bdev_get_max_open_zones(&bdev); 276 CU_ASSERT(get_max_open_zones == 8192); 277 } 278 279 static void 280 test_get_max_active_zones(void) 281 { 282 struct spdk_bdev bdev = {}; 283 uint32_t get_max_active_zones; 284 285 bdev.max_active_zones = 9216; 286 287 get_max_active_zones = spdk_bdev_get_max_active_zones(&bdev); 288 CU_ASSERT(get_max_active_zones == 9216); 289 } 290 291 static void 292 test_get_optimal_open_zones(void) 293 { 294 struct spdk_bdev bdev = {}; 295 uint32_t get_optimal_open_zones; 296 297 bdev.optimal_open_zones = 4096; 298 299 get_optimal_open_zones = spdk_bdev_get_optimal_open_zones(&bdev); 300 CU_ASSERT(get_optimal_open_zones == 4096); 301 } 302 303 static void 304 test_bdev_io_get_append_location(void) 305 { 306 struct spdk_bdev_io bdev_io = {}; 307 uint64_t get_offset_blocks; 308 309 bdev_io.u.bdev.offset_blocks = 1024 * 10; 310 311 get_offset_blocks = spdk_bdev_io_get_append_location(&bdev_io); 312 CU_ASSERT(get_offset_blocks == 1024 * 10); 313 } 314 315 static void 316 test_zone_get_operation(void) 317 { 318 test_get_zone_size(); 319 test_get_num_zones(); 320 test_get_zone_id(); 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 static void 434 test_bdev_zone_appendv(void) 435 { 436 DECLARE_VIRTUAL_BDEV_START(); 437 438 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 439 g_append_with_md = true; 440 441 start_operation(); 442 443 rc = spdk_bdev_zone_appendv(desc, ch, g_zone_op->bdev.iovs, g_unexpected_iovcnt, g_start_lba, 444 g_num_blocks, NULL, NULL); 445 446 CU_ASSERT(rc == 0); 447 CU_ASSERT(g_bdev_io->internal.desc == desc); 448 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 449 CU_ASSERT(g_bdev_io->u.bdev.iovs == g_zone_op->bdev.iovs); 450 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == g_unexpected_iovcnt); 451 CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL); 452 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 453 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 454 455 stop_operation(); 456 } 457 458 int 459 main(int argc, char **argv) 460 { 461 CU_pSuite suite = NULL; 462 unsigned int num_failures; 463 464 CU_set_error_action(CUEA_ABORT); 465 CU_initialize_registry(); 466 467 suite = CU_add_suite("zone", test_setup, test_cleanup); 468 CU_ADD_TEST(suite, test_zone_get_operation); 469 CU_ADD_TEST(suite, test_bdev_zone_get_info); 470 CU_ADD_TEST(suite, test_bdev_zone_management); 471 CU_ADD_TEST(suite, test_bdev_zone_append); 472 CU_ADD_TEST(suite, test_bdev_zone_append_with_md); 473 CU_ADD_TEST(suite, test_bdev_zone_appendv); 474 CU_ADD_TEST(suite, test_bdev_io_get_append_location); 475 476 CU_basic_set_mode(CU_BRM_VERBOSE); 477 CU_basic_run_tests(); 478 num_failures = CU_get_number_of_failures(); 479 CU_cleanup_registry(); 480 return num_failures; 481 } 482