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