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