diff --git a/lib/blob/bdev/blob_bdev.c b/lib/blob/bdev/blob_bdev.c index c42ed70df..42293142d 100644 --- a/lib/blob/bdev/blob_bdev.c +++ b/lib/blob/bdev/blob_bdev.c @@ -47,12 +47,31 @@ struct blob_bdev { bool claimed; }; +struct blob_resubmit { + struct spdk_bdev_io_wait_entry bdev_io_wait; + enum spdk_bdev_io_type io_type; + struct spdk_bs_dev *dev; + struct spdk_io_channel *channel; + void *payload; + int iovcnt; + uint64_t lba; + uint32_t lba_count; + struct spdk_bs_dev_cb_args *cb_args; +}; +static void bdev_blob_resubmit(void *); + static inline struct spdk_bdev_desc * __get_desc(struct spdk_bs_dev *dev) { return ((struct blob_bdev *)dev)->desc; } +static inline struct spdk_bdev * +__get_bdev(struct spdk_bs_dev *dev) +{ + return ((struct blob_bdev *)dev)->bdev; +} + static void bdev_blob_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg) { @@ -68,6 +87,45 @@ bdev_blob_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg) spdk_bdev_free_io(bdev_io); } +static void +bdev_blob_queue_io(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, + int iovcnt, + uint64_t lba, uint32_t lba_count, enum spdk_bdev_io_type io_type, + struct spdk_bs_dev_cb_args *cb_args) +{ + int rc; + struct spdk_bdev *bdev = __get_bdev(dev); + struct blob_resubmit *ctx; + + ctx = calloc(1, sizeof(struct blob_resubmit)); + + if (ctx == NULL) { + SPDK_ERRLOG("Not enough memory to queue io\n"); + cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -ENOMEM); + return; + } + + ctx->io_type = io_type; + ctx->dev = dev; + ctx->channel = channel; + ctx->payload = payload; + ctx->iovcnt = iovcnt; + ctx->lba = lba; + ctx->lba_count = lba_count; + ctx->cb_args = cb_args; + ctx->bdev_io_wait.bdev = bdev; + ctx->bdev_io_wait.cb_fn = bdev_blob_resubmit; + ctx->bdev_io_wait.cb_arg = ctx; + + rc = spdk_bdev_queue_io_wait(bdev, channel, &ctx->bdev_io_wait); + if (rc != 0) { + SPDK_ERRLOG("Queue io failed, rc=%d\n", rc); + cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); + free(ctx); + assert(false); + } +} + static void bdev_blob_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) @@ -76,7 +134,10 @@ bdev_blob_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *p rc = spdk_bdev_read_blocks(__get_desc(dev), channel, payload, lba, lba_count, bdev_blob_io_complete, cb_args); - if (rc) { + if (rc == -ENOMEM) { + bdev_blob_queue_io(dev, channel, payload, 0, lba, + lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args); + } else if (rc != 0) { cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); } } @@ -89,12 +150,14 @@ bdev_blob_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void * rc = spdk_bdev_write_blocks(__get_desc(dev), channel, payload, lba, lba_count, bdev_blob_io_complete, cb_args); - if (rc) { + if (rc == -ENOMEM) { + bdev_blob_queue_io(dev, channel, payload, 0, lba, + lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args); + } else if (rc != 0) { cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); } } - static void bdev_blob_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, struct iovec *iov, int iovcnt, @@ -104,7 +167,10 @@ bdev_blob_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, rc = spdk_bdev_readv_blocks(__get_desc(dev), channel, iov, iovcnt, lba, lba_count, bdev_blob_io_complete, cb_args); - if (rc) { + if (rc == -ENOMEM) { + bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, + lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args); + } else if (rc != 0) { cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); } } @@ -118,7 +184,10 @@ bdev_blob_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, rc = spdk_bdev_writev_blocks(__get_desc(dev), channel, iov, iovcnt, lba, lba_count, bdev_blob_io_complete, cb_args); - if (rc) { + if (rc == -ENOMEM) { + bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, + lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args); + } else if (rc != 0) { cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); } } @@ -131,7 +200,10 @@ bdev_blob_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, rc = spdk_bdev_write_zeroes_blocks(__get_desc(dev), channel, lba, lba_count, bdev_blob_io_complete, cb_args); - if (rc) { + if (rc == -ENOMEM) { + bdev_blob_queue_io(dev, channel, NULL, 0, lba, + lba_count, SPDK_BDEV_IO_TYPE_WRITE_ZEROES, cb_args); + } else if (rc != 0) { cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); } } @@ -146,7 +218,10 @@ bdev_blob_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64 if (spdk_bdev_io_type_supported(blob_bdev->bdev, SPDK_BDEV_IO_TYPE_UNMAP)) { rc = spdk_bdev_unmap_blocks(__get_desc(dev), channel, lba, lba_count, bdev_blob_io_complete, cb_args); - if (rc) { + if (rc == -ENOMEM) { + bdev_blob_queue_io(dev, channel, NULL, 0, lba, + lba_count, SPDK_BDEV_IO_TYPE_UNMAP, cb_args); + } else if (rc != 0) { cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc); } } else { @@ -159,6 +234,46 @@ bdev_blob_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64 } } +static void +bdev_blob_resubmit(void *arg) +{ + struct blob_resubmit *ctx = (struct blob_resubmit *) arg; + + switch (ctx->io_type) { + case SPDK_BDEV_IO_TYPE_READ: + if (ctx->iovcnt > 0) { + bdev_blob_readv(ctx->dev, ctx->channel, (struct iovec *)ctx->payload, ctx->iovcnt, + ctx->lba, ctx->lba_count, ctx->cb_args); + } else { + bdev_blob_read(ctx->dev, ctx->channel, ctx->payload, + ctx->lba, ctx->lba_count, ctx->cb_args); + } + break; + case SPDK_BDEV_IO_TYPE_WRITE: + if (ctx->iovcnt > 0) { + bdev_blob_writev(ctx->dev, ctx->channel, (struct iovec *)ctx->payload, ctx->iovcnt, + ctx->lba, ctx->lba_count, ctx->cb_args); + } else { + bdev_blob_write(ctx->dev, ctx->channel, ctx->payload, + ctx->lba, ctx->lba_count, ctx->cb_args); + } + break; + case SPDK_BDEV_IO_TYPE_UNMAP: + bdev_blob_unmap(ctx->dev, ctx->channel, + ctx->lba, ctx->lba_count, ctx->cb_args); + break; + case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: + bdev_blob_write_zeroes(ctx->dev, ctx->channel, + ctx->lba, ctx->lba_count, ctx->cb_args); + break; + default: + SPDK_ERRLOG("Unsupported io type %d\n", ctx->io_type); + assert(false); + break; + } + free(ctx); +} + int spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module *module) {