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_unexpected_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_unexpected_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_unexpected_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_num_zones(void) 259 { 260 struct spdk_bdev bdev = {}; 261 uint64_t get_num_zones; 262 263 bdev.blockcnt = 1024 * 1024 * 1024; 264 bdev.zone_size = 1024 * 4096; 265 266 get_num_zones = spdk_bdev_get_num_zones(&bdev); 267 CU_ASSERT(get_num_zones == 256); 268 } 269 270 static void 271 test_get_zone_id(void) 272 { 273 struct spdk_bdev bdev = {}; 274 uint64_t get_zone_id; 275 276 bdev.blockcnt = 1024 * 1024 * 1024; 277 bdev.zone_size = 1024 * 4096; 278 279 get_zone_id = spdk_bdev_get_zone_id(&bdev, 0x800032); 280 CU_ASSERT(get_zone_id == 0x800000); 281 } 282 283 static void 284 test_get_max_zone_append_size(void) 285 { 286 struct spdk_bdev bdev = {}; 287 uint32_t get_max_zone_append_size; 288 289 bdev.max_zone_append_size = 32; 290 291 get_max_zone_append_size = spdk_bdev_get_max_zone_append_size(&bdev); 292 CU_ASSERT(get_max_zone_append_size == 32); 293 } 294 295 static void 296 test_get_max_open_zones(void) 297 { 298 struct spdk_bdev bdev = {}; 299 uint32_t get_max_open_zones; 300 301 bdev.max_open_zones = 8192; 302 303 get_max_open_zones = spdk_bdev_get_max_open_zones(&bdev); 304 CU_ASSERT(get_max_open_zones == 8192); 305 } 306 307 static void 308 test_get_max_active_zones(void) 309 { 310 struct spdk_bdev bdev = {}; 311 uint32_t get_max_active_zones; 312 313 bdev.max_active_zones = 9216; 314 315 get_max_active_zones = spdk_bdev_get_max_active_zones(&bdev); 316 CU_ASSERT(get_max_active_zones == 9216); 317 } 318 319 static void 320 test_get_optimal_open_zones(void) 321 { 322 struct spdk_bdev bdev = {}; 323 uint32_t get_optimal_open_zones; 324 325 bdev.optimal_open_zones = 4096; 326 327 get_optimal_open_zones = spdk_bdev_get_optimal_open_zones(&bdev); 328 CU_ASSERT(get_optimal_open_zones == 4096); 329 } 330 331 static void 332 test_bdev_io_get_append_location(void) 333 { 334 struct spdk_bdev_io bdev_io = {}; 335 uint64_t get_offset_blocks; 336 337 bdev_io.u.bdev.offset_blocks = 1024 * 10; 338 339 get_offset_blocks = spdk_bdev_io_get_append_location(&bdev_io); 340 CU_ASSERT(get_offset_blocks == 1024 * 10); 341 } 342 343 static void 344 test_zone_get_operation(void) 345 { 346 test_get_zone_size(); 347 test_get_num_zones(); 348 test_get_zone_id(); 349 test_get_max_zone_append_size(); 350 test_get_max_open_zones(); 351 test_get_max_active_zones(); 352 test_get_optimal_open_zones(); 353 } 354 355 #define DECLARE_VIRTUAL_BDEV_START() \ 356 struct spdk_bdev bdev; \ 357 struct spdk_io_channel *ch; \ 358 struct spdk_bdev_desc *desc = NULL; \ 359 int rc; \ 360 memset(&bdev, 0, sizeof(bdev)); \ 361 bdev.name = "bdev_zone_ut"; \ 362 rc = spdk_bdev_open_ext(bdev.name, true, NULL, NULL, &desc); \ 363 CU_ASSERT(rc == 0); \ 364 SPDK_CU_ASSERT_FATAL(desc != NULL); \ 365 ch = spdk_bdev_get_io_channel(desc); \ 366 CU_ASSERT(ch != NULL);\ 367 368 static void 369 test_bdev_zone_get_info(void) 370 { 371 DECLARE_VIRTUAL_BDEV_START(); 372 373 g_zone_info.zone_id = g_expected_zone_id; 374 g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO; 375 376 start_operation(); 377 378 rc = spdk_bdev_get_zone_info(desc, ch, g_expected_zone_id, g_expected_num_zones, &g_zone_info, NULL, 379 NULL); 380 CU_ASSERT(rc == 0); 381 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_GET_ZONE_INFO); 382 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id); 383 CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == g_expected_num_zones); 384 CU_ASSERT(g_bdev_io->u.zone_mgmt.buf == &g_zone_info); 385 386 stop_operation(); 387 } 388 389 static void 390 test_bdev_zone_management(void) 391 { 392 DECLARE_VIRTUAL_BDEV_START(); 393 394 g_zone_info.zone_id = g_expected_zone_id; 395 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT; 396 397 start_operation(); 398 399 rc = spdk_bdev_zone_management(desc, ch, g_expected_zone_id, g_zone_action, NULL, 400 NULL); 401 CU_ASSERT(rc == 0); 402 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT); 403 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id); 404 CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_action == g_zone_action); 405 CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == 1); 406 407 stop_operation(); 408 } 409 410 static void 411 test_bdev_zone_append(void) 412 { 413 DECLARE_VIRTUAL_BDEV_START(); 414 415 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 416 g_append_with_md = false; 417 418 start_operation(); 419 420 rc = spdk_bdev_zone_append(desc, ch, g_buf, g_start_lba, g_num_blocks, NULL, NULL); 421 422 CU_ASSERT(rc == 0); 423 CU_ASSERT(g_bdev_io->internal.desc == desc); 424 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 425 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf); 426 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen); 427 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1); 428 CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL); 429 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 430 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 431 432 stop_operation(); 433 } 434 435 static void 436 test_bdev_zone_append_with_md(void) 437 { 438 DECLARE_VIRTUAL_BDEV_START(); 439 440 g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND; 441 g_append_with_md = true; 442 443 start_operation(); 444 445 rc = spdk_bdev_zone_append_with_md(desc, ch, g_buf, g_md_buf, g_start_lba, g_num_blocks, NULL, 446 NULL); 447 448 CU_ASSERT(rc == 0); 449 CU_ASSERT(g_bdev_io->internal.desc == desc); 450 CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND); 451 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf); 452 CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen); 453 CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1); 454 CU_ASSERT(g_bdev_io->u.bdev.md_buf == g_md_buf); 455 CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks); 456 CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id); 457 458 stop_operation(); 459 } 460 461 int 462 main(int argc, char **argv) 463 { 464 CU_pSuite suite = NULL; 465 unsigned int num_failures; 466 467 CU_set_error_action(CUEA_ABORT); 468 CU_initialize_registry(); 469 470 suite = CU_add_suite("zone", test_setup, test_cleanup); 471 CU_ADD_TEST(suite, test_zone_get_operation); 472 CU_ADD_TEST(suite, test_bdev_zone_get_info); 473 CU_ADD_TEST(suite, test_bdev_zone_management); 474 CU_ADD_TEST(suite, test_bdev_zone_append); 475 CU_ADD_TEST(suite, test_bdev_zone_append_with_md); 476 CU_ADD_TEST(suite, test_bdev_io_get_append_location); 477 478 CU_basic_set_mode(CU_BRM_VERBOSE); 479 CU_basic_run_tests(); 480 num_failures = CU_get_number_of_failures(); 481 CU_cleanup_registry(); 482 return num_failures; 483 } 484