1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019 Mellanox Technologies LTD. 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 ARE 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 36 #include "spdk/bdev.h" 37 #include "spdk/env.h" 38 #include "spdk/thread.h" 39 #include "spdk/json.h" 40 #include "spdk/string.h" 41 #include "spdk/likely.h" 42 43 #include "spdk/bdev_module.h" 44 #include "spdk/log.h" 45 46 #include "bdev_null.h" 47 48 struct null_bdev { 49 struct spdk_bdev bdev; 50 TAILQ_ENTRY(null_bdev) tailq; 51 }; 52 53 struct null_io_channel { 54 struct spdk_poller *poller; 55 TAILQ_HEAD(, spdk_bdev_io) io; 56 }; 57 58 static TAILQ_HEAD(, null_bdev) g_null_bdev_head = TAILQ_HEAD_INITIALIZER(g_null_bdev_head); 59 static void *g_null_read_buf; 60 61 static int bdev_null_initialize(void); 62 static void bdev_null_finish(void); 63 64 static struct spdk_bdev_module null_if = { 65 .name = "null", 66 .module_init = bdev_null_initialize, 67 .module_fini = bdev_null_finish, 68 .async_fini = true, 69 }; 70 71 SPDK_BDEV_MODULE_REGISTER(null, &null_if) 72 73 static int 74 bdev_null_destruct(void *ctx) 75 { 76 struct null_bdev *bdev = ctx; 77 78 TAILQ_REMOVE(&g_null_bdev_head, bdev, tailq); 79 free(bdev->bdev.name); 80 free(bdev); 81 82 return 0; 83 } 84 85 static bool 86 bdev_null_abort_io(struct null_io_channel *ch, struct spdk_bdev_io *bio_to_abort) 87 { 88 struct spdk_bdev_io *bdev_io; 89 90 TAILQ_FOREACH(bdev_io, &ch->io, module_link) { 91 if (bdev_io == bio_to_abort) { 92 TAILQ_REMOVE(&ch->io, bio_to_abort, module_link); 93 spdk_bdev_io_complete(bio_to_abort, SPDK_BDEV_IO_STATUS_ABORTED); 94 return true; 95 } 96 } 97 98 return false; 99 } 100 101 static void 102 bdev_null_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 103 { 104 struct null_io_channel *ch = spdk_io_channel_get_ctx(_ch); 105 struct spdk_bdev *bdev = bdev_io->bdev; 106 struct spdk_dif_ctx dif_ctx; 107 struct spdk_dif_error err_blk; 108 int rc; 109 110 if (SPDK_DIF_DISABLE != bdev->dif_type && 111 (SPDK_BDEV_IO_TYPE_READ == bdev_io->type || 112 SPDK_BDEV_IO_TYPE_WRITE == bdev_io->type)) { 113 rc = spdk_dif_ctx_init(&dif_ctx, 114 bdev->blocklen, 115 bdev->md_len, 116 bdev->md_interleave, 117 bdev->dif_is_head_of_md, 118 bdev->dif_type, 119 bdev->dif_check_flags, 120 bdev_io->u.bdev.offset_blocks & 0xFFFFFFFF, 121 0xFFFF, 0, 0, 0); 122 if (0 != rc) { 123 SPDK_ERRLOG("Failed to initialize DIF context, error %d\n", rc); 124 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 125 return; 126 } 127 } 128 129 switch (bdev_io->type) { 130 case SPDK_BDEV_IO_TYPE_READ: 131 if (bdev_io->u.bdev.iovs[0].iov_base == NULL) { 132 assert(bdev_io->u.bdev.iovcnt == 1); 133 if (spdk_likely(bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen <= 134 SPDK_BDEV_LARGE_BUF_MAX_SIZE)) { 135 bdev_io->u.bdev.iovs[0].iov_base = g_null_read_buf; 136 bdev_io->u.bdev.iovs[0].iov_len = bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen; 137 } else { 138 SPDK_ERRLOG("Overflow occurred. Read I/O size %" PRIu64 " was larger than permitted %d\n", 139 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen, 140 SPDK_BDEV_LARGE_BUF_MAX_SIZE); 141 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 142 return; 143 } 144 } 145 if (SPDK_DIF_DISABLE != bdev->dif_type) { 146 rc = spdk_dif_generate(bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, 147 bdev_io->u.bdev.num_blocks, &dif_ctx); 148 if (0 != rc) { 149 SPDK_ERRLOG("IO DIF generation failed: lba %" PRIu64 ", num_block %" PRIu64 "\n", 150 bdev_io->u.bdev.offset_blocks, 151 bdev_io->u.bdev.num_blocks); 152 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 153 return; 154 } 155 } 156 TAILQ_INSERT_TAIL(&ch->io, bdev_io, module_link); 157 break; 158 case SPDK_BDEV_IO_TYPE_WRITE: 159 if (SPDK_DIF_DISABLE != bdev->dif_type) { 160 rc = spdk_dif_verify(bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, 161 bdev_io->u.bdev.num_blocks, &dif_ctx, &err_blk); 162 if (0 != rc) { 163 SPDK_ERRLOG("IO DIF verification failed: lba %" PRIu64 ", num_blocks %" PRIu64 ", " 164 "err_type %u, expected %u, actual %u, err_offset %u\n", 165 bdev_io->u.bdev.offset_blocks, 166 bdev_io->u.bdev.num_blocks, 167 err_blk.err_type, 168 err_blk.expected, 169 err_blk.actual, 170 err_blk.err_offset); 171 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 172 return; 173 } 174 } 175 TAILQ_INSERT_TAIL(&ch->io, bdev_io, module_link); 176 break; 177 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 178 case SPDK_BDEV_IO_TYPE_RESET: 179 TAILQ_INSERT_TAIL(&ch->io, bdev_io, module_link); 180 break; 181 case SPDK_BDEV_IO_TYPE_ABORT: 182 if (bdev_null_abort_io(ch, bdev_io->u.abort.bio_to_abort)) { 183 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 184 } else { 185 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 186 } 187 break; 188 case SPDK_BDEV_IO_TYPE_FLUSH: 189 case SPDK_BDEV_IO_TYPE_UNMAP: 190 default: 191 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 192 break; 193 } 194 } 195 196 static bool 197 bdev_null_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) 198 { 199 switch (io_type) { 200 case SPDK_BDEV_IO_TYPE_READ: 201 case SPDK_BDEV_IO_TYPE_WRITE: 202 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 203 case SPDK_BDEV_IO_TYPE_RESET: 204 case SPDK_BDEV_IO_TYPE_ABORT: 205 return true; 206 case SPDK_BDEV_IO_TYPE_FLUSH: 207 case SPDK_BDEV_IO_TYPE_UNMAP: 208 default: 209 return false; 210 } 211 } 212 213 static struct spdk_io_channel * 214 bdev_null_get_io_channel(void *ctx) 215 { 216 return spdk_get_io_channel(&g_null_bdev_head); 217 } 218 219 static void 220 bdev_null_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 221 { 222 char uuid_str[SPDK_UUID_STRING_LEN]; 223 224 spdk_json_write_object_begin(w); 225 226 spdk_json_write_named_string(w, "method", "bdev_null_create"); 227 228 spdk_json_write_named_object_begin(w, "params"); 229 spdk_json_write_named_string(w, "name", bdev->name); 230 spdk_json_write_named_uint64(w, "num_blocks", bdev->blockcnt); 231 spdk_json_write_named_uint32(w, "block_size", bdev->blocklen); 232 spdk_json_write_named_uint32(w, "md_size", bdev->md_len); 233 spdk_json_write_named_uint32(w, "dif_type", bdev->dif_type); 234 spdk_json_write_named_bool(w, "dif_is_head_of_md", bdev->dif_is_head_of_md); 235 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); 236 spdk_json_write_named_string(w, "uuid", uuid_str); 237 spdk_json_write_object_end(w); 238 239 spdk_json_write_object_end(w); 240 } 241 242 static const struct spdk_bdev_fn_table null_fn_table = { 243 .destruct = bdev_null_destruct, 244 .submit_request = bdev_null_submit_request, 245 .io_type_supported = bdev_null_io_type_supported, 246 .get_io_channel = bdev_null_get_io_channel, 247 .write_config_json = bdev_null_write_config_json, 248 }; 249 250 int 251 bdev_null_create(struct spdk_bdev **bdev, const struct spdk_null_bdev_opts *opts) 252 { 253 struct null_bdev *null_disk; 254 uint32_t data_block_size; 255 int rc; 256 257 if (!opts) { 258 SPDK_ERRLOG("No options provided for Null bdev.\n"); 259 return -EINVAL; 260 } 261 262 if (opts->md_interleave) { 263 if (opts->block_size < opts->md_size) { 264 SPDK_ERRLOG("Interleaved metadata size can not be greater than block size.\n"); 265 return -EINVAL; 266 } 267 data_block_size = opts->block_size - opts->md_size; 268 } else { 269 if (opts->md_size != 0) { 270 SPDK_ERRLOG("Metadata in separate buffer is not supported\n"); 271 return -ENOTSUP; 272 } 273 data_block_size = opts->block_size; 274 } 275 276 if (data_block_size % 512 != 0) { 277 SPDK_ERRLOG("Data block size %u is not a multiple of 512.\n", opts->block_size); 278 return -EINVAL; 279 } 280 281 if (opts->num_blocks == 0) { 282 SPDK_ERRLOG("Disk must be more than 0 blocks\n"); 283 return -EINVAL; 284 } 285 286 null_disk = calloc(1, sizeof(*null_disk)); 287 if (!null_disk) { 288 SPDK_ERRLOG("could not allocate null_bdev\n"); 289 return -ENOMEM; 290 } 291 292 null_disk->bdev.name = strdup(opts->name); 293 if (!null_disk->bdev.name) { 294 free(null_disk); 295 return -ENOMEM; 296 } 297 null_disk->bdev.product_name = "Null disk"; 298 299 null_disk->bdev.write_cache = 0; 300 null_disk->bdev.blocklen = opts->block_size; 301 null_disk->bdev.blockcnt = opts->num_blocks; 302 null_disk->bdev.md_len = opts->md_size; 303 null_disk->bdev.md_interleave = opts->md_interleave; 304 null_disk->bdev.dif_type = opts->dif_type; 305 null_disk->bdev.dif_is_head_of_md = opts->dif_is_head_of_md; 306 /* Current block device layer API does not propagate 307 * any DIF related information from user. So, we can 308 * not generate or verify Application Tag. 309 */ 310 switch (opts->dif_type) { 311 case SPDK_DIF_TYPE1: 312 case SPDK_DIF_TYPE2: 313 null_disk->bdev.dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | 314 SPDK_DIF_FLAGS_REFTAG_CHECK; 315 break; 316 case SPDK_DIF_TYPE3: 317 null_disk->bdev.dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK; 318 break; 319 case SPDK_DIF_DISABLE: 320 break; 321 } 322 if (opts->uuid) { 323 null_disk->bdev.uuid = *opts->uuid; 324 } else { 325 spdk_uuid_generate(&null_disk->bdev.uuid); 326 } 327 328 null_disk->bdev.ctxt = null_disk; 329 null_disk->bdev.fn_table = &null_fn_table; 330 null_disk->bdev.module = &null_if; 331 332 rc = spdk_bdev_register(&null_disk->bdev); 333 if (rc) { 334 free(null_disk->bdev.name); 335 free(null_disk); 336 return rc; 337 } 338 339 *bdev = &(null_disk->bdev); 340 341 TAILQ_INSERT_TAIL(&g_null_bdev_head, null_disk, tailq); 342 343 return rc; 344 } 345 346 void 347 bdev_null_delete(const char *bdev_name, spdk_delete_null_complete cb_fn, void *cb_arg) 348 { 349 int rc; 350 351 rc = spdk_bdev_unregister_by_name(bdev_name, &null_if, cb_fn, cb_arg); 352 if (rc != 0) { 353 cb_fn(cb_arg, rc); 354 } 355 } 356 357 static int 358 null_io_poll(void *arg) 359 { 360 struct null_io_channel *ch = arg; 361 TAILQ_HEAD(, spdk_bdev_io) io; 362 struct spdk_bdev_io *bdev_io; 363 364 TAILQ_INIT(&io); 365 TAILQ_SWAP(&ch->io, &io, spdk_bdev_io, module_link); 366 367 if (TAILQ_EMPTY(&io)) { 368 return SPDK_POLLER_IDLE; 369 } 370 371 while (!TAILQ_EMPTY(&io)) { 372 bdev_io = TAILQ_FIRST(&io); 373 TAILQ_REMOVE(&io, bdev_io, module_link); 374 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 375 } 376 377 return SPDK_POLLER_BUSY; 378 } 379 380 static int 381 null_bdev_create_cb(void *io_device, void *ctx_buf) 382 { 383 struct null_io_channel *ch = ctx_buf; 384 385 TAILQ_INIT(&ch->io); 386 ch->poller = SPDK_POLLER_REGISTER(null_io_poll, ch, 0); 387 388 return 0; 389 } 390 391 static void 392 null_bdev_destroy_cb(void *io_device, void *ctx_buf) 393 { 394 struct null_io_channel *ch = ctx_buf; 395 396 spdk_poller_unregister(&ch->poller); 397 } 398 399 static int 400 bdev_null_initialize(void) 401 { 402 /* 403 * This will be used if upper layer expects us to allocate the read buffer. 404 * Instead of using a real rbuf from the bdev pool, just always point to 405 * this same zeroed buffer. 406 */ 407 g_null_read_buf = spdk_zmalloc(SPDK_BDEV_LARGE_BUF_MAX_SIZE, 0, NULL, 408 SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA); 409 if (g_null_read_buf == NULL) { 410 return -1; 411 } 412 413 /* 414 * We need to pick some unique address as our "io device" - so just use the 415 * address of the global tailq. 416 */ 417 spdk_io_device_register(&g_null_bdev_head, null_bdev_create_cb, null_bdev_destroy_cb, 418 sizeof(struct null_io_channel), "null_bdev"); 419 420 return 0; 421 } 422 423 static void 424 dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx) 425 { 426 } 427 428 int 429 bdev_null_resize(const char *bdev_name, const uint64_t new_size_in_mb) 430 { 431 struct spdk_bdev_desc *desc; 432 struct spdk_bdev *bdev; 433 uint64_t current_size_in_mb; 434 uint64_t new_size_in_byte; 435 int rc = 0; 436 437 rc = spdk_bdev_open_ext(bdev_name, false, dummy_bdev_event_cb, NULL, &desc); 438 if (rc != 0) { 439 SPDK_ERRLOG("failed to open bdev; %s.\n", bdev_name); 440 return rc; 441 } 442 443 bdev = spdk_bdev_desc_get_bdev(desc); 444 445 if (bdev->module != &null_if) { 446 rc = -EINVAL; 447 goto exit; 448 } 449 450 current_size_in_mb = bdev->blocklen * bdev->blockcnt / (1024 * 1024); 451 if (new_size_in_mb < current_size_in_mb) { 452 SPDK_ERRLOG("The new bdev size must not be smaller than current bdev size.\n"); 453 rc = -EINVAL; 454 goto exit; 455 } 456 457 new_size_in_byte = new_size_in_mb * 1024 * 1024; 458 459 rc = spdk_bdev_notify_blockcnt_change(bdev, new_size_in_byte / bdev->blocklen); 460 if (rc != 0) { 461 SPDK_ERRLOG("failed to notify block cnt change.\n"); 462 } 463 464 exit: 465 spdk_bdev_close(desc); 466 return rc; 467 } 468 469 static void 470 _bdev_null_finish_cb(void *arg) 471 { 472 spdk_free(g_null_read_buf); 473 spdk_bdev_module_fini_done(); 474 } 475 476 static void 477 bdev_null_finish(void) 478 { 479 if (g_null_read_buf == NULL) { 480 spdk_bdev_module_fini_done(); 481 return; 482 } 483 spdk_io_device_unregister(&g_null_bdev_head, _bdev_null_finish_cb); 484 } 485 486 SPDK_LOG_REGISTER_COMPONENT(bdev_null) 487