2022-06-03 19:15:11 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
2022-11-01 20:26:26 +00:00
|
|
|
* Copyright (C) 2017 Intel Corporation.
|
2017-03-22 20:35:00 +00:00
|
|
|
* All rights reserved.
|
2023-01-05 14:35:40 +00:00
|
|
|
* Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2017-03-22 20:35:00 +00:00
|
|
|
*/
|
2017-05-02 18:18:25 +00:00
|
|
|
|
|
|
|
#include "spdk/stdinc.h"
|
2017-03-22 20:35:00 +00:00
|
|
|
|
|
|
|
#include "spdk/blob_bdev.h"
|
|
|
|
#include "spdk/blob.h"
|
2018-06-11 20:32:15 +00:00
|
|
|
#include "spdk/thread.h"
|
2017-03-22 20:35:00 +00:00
|
|
|
#include "spdk/log.h"
|
|
|
|
#include "spdk/endian.h"
|
2021-05-07 17:34:18 +00:00
|
|
|
#define __SPDK_BDEV_MODULE_ONLY
|
2018-05-23 21:01:03 +00:00
|
|
|
#include "spdk/bdev_module.h"
|
2017-03-22 20:35:00 +00:00
|
|
|
|
|
|
|
struct blob_bdev {
|
|
|
|
struct spdk_bs_dev bs_dev;
|
|
|
|
struct spdk_bdev *bdev;
|
2017-06-29 18:23:50 +00:00
|
|
|
struct spdk_bdev_desc *desc;
|
2023-01-11 19:48:06 +00:00
|
|
|
bool write;
|
2023-01-16 23:34:32 +00:00
|
|
|
int32_t refs;
|
|
|
|
struct spdk_spinlock lock;
|
2017-03-22 20:35:00 +00:00
|
|
|
};
|
|
|
|
|
2018-08-27 12:02:15 +00:00
|
|
|
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;
|
2022-08-22 13:59:37 +00:00
|
|
|
uint64_t src_lba;
|
2018-08-27 12:02:15 +00:00
|
|
|
uint32_t lba_count;
|
|
|
|
struct spdk_bs_dev_cb_args *cb_args;
|
2022-01-31 10:30:04 +00:00
|
|
|
struct spdk_blob_ext_io_opts *ext_io_opts;
|
2018-08-27 12:02:15 +00:00
|
|
|
};
|
|
|
|
static void bdev_blob_resubmit(void *);
|
|
|
|
|
2017-07-06 10:04:25 +00:00
|
|
|
static inline struct spdk_bdev_desc *
|
|
|
|
__get_desc(struct spdk_bs_dev *dev)
|
|
|
|
{
|
|
|
|
return ((struct blob_bdev *)dev)->desc;
|
|
|
|
}
|
|
|
|
|
2018-08-27 12:02:15 +00:00
|
|
|
static inline struct spdk_bdev *
|
|
|
|
__get_bdev(struct spdk_bs_dev *dev)
|
|
|
|
{
|
|
|
|
return ((struct blob_bdev *)dev)->bdev;
|
|
|
|
}
|
|
|
|
|
2017-03-22 20:35:00 +00:00
|
|
|
static void
|
2017-05-16 20:25:03 +00:00
|
|
|
bdev_blob_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg)
|
2017-03-22 20:35:00 +00:00
|
|
|
{
|
|
|
|
struct spdk_bs_dev_cb_args *cb_args = arg;
|
|
|
|
int bserrno;
|
|
|
|
|
2017-05-16 20:25:03 +00:00
|
|
|
if (success) {
|
2017-03-22 20:35:00 +00:00
|
|
|
bserrno = 0;
|
|
|
|
} else {
|
|
|
|
bserrno = -EIO;
|
|
|
|
}
|
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno);
|
|
|
|
spdk_bdev_free_io(bdev_io);
|
|
|
|
}
|
|
|
|
|
2018-08-27 12:02:15 +00:00
|
|
|
static void
|
|
|
|
bdev_blob_queue_io(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
|
2022-08-22 13:59:37 +00:00
|
|
|
int iovcnt, uint64_t lba, uint64_t src_lba, uint32_t lba_count,
|
|
|
|
enum spdk_bdev_io_type io_type, struct spdk_bs_dev_cb_args *cb_args,
|
|
|
|
struct spdk_blob_ext_io_opts *ext_io_opts)
|
2018-08-27 12:02:15 +00:00
|
|
|
{
|
|
|
|
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;
|
2022-08-22 13:59:37 +00:00
|
|
|
ctx->src_lba = src_lba;
|
2018-08-27 12:02:15 +00:00
|
|
|
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;
|
2022-01-31 10:30:04 +00:00
|
|
|
ctx->ext_io_opts = ext_io_opts;
|
2018-08-27 12:02:15 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-22 20:35:00 +00:00
|
|
|
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)
|
|
|
|
{
|
2017-06-05 18:39:38 +00:00
|
|
|
int rc;
|
2017-03-22 20:35:00 +00:00
|
|
|
|
2017-08-29 21:35:39 +00:00
|
|
|
rc = spdk_bdev_read_blocks(__get_desc(dev), channel, payload, lba,
|
|
|
|
lba_count, bdev_blob_io_complete, cb_args);
|
2018-08-27 12:02:15 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, payload, 0, lba, 0,
|
2022-01-31 10:30:04 +00:00
|
|
|
lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args, NULL);
|
2018-08-27 12:02:15 +00:00
|
|
|
} else if (rc != 0) {
|
2017-06-05 18:39:38 +00:00
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
2017-03-22 20:35:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_blob_write(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)
|
|
|
|
{
|
2017-06-05 18:39:38 +00:00
|
|
|
int rc;
|
2017-03-22 20:35:00 +00:00
|
|
|
|
2017-08-29 21:35:39 +00:00
|
|
|
rc = spdk_bdev_write_blocks(__get_desc(dev), channel, payload, lba,
|
|
|
|
lba_count, bdev_blob_io_complete, cb_args);
|
2018-08-27 12:02:15 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, payload, 0, lba, 0,
|
2022-01-31 10:30:04 +00:00
|
|
|
lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args, NULL);
|
2018-08-27 12:02:15 +00:00
|
|
|
} else if (rc != 0) {
|
2017-06-05 18:39:38 +00:00
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
2017-03-22 20:35:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-18 16:41:26 +00:00
|
|
|
static void
|
|
|
|
bdev_blob_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
|
|
|
|
struct iovec *iov, int iovcnt,
|
|
|
|
uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2017-08-29 21:35:39 +00:00
|
|
|
rc = spdk_bdev_readv_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
|
|
|
|
lba_count, bdev_blob_io_complete, cb_args);
|
2018-08-27 12:02:15 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0,
|
2022-01-31 10:30:04 +00:00
|
|
|
lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args, NULL);
|
2018-08-27 12:02:15 +00:00
|
|
|
} else if (rc != 0) {
|
2017-08-18 16:41:26 +00:00
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_blob_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
|
|
|
|
struct iovec *iov, int iovcnt,
|
|
|
|
uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2017-08-29 21:35:39 +00:00
|
|
|
rc = spdk_bdev_writev_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
|
|
|
|
lba_count, bdev_blob_io_complete, cb_args);
|
2018-08-27 12:02:15 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0,
|
2022-01-31 10:30:04 +00:00
|
|
|
lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args, NULL);
|
2018-08-27 12:02:15 +00:00
|
|
|
} else if (rc != 0) {
|
2017-08-18 16:41:26 +00:00
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
static inline void
|
|
|
|
blob_ext_io_opts_to_bdev_opts(struct spdk_bdev_ext_io_opts *dst, struct spdk_blob_ext_io_opts *src)
|
|
|
|
{
|
|
|
|
memset(dst, 0, sizeof(*dst));
|
|
|
|
dst->size = sizeof(*dst);
|
|
|
|
dst->memory_domain = src->memory_domain;
|
|
|
|
dst->memory_domain_ctx = src->memory_domain_ctx;
|
|
|
|
}
|
|
|
|
|
2022-01-31 08:53:15 +00:00
|
|
|
static void
|
|
|
|
bdev_blob_readv_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
|
|
|
|
struct iovec *iov, int iovcnt,
|
|
|
|
uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args,
|
|
|
|
struct spdk_blob_ext_io_opts *io_opts)
|
|
|
|
{
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
struct spdk_bdev_ext_io_opts bdev_io_opts;
|
2022-01-31 10:30:04 +00:00
|
|
|
int rc;
|
|
|
|
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
blob_ext_io_opts_to_bdev_opts(&bdev_io_opts, io_opts);
|
2022-01-31 10:30:04 +00:00
|
|
|
rc = spdk_bdev_readv_blocks_ext(__get_desc(dev), channel, iov, iovcnt, lba, lba_count,
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
bdev_blob_io_complete, cb_args, &bdev_io_opts);
|
2022-01-31 10:30:04 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0, lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args,
|
2022-01-31 10:30:04 +00:00
|
|
|
io_opts);
|
|
|
|
} else if (rc != 0) {
|
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
|
|
|
}
|
2022-01-31 08:53:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_blob_writev_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
|
|
|
|
struct iovec *iov, int iovcnt,
|
|
|
|
uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args,
|
|
|
|
struct spdk_blob_ext_io_opts *io_opts)
|
|
|
|
{
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
struct spdk_bdev_ext_io_opts bdev_io_opts;
|
2022-01-31 10:30:04 +00:00
|
|
|
int rc;
|
|
|
|
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
blob_ext_io_opts_to_bdev_opts(&bdev_io_opts, io_opts);
|
2022-01-31 10:30:04 +00:00
|
|
|
rc = spdk_bdev_writev_blocks_ext(__get_desc(dev), channel, iov, iovcnt, lba, lba_count,
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
bdev_blob_io_complete, cb_args, &bdev_io_opts);
|
2022-01-31 10:30:04 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0, lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args,
|
2022-01-31 10:30:04 +00:00
|
|
|
io_opts);
|
|
|
|
} else if (rc != 0) {
|
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
|
|
|
}
|
2022-01-31 08:53:15 +00:00
|
|
|
}
|
|
|
|
|
2017-07-27 17:58:51 +00:00
|
|
|
static void
|
|
|
|
bdev_blob_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
|
2021-10-05 23:37:19 +00:00
|
|
|
uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
|
2017-07-27 17:58:51 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = spdk_bdev_write_zeroes_blocks(__get_desc(dev), channel, lba,
|
|
|
|
lba_count, bdev_blob_io_complete, cb_args);
|
2018-08-27 12:02:15 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, NULL, 0, lba, 0,
|
2022-01-31 10:30:04 +00:00
|
|
|
lba_count, SPDK_BDEV_IO_TYPE_WRITE_ZEROES, cb_args, NULL);
|
2018-08-27 12:02:15 +00:00
|
|
|
} else if (rc != 0) {
|
2017-07-27 17:58:51 +00:00
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-22 20:35:00 +00:00
|
|
|
static void
|
|
|
|
bdev_blob_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
|
2021-10-05 23:37:19 +00:00
|
|
|
uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
|
2017-03-22 20:35:00 +00:00
|
|
|
{
|
2017-12-04 17:40:17 +00:00
|
|
|
struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
|
2017-06-05 18:39:38 +00:00
|
|
|
int rc;
|
2017-03-22 20:35:00 +00:00
|
|
|
|
2017-12-04 17:40:17 +00:00
|
|
|
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);
|
2018-08-27 12:02:15 +00:00
|
|
|
if (rc == -ENOMEM) {
|
2022-08-22 13:59:37 +00:00
|
|
|
bdev_blob_queue_io(dev, channel, NULL, 0, lba, 0,
|
2022-01-31 10:30:04 +00:00
|
|
|
lba_count, SPDK_BDEV_IO_TYPE_UNMAP, cb_args, NULL);
|
2018-08-27 12:02:15 +00:00
|
|
|
} else if (rc != 0) {
|
2017-12-04 17:40:17 +00:00
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If the device doesn't support unmap, immediately complete
|
|
|
|
* the request. Blobstore does not rely on unmap zeroing
|
|
|
|
* data.
|
|
|
|
*/
|
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0);
|
2017-03-22 20:35:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-22 13:59:37 +00:00
|
|
|
static void
|
|
|
|
bdev_blob_copy(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
|
|
|
|
uint64_t dst_lba, uint64_t src_lba, uint64_t lba_count,
|
|
|
|
struct spdk_bs_dev_cb_args *cb_args)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = spdk_bdev_copy_blocks(__get_desc(dev), channel,
|
|
|
|
dst_lba, src_lba, lba_count,
|
|
|
|
bdev_blob_io_complete, cb_args);
|
|
|
|
if (rc == -ENOMEM) {
|
|
|
|
bdev_blob_queue_io(dev, channel, NULL, 0, dst_lba, src_lba,
|
|
|
|
lba_count, SPDK_BDEV_IO_TYPE_COPY, cb_args, NULL);
|
|
|
|
} else if (rc != 0) {
|
|
|
|
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-27 12:02:15 +00:00
|
|
|
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) {
|
2022-01-31 10:30:04 +00:00
|
|
|
bdev_blob_readv_ext(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
|
|
|
|
ctx->lba, ctx->lba_count, ctx->cb_args, ctx->ext_io_opts);
|
2018-08-27 12:02:15 +00:00
|
|
|
} 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) {
|
2022-01-31 10:30:04 +00:00
|
|
|
bdev_blob_writev_ext(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
|
|
|
|
ctx->lba, ctx->lba_count, ctx->cb_args, ctx->ext_io_opts);
|
2018-08-27 12:02:15 +00:00
|
|
|
} 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;
|
2022-08-22 13:59:37 +00:00
|
|
|
case SPDK_BDEV_IO_TYPE_COPY:
|
|
|
|
bdev_blob_copy(ctx->dev, ctx->channel,
|
|
|
|
ctx->lba, ctx->src_lba, ctx->lba_count, ctx->cb_args);
|
|
|
|
break;
|
2018-08-27 12:02:15 +00:00
|
|
|
default:
|
|
|
|
SPDK_ERRLOG("Unsupported io type %d\n", ctx->io_type);
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free(ctx);
|
|
|
|
}
|
|
|
|
|
2017-10-05 15:17:38 +00:00
|
|
|
int
|
2018-03-09 22:20:21 +00:00
|
|
|
spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module *module)
|
2017-10-05 15:17:38 +00:00
|
|
|
{
|
2023-01-11 19:48:06 +00:00
|
|
|
struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
|
|
|
|
struct spdk_bdev_desc *desc = blob_bdev->desc;
|
|
|
|
enum spdk_bdev_claim_type claim_type;
|
2017-10-05 15:17:38 +00:00
|
|
|
int rc;
|
|
|
|
|
2023-01-11 19:48:06 +00:00
|
|
|
claim_type = blob_bdev->write ? SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE :
|
|
|
|
SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE;
|
|
|
|
rc = spdk_bdev_module_claim_bdev_desc(desc, claim_type, NULL, module);
|
2017-10-05 15:17:38 +00:00
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("could not claim bs dev\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2017-03-22 20:35:00 +00:00
|
|
|
static struct spdk_io_channel *
|
|
|
|
bdev_blob_create_channel(struct spdk_bs_dev *dev)
|
|
|
|
{
|
2017-06-29 18:23:50 +00:00
|
|
|
struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
|
2023-01-16 23:34:32 +00:00
|
|
|
struct spdk_io_channel *ch;
|
2017-03-22 20:35:00 +00:00
|
|
|
|
2023-01-16 23:34:32 +00:00
|
|
|
ch = spdk_bdev_get_io_channel(blob_bdev->desc);
|
|
|
|
if (ch != NULL) {
|
|
|
|
spdk_spin_lock(&blob_bdev->lock);
|
|
|
|
blob_bdev->refs++;
|
|
|
|
spdk_spin_unlock(&blob_bdev->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_blob_free(struct blob_bdev *blob_bdev)
|
|
|
|
{
|
|
|
|
assert(blob_bdev->refs == 0);
|
|
|
|
|
|
|
|
spdk_spin_destroy(&blob_bdev->lock);
|
|
|
|
free(blob_bdev);
|
2017-03-22 20:35:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_blob_destroy_channel(struct spdk_bs_dev *dev, struct spdk_io_channel *channel)
|
|
|
|
{
|
2023-01-16 23:34:32 +00:00
|
|
|
struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
|
|
|
|
int32_t refs;
|
|
|
|
|
|
|
|
spdk_spin_lock(&blob_bdev->lock);
|
|
|
|
|
|
|
|
assert(blob_bdev->refs > 0);
|
|
|
|
blob_bdev->refs--;
|
|
|
|
refs = blob_bdev->refs;
|
|
|
|
|
|
|
|
spdk_spin_unlock(&blob_bdev->lock);
|
|
|
|
|
2017-03-22 20:35:00 +00:00
|
|
|
spdk_put_io_channel(channel);
|
2023-01-16 23:34:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the value of blob_bdev->refs taken while holding blob_bdev->refs is zero, the blob and
|
|
|
|
* this channel have been destroyed. This means that dev->destroy() has been called and it
|
|
|
|
* would be an error (akin to use after free) if dev is dereferenced after destroying it.
|
|
|
|
* Thus, there should be no race with bdev_blob_create_channel().
|
|
|
|
*
|
|
|
|
* Because the value of blob_bdev->refs was taken while holding the lock here and the same
|
|
|
|
* is done in bdev_blob_destroy(), there is no race with bdev_blob_destroy().
|
|
|
|
*/
|
|
|
|
if (refs == 0) {
|
|
|
|
bdev_blob_free(blob_bdev);
|
|
|
|
}
|
2017-03-22 20:35:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_blob_destroy(struct spdk_bs_dev *bs_dev)
|
|
|
|
{
|
2023-01-16 23:34:32 +00:00
|
|
|
struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
|
|
|
|
struct spdk_bdev_desc *desc;
|
|
|
|
int32_t refs;
|
|
|
|
|
|
|
|
spdk_spin_lock(&blob_bdev->lock);
|
|
|
|
|
|
|
|
desc = blob_bdev->desc;
|
|
|
|
blob_bdev->desc = NULL;
|
|
|
|
blob_bdev->refs--;
|
|
|
|
refs = blob_bdev->refs;
|
|
|
|
|
|
|
|
spdk_spin_unlock(&blob_bdev->lock);
|
2017-07-06 10:04:25 +00:00
|
|
|
|
|
|
|
spdk_bdev_close(desc);
|
2023-01-16 23:34:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the value of blob_bdev->refs taken while holding blob_bdev->refs is zero,
|
|
|
|
* bs_dev->destroy() has been called and all the channels have been destroyed. It would be
|
|
|
|
* an error (akin to use after free) if bs_dev is dereferenced after destroying it. Thus,
|
|
|
|
* there should be no race with bdev_blob_create_channel().
|
|
|
|
*
|
|
|
|
* Because the value of blob_bdev->refs was taken while holding the lock here and the same
|
|
|
|
* is done in bdev_blob_destroy_channel(), there is no race with
|
|
|
|
* bdev_blob_destroy_channel().
|
|
|
|
*/
|
|
|
|
if (refs == 0) {
|
|
|
|
bdev_blob_free(blob_bdev);
|
|
|
|
}
|
2017-03-22 20:35:00 +00:00
|
|
|
}
|
|
|
|
|
2020-10-14 18:04:45 +00:00
|
|
|
static struct spdk_bdev *
|
|
|
|
bdev_blob_get_base_bdev(struct spdk_bs_dev *bs_dev)
|
|
|
|
{
|
|
|
|
return __get_bdev(bs_dev);
|
|
|
|
}
|
|
|
|
|
2022-06-22 13:55:46 +00:00
|
|
|
static bool
|
|
|
|
bdev_blob_is_zeroes(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-09-15 21:56:12 +00:00
|
|
|
static bool
|
|
|
|
bdev_blob_translate_lba(struct spdk_bs_dev *dev, uint64_t lba, uint64_t *base_lba)
|
|
|
|
{
|
|
|
|
*base_lba = lba;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-10-14 14:08:31 +00:00
|
|
|
static void
|
|
|
|
blob_bdev_init(struct blob_bdev *b, struct spdk_bdev_desc *desc)
|
|
|
|
{
|
|
|
|
struct spdk_bdev *bdev;
|
|
|
|
|
|
|
|
bdev = spdk_bdev_desc_get_bdev(desc);
|
|
|
|
assert(bdev != NULL);
|
|
|
|
|
|
|
|
b->bdev = bdev;
|
|
|
|
b->desc = desc;
|
|
|
|
b->bs_dev.blockcnt = spdk_bdev_get_num_blocks(bdev);
|
|
|
|
b->bs_dev.blocklen = spdk_bdev_get_block_size(bdev);
|
|
|
|
b->bs_dev.create_channel = bdev_blob_create_channel;
|
|
|
|
b->bs_dev.destroy_channel = bdev_blob_destroy_channel;
|
|
|
|
b->bs_dev.destroy = bdev_blob_destroy;
|
|
|
|
b->bs_dev.read = bdev_blob_read;
|
|
|
|
b->bs_dev.write = bdev_blob_write;
|
|
|
|
b->bs_dev.readv = bdev_blob_readv;
|
|
|
|
b->bs_dev.writev = bdev_blob_writev;
|
2022-01-31 08:53:15 +00:00
|
|
|
b->bs_dev.readv_ext = bdev_blob_readv_ext;
|
|
|
|
b->bs_dev.writev_ext = bdev_blob_writev_ext;
|
2020-10-14 14:08:31 +00:00
|
|
|
b->bs_dev.write_zeroes = bdev_blob_write_zeroes;
|
|
|
|
b->bs_dev.unmap = bdev_blob_unmap;
|
2022-08-22 13:59:37 +00:00
|
|
|
if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_COPY)) {
|
|
|
|
b->bs_dev.copy = bdev_blob_copy;
|
|
|
|
}
|
2020-10-14 18:04:45 +00:00
|
|
|
b->bs_dev.get_base_bdev = bdev_blob_get_base_bdev;
|
2022-06-22 13:55:46 +00:00
|
|
|
b->bs_dev.is_zeroes = bdev_blob_is_zeroes;
|
2022-09-15 21:56:12 +00:00
|
|
|
b->bs_dev.translate_lba = bdev_blob_translate_lba;
|
2020-10-14 14:08:31 +00:00
|
|
|
}
|
|
|
|
|
2020-10-14 14:55:06 +00:00
|
|
|
int
|
2022-09-20 14:53:06 +00:00
|
|
|
spdk_bdev_create_bs_dev(const char *bdev_name, bool write,
|
|
|
|
struct spdk_bdev_bs_dev_opts *opts, size_t opts_size,
|
|
|
|
spdk_bdev_event_cb_t event_cb, void *event_ctx,
|
|
|
|
struct spdk_bs_dev **bs_dev)
|
2020-10-14 14:55:06 +00:00
|
|
|
{
|
|
|
|
struct blob_bdev *b;
|
|
|
|
struct spdk_bdev_desc *desc;
|
|
|
|
int rc;
|
|
|
|
|
2023-01-16 23:34:32 +00:00
|
|
|
assert(spdk_get_thread() != NULL);
|
|
|
|
|
2022-09-20 14:53:06 +00:00
|
|
|
if (opts != NULL && opts_size != sizeof(*opts)) {
|
|
|
|
SPDK_ERRLOG("bdev name '%s': unsupported options\n", bdev_name);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2020-10-14 14:55:06 +00:00
|
|
|
b = calloc(1, sizeof(*b));
|
|
|
|
|
|
|
|
if (b == NULL) {
|
|
|
|
SPDK_ERRLOG("could not allocate blob_bdev\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2022-09-20 14:53:06 +00:00
|
|
|
rc = spdk_bdev_open_ext(bdev_name, write, event_cb, event_ctx, &desc);
|
2020-10-14 14:55:06 +00:00
|
|
|
if (rc != 0) {
|
|
|
|
free(b);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
blob_bdev_init(b, desc);
|
|
|
|
|
2022-09-20 14:53:06 +00:00
|
|
|
*bs_dev = &b->bs_dev;
|
2023-01-11 19:48:06 +00:00
|
|
|
b->write = write;
|
2023-01-16 23:34:32 +00:00
|
|
|
b->refs = 1;
|
|
|
|
spdk_spin_init(&b->lock);
|
2020-10-14 14:55:06 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2022-09-20 14:53:06 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
spdk_bdev_create_bs_dev_ext(const char *bdev_name, spdk_bdev_event_cb_t event_cb,
|
|
|
|
void *event_ctx, struct spdk_bs_dev **bs_dev)
|
|
|
|
{
|
|
|
|
return spdk_bdev_create_bs_dev(bdev_name, true, NULL, 0, event_cb, event_ctx, bs_dev);
|
|
|
|
}
|