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 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 /* 35 * Common code for partition-like virtual bdevs. 36 */ 37 38 #include "spdk/bdev.h" 39 #include "spdk/log.h" 40 #include "spdk/string.h" 41 42 #include "spdk/bdev_module.h" 43 44 struct spdk_bdev_part_base { 45 struct spdk_bdev *bdev; 46 struct spdk_bdev_desc *desc; 47 uint32_t ref; 48 uint32_t channel_size; 49 spdk_bdev_part_base_free_fn base_free_fn; 50 void *ctx; 51 bool claimed; 52 struct spdk_bdev_module *module; 53 struct spdk_bdev_fn_table *fn_table; 54 struct bdev_part_tailq *tailq; 55 spdk_io_channel_create_cb ch_create_cb; 56 spdk_io_channel_destroy_cb ch_destroy_cb; 57 }; 58 59 struct spdk_bdev * 60 spdk_bdev_part_base_get_bdev(struct spdk_bdev_part_base *part_base) 61 { 62 return part_base->bdev; 63 } 64 65 struct spdk_bdev_desc * 66 spdk_bdev_part_base_get_desc(struct spdk_bdev_part_base *part_base) 67 { 68 return part_base->desc; 69 } 70 71 struct bdev_part_tailq * 72 spdk_bdev_part_base_get_tailq(struct spdk_bdev_part_base *part_base) 73 { 74 return part_base->tailq; 75 } 76 77 void * 78 spdk_bdev_part_base_get_ctx(struct spdk_bdev_part_base *part_base) 79 { 80 return part_base->ctx; 81 } 82 83 void 84 spdk_bdev_part_base_free(struct spdk_bdev_part_base *base) 85 { 86 if (base->desc) { 87 spdk_bdev_close(base->desc); 88 base->desc = NULL; 89 } 90 91 if (base->base_free_fn != NULL) { 92 base->base_free_fn(base->ctx); 93 } 94 95 free(base); 96 } 97 98 static void 99 spdk_bdev_part_free_cb(void *io_device) 100 { 101 struct spdk_bdev_part *part = io_device; 102 struct spdk_bdev_part_base *base; 103 104 assert(part); 105 assert(part->internal.base); 106 107 base = part->internal.base; 108 109 TAILQ_REMOVE(base->tailq, part, tailq); 110 111 if (__sync_sub_and_fetch(&base->ref, 1) == 0) { 112 spdk_bdev_module_release_bdev(base->bdev); 113 spdk_bdev_part_base_free(base); 114 } 115 116 spdk_bdev_destruct_done(&part->internal.bdev, 0); 117 free(part->internal.bdev.name); 118 free(part->internal.bdev.product_name); 119 free(part); 120 } 121 122 int 123 spdk_bdev_part_free(struct spdk_bdev_part *part) 124 { 125 spdk_io_device_unregister(part, spdk_bdev_part_free_cb); 126 127 /* Return 1 to indicate that this is an asynchronous operation that isn't complete 128 * until spdk_bdev_destruct_done is called */ 129 return 1; 130 } 131 132 void 133 spdk_bdev_part_base_hotremove(struct spdk_bdev_part_base *part_base, struct bdev_part_tailq *tailq) 134 { 135 struct spdk_bdev_part *part, *tmp; 136 137 TAILQ_FOREACH_SAFE(part, tailq, tailq, tmp) { 138 if (part->internal.base == part_base) { 139 spdk_bdev_unregister(&part->internal.bdev, NULL, NULL); 140 } 141 } 142 } 143 144 static bool 145 spdk_bdev_part_io_type_supported(void *_part, enum spdk_bdev_io_type io_type) 146 { 147 struct spdk_bdev_part *part = _part; 148 149 /* We can't decode/modify passthrough NVMe commands, so don't report 150 * that a partition supports these io types, even if the underlying 151 * bdev does. 152 */ 153 switch (io_type) { 154 case SPDK_BDEV_IO_TYPE_NVME_ADMIN: 155 case SPDK_BDEV_IO_TYPE_NVME_IO: 156 case SPDK_BDEV_IO_TYPE_NVME_IO_MD: 157 return false; 158 default: 159 break; 160 } 161 162 return part->internal.base->bdev->fn_table->io_type_supported(part->internal.base->bdev->ctxt, 163 io_type); 164 } 165 166 static struct spdk_io_channel * 167 spdk_bdev_part_get_io_channel(void *_part) 168 { 169 struct spdk_bdev_part *part = _part; 170 171 return spdk_get_io_channel(part); 172 } 173 174 struct spdk_bdev * 175 spdk_bdev_part_get_bdev(struct spdk_bdev_part *part) 176 { 177 return &part->internal.bdev; 178 } 179 180 struct spdk_bdev_part_base * 181 spdk_bdev_part_get_base(struct spdk_bdev_part *part) 182 { 183 return part->internal.base; 184 } 185 186 struct spdk_bdev * 187 spdk_bdev_part_get_base_bdev(struct spdk_bdev_part *part) 188 { 189 return part->internal.base->bdev; 190 } 191 192 uint64_t 193 spdk_bdev_part_get_offset_blocks(struct spdk_bdev_part *part) 194 { 195 return part->internal.offset_blocks; 196 } 197 198 static void 199 spdk_bdev_part_complete_io(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 200 { 201 struct spdk_bdev_io *part_io = cb_arg; 202 int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED; 203 204 spdk_bdev_io_complete(part_io, status); 205 spdk_bdev_free_io(bdev_io); 206 } 207 208 int 209 spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bdev_io *bdev_io) 210 { 211 struct spdk_bdev_part *part = ch->part; 212 struct spdk_io_channel *base_ch = ch->base_ch; 213 struct spdk_bdev_desc *base_desc = part->internal.base->desc; 214 uint64_t offset; 215 int rc = 0; 216 217 /* Modify the I/O to adjust for the offset within the base bdev. */ 218 switch (bdev_io->type) { 219 case SPDK_BDEV_IO_TYPE_READ: 220 offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; 221 if (bdev_io->u.bdev.md_buf == NULL) { 222 rc = spdk_bdev_readv_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs, 223 bdev_io->u.bdev.iovcnt, offset, 224 bdev_io->u.bdev.num_blocks, 225 spdk_bdev_part_complete_io, bdev_io); 226 } else { 227 rc = spdk_bdev_readv_blocks_with_md(base_desc, base_ch, 228 bdev_io->u.bdev.iovs, 229 bdev_io->u.bdev.iovcnt, 230 bdev_io->u.bdev.md_buf, offset, 231 bdev_io->u.bdev.num_blocks, 232 spdk_bdev_part_complete_io, bdev_io); 233 } 234 break; 235 case SPDK_BDEV_IO_TYPE_WRITE: 236 offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; 237 if (bdev_io->u.bdev.md_buf == NULL) { 238 rc = spdk_bdev_writev_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs, 239 bdev_io->u.bdev.iovcnt, offset, 240 bdev_io->u.bdev.num_blocks, 241 spdk_bdev_part_complete_io, bdev_io); 242 } else { 243 rc = spdk_bdev_writev_blocks_with_md(base_desc, base_ch, 244 bdev_io->u.bdev.iovs, 245 bdev_io->u.bdev.iovcnt, 246 bdev_io->u.bdev.md_buf, offset, 247 bdev_io->u.bdev.num_blocks, 248 spdk_bdev_part_complete_io, bdev_io); 249 } 250 break; 251 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 252 offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; 253 rc = spdk_bdev_write_zeroes_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks, 254 spdk_bdev_part_complete_io, bdev_io); 255 break; 256 case SPDK_BDEV_IO_TYPE_UNMAP: 257 offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; 258 rc = spdk_bdev_unmap_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks, 259 spdk_bdev_part_complete_io, bdev_io); 260 break; 261 case SPDK_BDEV_IO_TYPE_FLUSH: 262 offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; 263 rc = spdk_bdev_flush_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks, 264 spdk_bdev_part_complete_io, bdev_io); 265 break; 266 case SPDK_BDEV_IO_TYPE_RESET: 267 rc = spdk_bdev_reset(base_desc, base_ch, 268 spdk_bdev_part_complete_io, bdev_io); 269 break; 270 default: 271 SPDK_ERRLOG("unknown I/O type %d\n", bdev_io->type); 272 return SPDK_BDEV_IO_STATUS_FAILED; 273 } 274 275 return rc; 276 } 277 278 static int 279 spdk_bdev_part_channel_create_cb(void *io_device, void *ctx_buf) 280 { 281 struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device; 282 struct spdk_bdev_part_channel *ch = ctx_buf; 283 284 ch->part = part; 285 ch->base_ch = spdk_bdev_get_io_channel(part->internal.base->desc); 286 if (ch->base_ch == NULL) { 287 return -1; 288 } 289 290 if (part->internal.base->ch_create_cb) { 291 return part->internal.base->ch_create_cb(io_device, ctx_buf); 292 } else { 293 return 0; 294 } 295 } 296 297 static void 298 spdk_bdev_part_channel_destroy_cb(void *io_device, void *ctx_buf) 299 { 300 struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device; 301 struct spdk_bdev_part_channel *ch = ctx_buf; 302 303 if (part->internal.base->ch_destroy_cb) { 304 part->internal.base->ch_destroy_cb(io_device, ctx_buf); 305 } 306 spdk_put_io_channel(ch->base_ch); 307 } 308 309 struct spdk_bdev_part_base * 310 spdk_bdev_part_base_construct(struct spdk_bdev *bdev, 311 spdk_bdev_remove_cb_t remove_cb, struct spdk_bdev_module *module, 312 struct spdk_bdev_fn_table *fn_table, struct bdev_part_tailq *tailq, 313 spdk_bdev_part_base_free_fn free_fn, void *ctx, 314 uint32_t channel_size, spdk_io_channel_create_cb ch_create_cb, 315 spdk_io_channel_destroy_cb ch_destroy_cb) 316 { 317 int rc; 318 struct spdk_bdev_part_base *base; 319 320 base = calloc(1, sizeof(*base)); 321 if (!base) { 322 SPDK_ERRLOG("Memory allocation failure\n"); 323 return NULL; 324 } 325 fn_table->get_io_channel = spdk_bdev_part_get_io_channel; 326 fn_table->io_type_supported = spdk_bdev_part_io_type_supported; 327 328 base->bdev = bdev; 329 base->desc = NULL; 330 base->ref = 0; 331 base->module = module; 332 base->fn_table = fn_table; 333 base->tailq = tailq; 334 base->base_free_fn = free_fn; 335 base->ctx = ctx; 336 base->claimed = false; 337 base->channel_size = channel_size; 338 base->ch_create_cb = ch_create_cb; 339 base->ch_destroy_cb = ch_destroy_cb; 340 341 rc = spdk_bdev_open(bdev, false, remove_cb, base, &base->desc); 342 if (rc) { 343 spdk_bdev_part_base_free(base); 344 SPDK_ERRLOG("could not open bdev %s: %s\n", spdk_bdev_get_name(bdev), 345 spdk_strerror(-rc)); 346 return NULL; 347 } 348 349 return base; 350 } 351 352 int 353 spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base, 354 char *name, uint64_t offset_blocks, uint64_t num_blocks, 355 char *product_name) 356 { 357 part->internal.bdev.blocklen = base->bdev->blocklen; 358 part->internal.bdev.blockcnt = num_blocks; 359 part->internal.offset_blocks = offset_blocks; 360 361 part->internal.bdev.write_cache = base->bdev->write_cache; 362 part->internal.bdev.required_alignment = base->bdev->required_alignment; 363 part->internal.bdev.ctxt = part; 364 part->internal.bdev.module = base->module; 365 part->internal.bdev.fn_table = base->fn_table; 366 367 part->internal.bdev.md_interleave = base->bdev->md_interleave; 368 part->internal.bdev.md_len = base->bdev->md_len; 369 part->internal.bdev.dif_type = base->bdev->dif_type; 370 part->internal.bdev.dif_is_head_of_md = base->bdev->dif_is_head_of_md; 371 part->internal.bdev.dif_check_flags = base->bdev->dif_check_flags; 372 373 part->internal.bdev.name = strdup(name); 374 part->internal.bdev.product_name = strdup(product_name); 375 376 if (part->internal.bdev.name == NULL) { 377 SPDK_ERRLOG("Failed to allocate name for new part of bdev %s\n", spdk_bdev_get_name(base->bdev)); 378 return -1; 379 } else if (part->internal.bdev.product_name == NULL) { 380 free(part->internal.bdev.name); 381 SPDK_ERRLOG("Failed to allocate product name for new part of bdev %s\n", 382 spdk_bdev_get_name(base->bdev)); 383 return -1; 384 } 385 386 __sync_fetch_and_add(&base->ref, 1); 387 part->internal.base = base; 388 389 if (!base->claimed) { 390 int rc; 391 392 rc = spdk_bdev_module_claim_bdev(base->bdev, base->desc, base->module); 393 if (rc) { 394 SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(base->bdev)); 395 free(part->internal.bdev.name); 396 free(part->internal.bdev.product_name); 397 return -1; 398 } 399 base->claimed = true; 400 } 401 402 spdk_io_device_register(part, spdk_bdev_part_channel_create_cb, 403 spdk_bdev_part_channel_destroy_cb, 404 base->channel_size, 405 name); 406 407 spdk_bdev_register(&part->internal.bdev); 408 TAILQ_INSERT_TAIL(base->tailq, part, tailq); 409 410 return 0; 411 } 412