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