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 #include "spdk/stdinc.h" 35 36 #include "spdk/blob_bdev.h" 37 #include "spdk/blob.h" 38 #include "spdk/thread.h" 39 #include "spdk/log.h" 40 #include "spdk/endian.h" 41 #include "spdk/bdev_module.h" 42 43 struct blob_bdev { 44 struct spdk_bs_dev bs_dev; 45 struct spdk_bdev *bdev; 46 struct spdk_bdev_desc *desc; 47 bool claimed; 48 }; 49 50 struct blob_resubmit { 51 struct spdk_bdev_io_wait_entry bdev_io_wait; 52 enum spdk_bdev_io_type io_type; 53 struct spdk_bs_dev *dev; 54 struct spdk_io_channel *channel; 55 void *payload; 56 int iovcnt; 57 uint64_t lba; 58 uint32_t lba_count; 59 struct spdk_bs_dev_cb_args *cb_args; 60 }; 61 static void bdev_blob_resubmit(void *); 62 63 static inline struct spdk_bdev_desc * 64 __get_desc(struct spdk_bs_dev *dev) 65 { 66 return ((struct blob_bdev *)dev)->desc; 67 } 68 69 static inline struct spdk_bdev * 70 __get_bdev(struct spdk_bs_dev *dev) 71 { 72 return ((struct blob_bdev *)dev)->bdev; 73 } 74 75 static void 76 bdev_blob_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg) 77 { 78 struct spdk_bs_dev_cb_args *cb_args = arg; 79 int bserrno; 80 81 if (success) { 82 bserrno = 0; 83 } else { 84 bserrno = -EIO; 85 } 86 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno); 87 spdk_bdev_free_io(bdev_io); 88 } 89 90 static void 91 bdev_blob_queue_io(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, 92 int iovcnt, 93 uint64_t lba, uint32_t lba_count, enum spdk_bdev_io_type io_type, 94 struct spdk_bs_dev_cb_args *cb_args) 95 { 96 int rc; 97 struct spdk_bdev *bdev = __get_bdev(dev); 98 struct blob_resubmit *ctx; 99 100 ctx = calloc(1, sizeof(struct blob_resubmit)); 101 102 if (ctx == NULL) { 103 SPDK_ERRLOG("Not enough memory to queue io\n"); 104 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -ENOMEM); 105 return; 106 } 107 108 ctx->io_type = io_type; 109 ctx->dev = dev; 110 ctx->channel = channel; 111 ctx->payload = payload; 112 ctx->iovcnt = iovcnt; 113 ctx->lba = lba; 114 ctx->lba_count = lba_count; 115 ctx->cb_args = cb_args; 116 ctx->bdev_io_wait.bdev = bdev; 117 ctx->bdev_io_wait.cb_fn = bdev_blob_resubmit; 118 ctx->bdev_io_wait.cb_arg = ctx; 119 120 rc = spdk_bdev_queue_io_wait(bdev, channel, &ctx->bdev_io_wait); 121 if (rc != 0) { 122 SPDK_ERRLOG("Queue io failed, rc=%d\n", rc); 123 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); 124 free(ctx); 125 assert(false); 126 } 127 } 128 129 static void 130 bdev_blob_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, 131 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 132 { 133 int rc; 134 135 rc = spdk_bdev_read_blocks(__get_desc(dev), channel, payload, lba, 136 lba_count, bdev_blob_io_complete, cb_args); 137 if (rc == -ENOMEM) { 138 bdev_blob_queue_io(dev, channel, payload, 0, lba, 139 lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args); 140 } else if (rc != 0) { 141 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); 142 } 143 } 144 145 static void 146 bdev_blob_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, 147 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 148 { 149 int rc; 150 151 rc = spdk_bdev_write_blocks(__get_desc(dev), channel, payload, lba, 152 lba_count, bdev_blob_io_complete, cb_args); 153 if (rc == -ENOMEM) { 154 bdev_blob_queue_io(dev, channel, payload, 0, lba, 155 lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args); 156 } else if (rc != 0) { 157 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); 158 } 159 } 160 161 static void 162 bdev_blob_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 163 struct iovec *iov, int iovcnt, 164 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 165 { 166 int rc; 167 168 rc = spdk_bdev_readv_blocks(__get_desc(dev), channel, iov, iovcnt, lba, 169 lba_count, bdev_blob_io_complete, cb_args); 170 if (rc == -ENOMEM) { 171 bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 172 lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args); 173 } else if (rc != 0) { 174 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); 175 } 176 } 177 178 static void 179 bdev_blob_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 180 struct iovec *iov, int iovcnt, 181 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 182 { 183 int rc; 184 185 rc = spdk_bdev_writev_blocks(__get_desc(dev), channel, iov, iovcnt, lba, 186 lba_count, bdev_blob_io_complete, cb_args); 187 if (rc == -ENOMEM) { 188 bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 189 lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args); 190 } else if (rc != 0) { 191 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); 192 } 193 } 194 195 static void 196 bdev_blob_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba, 197 uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 198 { 199 int rc; 200 201 rc = spdk_bdev_write_zeroes_blocks(__get_desc(dev), channel, lba, 202 lba_count, bdev_blob_io_complete, cb_args); 203 if (rc == -ENOMEM) { 204 bdev_blob_queue_io(dev, channel, NULL, 0, lba, 205 lba_count, SPDK_BDEV_IO_TYPE_WRITE_ZEROES, cb_args); 206 } else if (rc != 0) { 207 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); 208 } 209 } 210 211 static void 212 bdev_blob_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba, 213 uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 214 { 215 struct blob_bdev *blob_bdev = (struct blob_bdev *)dev; 216 int rc; 217 218 if (spdk_bdev_io_type_supported(blob_bdev->bdev, SPDK_BDEV_IO_TYPE_UNMAP)) { 219 rc = spdk_bdev_unmap_blocks(__get_desc(dev), channel, lba, lba_count, 220 bdev_blob_io_complete, cb_args); 221 if (rc == -ENOMEM) { 222 bdev_blob_queue_io(dev, channel, NULL, 0, lba, 223 lba_count, SPDK_BDEV_IO_TYPE_UNMAP, cb_args); 224 } else if (rc != 0) { 225 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); 226 } 227 } else { 228 /* 229 * If the device doesn't support unmap, immediately complete 230 * the request. Blobstore does not rely on unmap zeroing 231 * data. 232 */ 233 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0); 234 } 235 } 236 237 static void 238 bdev_blob_resubmit(void *arg) 239 { 240 struct blob_resubmit *ctx = (struct blob_resubmit *) arg; 241 242 switch (ctx->io_type) { 243 case SPDK_BDEV_IO_TYPE_READ: 244 if (ctx->iovcnt > 0) { 245 bdev_blob_readv(ctx->dev, ctx->channel, (struct iovec *)ctx->payload, ctx->iovcnt, 246 ctx->lba, ctx->lba_count, ctx->cb_args); 247 } else { 248 bdev_blob_read(ctx->dev, ctx->channel, ctx->payload, 249 ctx->lba, ctx->lba_count, ctx->cb_args); 250 } 251 break; 252 case SPDK_BDEV_IO_TYPE_WRITE: 253 if (ctx->iovcnt > 0) { 254 bdev_blob_writev(ctx->dev, ctx->channel, (struct iovec *)ctx->payload, ctx->iovcnt, 255 ctx->lba, ctx->lba_count, ctx->cb_args); 256 } else { 257 bdev_blob_write(ctx->dev, ctx->channel, ctx->payload, 258 ctx->lba, ctx->lba_count, ctx->cb_args); 259 } 260 break; 261 case SPDK_BDEV_IO_TYPE_UNMAP: 262 bdev_blob_unmap(ctx->dev, ctx->channel, 263 ctx->lba, ctx->lba_count, ctx->cb_args); 264 break; 265 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 266 bdev_blob_write_zeroes(ctx->dev, ctx->channel, 267 ctx->lba, ctx->lba_count, ctx->cb_args); 268 break; 269 default: 270 SPDK_ERRLOG("Unsupported io type %d\n", ctx->io_type); 271 assert(false); 272 break; 273 } 274 free(ctx); 275 } 276 277 int 278 spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module *module) 279 { 280 struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev; 281 int rc; 282 283 rc = spdk_bdev_module_claim_bdev(blob_bdev->bdev, NULL, module); 284 if (rc != 0) { 285 SPDK_ERRLOG("could not claim bs dev\n"); 286 return rc; 287 } 288 289 blob_bdev->claimed = true; 290 291 return rc; 292 } 293 294 static struct spdk_io_channel * 295 bdev_blob_create_channel(struct spdk_bs_dev *dev) 296 { 297 struct blob_bdev *blob_bdev = (struct blob_bdev *)dev; 298 299 return spdk_bdev_get_io_channel(blob_bdev->desc); 300 } 301 302 static void 303 bdev_blob_destroy_channel(struct spdk_bs_dev *dev, struct spdk_io_channel *channel) 304 { 305 spdk_put_io_channel(channel); 306 } 307 308 static void 309 bdev_blob_destroy(struct spdk_bs_dev *bs_dev) 310 { 311 struct spdk_bdev_desc *desc = __get_desc(bs_dev); 312 struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev; 313 314 if (blob_bdev->claimed) { 315 spdk_bdev_module_release_bdev(blob_bdev->bdev); 316 } 317 318 spdk_bdev_close(desc); 319 free(bs_dev); 320 } 321 322 struct spdk_bs_dev * 323 spdk_bdev_create_bs_dev(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb, void *remove_ctx) 324 { 325 struct blob_bdev *b; 326 struct spdk_bdev_desc *desc; 327 int rc; 328 329 b = calloc(1, sizeof(*b)); 330 331 if (b == NULL) { 332 SPDK_ERRLOG("could not allocate blob_bdev\n"); 333 return NULL; 334 } 335 336 rc = spdk_bdev_open(bdev, true, remove_cb, remove_ctx, &desc); 337 if (rc != 0) { 338 free(b); 339 return NULL; 340 } 341 342 b->bdev = bdev; 343 b->desc = desc; 344 b->bs_dev.blockcnt = spdk_bdev_get_num_blocks(bdev); 345 b->bs_dev.blocklen = spdk_bdev_get_block_size(bdev); 346 b->bs_dev.create_channel = bdev_blob_create_channel; 347 b->bs_dev.destroy_channel = bdev_blob_destroy_channel; 348 b->bs_dev.destroy = bdev_blob_destroy; 349 b->bs_dev.read = bdev_blob_read; 350 b->bs_dev.write = bdev_blob_write; 351 b->bs_dev.readv = bdev_blob_readv; 352 b->bs_dev.writev = bdev_blob_writev; 353 b->bs_dev.write_zeroes = bdev_blob_write_zeroes; 354 b->bs_dev.unmap = bdev_blob_unmap; 355 356 return &b->bs_dev; 357 } 358 359 struct spdk_bs_dev * 360 spdk_bdev_create_bs_dev_from_desc(struct spdk_bdev_desc *desc) 361 { 362 struct blob_bdev *b; 363 struct spdk_bdev *bdev; 364 365 b = calloc(1, sizeof(*b)); 366 367 if (b == NULL) { 368 SPDK_ERRLOG("could not allocate blob_bdev\n"); 369 return NULL; 370 } 371 372 bdev = spdk_bdev_desc_get_bdev(desc); 373 assert(bdev != NULL); 374 375 b->bdev = bdev; 376 b->desc = desc; 377 b->bs_dev.blockcnt = spdk_bdev_get_num_blocks(bdev); 378 b->bs_dev.blocklen = spdk_bdev_get_block_size(bdev); 379 b->bs_dev.create_channel = bdev_blob_create_channel; 380 b->bs_dev.destroy_channel = bdev_blob_destroy_channel; 381 b->bs_dev.destroy = bdev_blob_destroy; 382 b->bs_dev.read = bdev_blob_read; 383 b->bs_dev.write = bdev_blob_write; 384 b->bs_dev.readv = bdev_blob_readv; 385 b->bs_dev.writev = bdev_blob_writev; 386 b->bs_dev.write_zeroes = bdev_blob_write_zeroes; 387 b->bs_dev.unmap = bdev_blob_unmap; 388 389 return &b->bs_dev; 390 } 391