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