bdev: Copy ext_opts when request is split
That is done to correctly handle metadata pointer which is part of ext_opts structure. It will also be used by the next patch to remove memory_domain pointer if request which uses local buffers is split Force the user to set correct ext_opts size, update API functions description. Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com> Change-Id: I77517d70df34a998d718cc6474fb4c538a42918f Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11349 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
parent
c20dd8afee
commit
8e7688c5a7
@ -934,7 +934,8 @@ int spdk_bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_c
|
|||||||
* \param cb Called when the request is complete.
|
* \param cb Called when the request is complete.
|
||||||
* \param cb_arg Argument passed to cb.
|
* \param cb_arg Argument passed to cb.
|
||||||
* \param opts Optional structure with extended IO request options. If set, this structure must be
|
* \param opts Optional structure with extended IO request options. If set, this structure must be
|
||||||
* valid until the IO is completed.
|
* valid until the IO is completed. `size` member of this structure is used for ABI compatibility and
|
||||||
|
* must be set to sizeof(struct spdk_bdev_ext_io_opts).
|
||||||
*
|
*
|
||||||
* \return 0 on success. On success, the callback will always
|
* \return 0 on success. On success, the callback will always
|
||||||
* be called (even if the request ultimately failed). Return
|
* be called (even if the request ultimately failed). Return
|
||||||
@ -1136,7 +1137,8 @@ int spdk_bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_
|
|||||||
* \param cb Called when the request is complete.
|
* \param cb Called when the request is complete.
|
||||||
* \param cb_arg Argument passed to cb.
|
* \param cb_arg Argument passed to cb.
|
||||||
* \param opts Optional structure with extended IO request options. If set, this structure must be
|
* \param opts Optional structure with extended IO request options. If set, this structure must be
|
||||||
* valid until the IO is completed.
|
* valid until the IO is completed. `size` member of this structure is used for ABI compatibility and
|
||||||
|
* must be set to sizeof(struct spdk_bdev_ext_io_opts).
|
||||||
*
|
*
|
||||||
* \return 0 on success. On success, the callback will always
|
* \return 0 on success. On success, the callback will always
|
||||||
* be called (even if the request ultimately failed). Return
|
* be called (even if the request ultimately failed). Return
|
||||||
|
@ -775,6 +775,9 @@ struct spdk_bdev_io {
|
|||||||
/** Pointer to a structure passed by the user in ext API */
|
/** Pointer to a structure passed by the user in ext API */
|
||||||
struct spdk_bdev_ext_io_opts *ext_opts;
|
struct spdk_bdev_ext_io_opts *ext_opts;
|
||||||
|
|
||||||
|
/** Copy of user's opts, used when I/O is split */
|
||||||
|
struct spdk_bdev_ext_io_opts ext_opts_copy;
|
||||||
|
|
||||||
/** Data transfer completion callback */
|
/** Data transfer completion callback */
|
||||||
void (*data_transfer_cpl)(void *ctx, int rc);
|
void (*data_transfer_cpl)(void *ctx, int rc);
|
||||||
} internal;
|
} internal;
|
||||||
|
@ -362,13 +362,13 @@ static int
|
|||||||
bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
struct iovec *iov, int iovcnt, void *md_buf, uint64_t offset_blocks,
|
struct iovec *iov, int iovcnt, void *md_buf, uint64_t offset_blocks,
|
||||||
uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg,
|
uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg,
|
||||||
struct spdk_bdev_ext_io_opts *opts);
|
struct spdk_bdev_ext_io_opts *opts, bool copy_opts);
|
||||||
static int
|
static int
|
||||||
bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
struct iovec *iov, int iovcnt, void *md_buf,
|
struct iovec *iov, int iovcnt, void *md_buf,
|
||||||
uint64_t offset_blocks, uint64_t num_blocks,
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg,
|
spdk_bdev_io_completion_cb cb, void *cb_arg,
|
||||||
struct spdk_bdev_ext_io_opts *opts);
|
struct spdk_bdev_ext_io_opts *opts, bool copy_opts);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bdev_lock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
bdev_lock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
||||||
@ -1876,6 +1876,10 @@ spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
|
|||||||
bdev_io_put_buf(bdev_io);
|
bdev_io_put_buf(bdev_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spdk_unlikely(bdev_io->internal.ext_opts == &bdev_io->internal.ext_opts_copy)) {
|
||||||
|
memset(&bdev_io->internal.ext_opts_copy, 0, sizeof(bdev_io->internal.ext_opts_copy));
|
||||||
|
}
|
||||||
|
|
||||||
if (ch->per_thread_cache_count < ch->bdev_io_cache_size) {
|
if (ch->per_thread_cache_count < ch->bdev_io_cache_size) {
|
||||||
ch->per_thread_cache_count++;
|
ch->per_thread_cache_count++;
|
||||||
STAILQ_INSERT_HEAD(&ch->per_thread_cache, bdev_io, internal.buf_link);
|
STAILQ_INSERT_HEAD(&ch->per_thread_cache, bdev_io, internal.buf_link);
|
||||||
@ -2321,7 +2325,7 @@ bdev_io_split_submit(struct spdk_bdev_io *bdev_io, struct iovec *iov, int iovcnt
|
|||||||
iov, iovcnt, md_buf, current_offset,
|
iov, iovcnt, md_buf, current_offset,
|
||||||
num_blocks,
|
num_blocks,
|
||||||
bdev_io_split_done, bdev_io,
|
bdev_io_split_done, bdev_io,
|
||||||
bdev_io->internal.ext_opts);
|
bdev_io->internal.ext_opts, true);
|
||||||
break;
|
break;
|
||||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||||
rc = bdev_writev_blocks_with_md(bdev_io->internal.desc,
|
rc = bdev_writev_blocks_with_md(bdev_io->internal.desc,
|
||||||
@ -2329,7 +2333,7 @@ bdev_io_split_submit(struct spdk_bdev_io *bdev_io, struct iovec *iov, int iovcnt
|
|||||||
iov, iovcnt, md_buf, current_offset,
|
iov, iovcnt, md_buf, current_offset,
|
||||||
num_blocks,
|
num_blocks,
|
||||||
bdev_io_split_done, bdev_io,
|
bdev_io_split_done, bdev_io,
|
||||||
bdev_io->internal.ext_opts);
|
bdev_io->internal.ext_opts, true);
|
||||||
break;
|
break;
|
||||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||||
io_wait_fn = _bdev_unmap_split;
|
io_wait_fn = _bdev_unmap_split;
|
||||||
@ -4084,11 +4088,12 @@ static int
|
|||||||
bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
struct iovec *iov, int iovcnt, void *md_buf, uint64_t offset_blocks,
|
struct iovec *iov, int iovcnt, void *md_buf, uint64_t offset_blocks,
|
||||||
uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg,
|
uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg,
|
||||||
struct spdk_bdev_ext_io_opts *opts)
|
struct spdk_bdev_ext_io_opts *opts, bool copy_opts)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
|
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
||||||
|
struct spdk_bdev_ext_io_opts *opts_copy;
|
||||||
|
|
||||||
if (!bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
if (!bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -4111,7 +4116,17 @@ bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *c
|
|||||||
bdev_io->internal.ext_opts = opts;
|
bdev_io->internal.ext_opts = opts;
|
||||||
bdev_io->u.bdev.ext_opts = opts;
|
bdev_io->u.bdev.ext_opts = opts;
|
||||||
|
|
||||||
|
if (opts && copy_opts) {
|
||||||
|
assert(opts->size <= sizeof(*opts));
|
||||||
|
opts_copy = &bdev_io->internal.ext_opts_copy;
|
||||||
|
memcpy(opts_copy, opts, opts->size);
|
||||||
|
bdev_io->internal.ext_opts_copy.metadata = md_buf;
|
||||||
|
bdev_io->internal.ext_opts = opts_copy;
|
||||||
|
bdev_io->u.bdev.ext_opts = opts_copy;
|
||||||
|
}
|
||||||
|
|
||||||
bdev_io_submit(bdev_io);
|
bdev_io_submit(bdev_io);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4121,7 +4136,7 @@ int spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *
|
|||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
return bdev_readv_blocks_with_md(desc, ch, iov, iovcnt, NULL, offset_blocks,
|
return bdev_readv_blocks_with_md(desc, ch, iov, iovcnt, NULL, offset_blocks,
|
||||||
num_blocks, cb, cb_arg, NULL);
|
num_blocks, cb, cb_arg, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -4139,7 +4154,7 @@ spdk_bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_chann
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bdev_readv_blocks_with_md(desc, ch, iov, iovcnt, md_buf, offset_blocks,
|
return bdev_readv_blocks_with_md(desc, ch, iov, iovcnt, md_buf, offset_blocks,
|
||||||
num_blocks, cb, cb_arg, NULL);
|
num_blocks, cb, cb_arg, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -4152,6 +4167,9 @@ spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *
|
|||||||
void *md = NULL;
|
void *md = NULL;
|
||||||
|
|
||||||
if (opts) {
|
if (opts) {
|
||||||
|
if (spdk_unlikely(!opts->size || opts->size > sizeof(struct spdk_bdev_ext_io_opts))) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
md = opts->metadata;
|
md = opts->metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4164,7 +4182,7 @@ spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bdev_readv_blocks_with_md(desc, ch, iov, iovcnt, md, offset_blocks,
|
return bdev_readv_blocks_with_md(desc, ch, iov, iovcnt, md, offset_blocks,
|
||||||
num_blocks, cb, cb_arg, opts);
|
num_blocks, cb, cb_arg, opts, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -4256,11 +4274,12 @@ bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *
|
|||||||
struct iovec *iov, int iovcnt, void *md_buf,
|
struct iovec *iov, int iovcnt, void *md_buf,
|
||||||
uint64_t offset_blocks, uint64_t num_blocks,
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg,
|
spdk_bdev_io_completion_cb cb, void *cb_arg,
|
||||||
struct spdk_bdev_ext_io_opts *opts)
|
struct spdk_bdev_ext_io_opts *opts, bool copy_opts)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
|
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
||||||
|
struct spdk_bdev_ext_io_opts *opts_copy;
|
||||||
|
|
||||||
if (!desc->write) {
|
if (!desc->write) {
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
@ -4287,7 +4306,17 @@ bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *
|
|||||||
bdev_io->internal.ext_opts = opts;
|
bdev_io->internal.ext_opts = opts;
|
||||||
bdev_io->u.bdev.ext_opts = opts;
|
bdev_io->u.bdev.ext_opts = opts;
|
||||||
|
|
||||||
|
if (opts && copy_opts) {
|
||||||
|
assert(opts->size <= sizeof(*opts));
|
||||||
|
opts_copy = &bdev_io->internal.ext_opts_copy;
|
||||||
|
memcpy(opts_copy, opts, opts->size);
|
||||||
|
bdev_io->internal.ext_opts_copy.metadata = md_buf;
|
||||||
|
bdev_io->internal.ext_opts = opts_copy;
|
||||||
|
bdev_io->u.bdev.ext_opts = opts_copy;
|
||||||
|
}
|
||||||
|
|
||||||
bdev_io_submit(bdev_io);
|
bdev_io_submit(bdev_io);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4314,7 +4343,7 @@ spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
return bdev_writev_blocks_with_md(desc, ch, iov, iovcnt, NULL, offset_blocks,
|
return bdev_writev_blocks_with_md(desc, ch, iov, iovcnt, NULL, offset_blocks,
|
||||||
num_blocks, cb, cb_arg, NULL);
|
num_blocks, cb, cb_arg, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -4332,7 +4361,7 @@ spdk_bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_chan
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bdev_writev_blocks_with_md(desc, ch, iov, iovcnt, md_buf, offset_blocks,
|
return bdev_writev_blocks_with_md(desc, ch, iov, iovcnt, md_buf, offset_blocks,
|
||||||
num_blocks, cb, cb_arg, NULL);
|
num_blocks, cb, cb_arg, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -4345,6 +4374,9 @@ spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel
|
|||||||
void *md = NULL;
|
void *md = NULL;
|
||||||
|
|
||||||
if (opts) {
|
if (opts) {
|
||||||
|
if (spdk_unlikely(!opts->size || opts->size > sizeof(struct spdk_bdev_ext_io_opts))) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
md = opts->metadata;
|
md = opts->metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4357,7 +4389,7 @@ spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bdev_writev_blocks_with_md(desc, ch, iov, iovcnt, md, offset_blocks,
|
return bdev_writev_blocks_with_md(desc, ch, iov, iovcnt, md, offset_blocks,
|
||||||
num_blocks, cb, cb_arg, opts);
|
num_blocks, cb, cb_arg, opts, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -238,6 +238,9 @@ stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
|
|||||||
|
|
||||||
if (expected_io->md_buf != NULL) {
|
if (expected_io->md_buf != NULL) {
|
||||||
CU_ASSERT(expected_io->md_buf == bdev_io->u.bdev.md_buf);
|
CU_ASSERT(expected_io->md_buf == bdev_io->u.bdev.md_buf);
|
||||||
|
if (bdev_io->internal.ext_opts) {
|
||||||
|
CU_ASSERT(expected_io->md_buf == bdev_io->internal.ext_opts->metadata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expected_io->length == 0) {
|
if (expected_io->length == 0) {
|
||||||
@ -4900,7 +4903,8 @@ bdev_writev_readv_ext(void)
|
|||||||
struct iovec iov = { .iov_base = (void *)0xbaaddead, .iov_len = 0x1000 };
|
struct iovec iov = { .iov_base = (void *)0xbaaddead, .iov_len = 0x1000 };
|
||||||
struct ut_expected_io *expected_io;
|
struct ut_expected_io *expected_io;
|
||||||
struct spdk_bdev_ext_io_opts ext_io_opts = {
|
struct spdk_bdev_ext_io_opts ext_io_opts = {
|
||||||
.metadata = (void *)0xFF000000
|
.metadata = (void *)0xFF000000,
|
||||||
|
.size = sizeof(ext_io_opts)
|
||||||
};
|
};
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -4947,6 +4951,134 @@ bdev_writev_readv_ext(void)
|
|||||||
stub_complete_io(1);
|
stub_complete_io(1);
|
||||||
CU_ASSERT(g_io_done == true);
|
CU_ASSERT(g_io_done == true);
|
||||||
|
|
||||||
|
/* Test invalid ext_opts size */
|
||||||
|
ext_io_opts.size = 0;
|
||||||
|
rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc != 0);
|
||||||
|
rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc != 0);
|
||||||
|
|
||||||
|
ext_io_opts.size = sizeof(ext_io_opts) * 2;
|
||||||
|
rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc != 0);
|
||||||
|
rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc != 0);
|
||||||
|
|
||||||
|
/* Check that IO request with ext_opts and metadata is split correctly
|
||||||
|
* Offset 14, length 8, payload 0xF000
|
||||||
|
* Child - Offset 14, length 2, payload 0xF000
|
||||||
|
* Child - Offset 16, length 6, payload 0xF000 + 2 * 512
|
||||||
|
*/
|
||||||
|
bdev->optimal_io_boundary = 16;
|
||||||
|
bdev->split_on_optimal_io_boundary = true;
|
||||||
|
bdev->md_interleave = false;
|
||||||
|
bdev->md_len = 8;
|
||||||
|
|
||||||
|
iov.iov_base = (void *)0xF000;
|
||||||
|
iov.iov_len = 4096;
|
||||||
|
memset(&ext_io_opts, 0, sizeof(ext_io_opts));
|
||||||
|
ext_io_opts.metadata = (void *)0xFF000000;
|
||||||
|
ext_io_opts.size = sizeof(ext_io_opts);
|
||||||
|
g_io_done = false;
|
||||||
|
|
||||||
|
/* read */
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1);
|
||||||
|
expected_io->md_buf = ext_io_opts.metadata;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1);
|
||||||
|
expected_io->md_buf = ext_io_opts.metadata + 2 * 8;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 14, 8, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(g_io_done == false);
|
||||||
|
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2);
|
||||||
|
stub_complete_io(2);
|
||||||
|
CU_ASSERT(g_io_done == true);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0);
|
||||||
|
|
||||||
|
/* write */
|
||||||
|
g_io_done = false;
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 1);
|
||||||
|
expected_io->md_buf = ext_io_opts.metadata;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 6, 1);
|
||||||
|
expected_io->md_buf = ext_io_opts.metadata + 2 * 8;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 14, 8, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(g_io_done == false);
|
||||||
|
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2);
|
||||||
|
stub_complete_io(2);
|
||||||
|
CU_ASSERT(g_io_done == true);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0);
|
||||||
|
|
||||||
|
/* ext_opts contains metadata but ext_opts::size doesn't cover metadata pointer.
|
||||||
|
* Check that IO request with ext_opts and metadata is split correctly - metadata pointer is not copied, so split
|
||||||
|
* requests do not have metadata
|
||||||
|
* Offset 14, length 8, payload 0xF000
|
||||||
|
* Child - Offset 14, length 2, payload 0xF000
|
||||||
|
* Child - Offset 16, length 6, payload 0xF000 + 2 * 512
|
||||||
|
*/
|
||||||
|
iov.iov_base = (void *)0xF000;
|
||||||
|
iov.iov_len = 4096;
|
||||||
|
memset(&ext_io_opts, 0, sizeof(ext_io_opts));
|
||||||
|
ext_io_opts.metadata = (void *)0xFF000000;
|
||||||
|
ext_io_opts.size = offsetof(struct spdk_bdev_ext_io_opts, metadata);;
|
||||||
|
g_io_done = false;
|
||||||
|
|
||||||
|
/* read */
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 14, 2, 1);
|
||||||
|
/* Split request must not contain metadata pointer */
|
||||||
|
expected_io->md_buf = NULL;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 16, 6, 1);
|
||||||
|
expected_io->md_buf = NULL;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 14, 8, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(g_io_done == false);
|
||||||
|
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2);
|
||||||
|
stub_complete_io(2);
|
||||||
|
CU_ASSERT(g_io_done == true);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0);
|
||||||
|
|
||||||
|
/* write */
|
||||||
|
g_io_done = false;
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 14, 2, 1);
|
||||||
|
expected_io->md_buf = NULL;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)0xF000, 2 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 16, 6, 1);
|
||||||
|
/* Split request must not contain metadata pointer */
|
||||||
|
expected_io->md_buf = NULL;
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, (void *)(0xF000 + 2 * 512), 6 * 512);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
rc = spdk_bdev_writev_blocks_ext(desc, io_ch, &iov, 1, 14, 8, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(g_io_done == false);
|
||||||
|
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2);
|
||||||
|
stub_complete_io(2);
|
||||||
|
CU_ASSERT(g_io_done == true);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0);
|
||||||
|
|
||||||
spdk_put_io_channel(io_ch);
|
spdk_put_io_channel(io_ch);
|
||||||
spdk_bdev_close(desc);
|
spdk_bdev_close(desc);
|
||||||
free_bdev(bdev);
|
free_bdev(bdev);
|
||||||
|
Loading…
Reference in New Issue
Block a user