lib/ftl: use parent's iovecs during child initialization

Fill in the child's iovec during its initialization by calculating it
based on the parent's iovecs and the request's block offset.

Change-Id: I61a1d5cf8a1ceae71e996d50db31077c43c4e3d9
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/898
Reviewed-by: Wojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Maciej Szczepaniak <maciej.szczepaniak@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Konrad Sztyber 2020-01-22 12:02:01 +01:00 committed by Tomasz Zawadzki
parent 4a3bf3a942
commit f4e42560b4
2 changed files with 32 additions and 89 deletions

View File

@ -1183,13 +1183,7 @@ ftl_alloc_io_nv_cache(struct ftl_io *parent, size_t num_blocks)
struct ftl_io_init_opts opts = {
.dev = parent->dev,
.parent = parent,
.iovs = {
{
.iov_base = ftl_io_iovec_addr(parent),
.iov_len = num_blocks * FTL_BLOCK_SIZE,
}
},
.iovcnt = 1,
.iovcnt = 0,
.num_blocks = num_blocks,
.flags = parent->flags | FTL_IO_CACHE,
};
@ -1520,8 +1514,7 @@ ftl_update_l2p(struct spdk_ftl_dev *dev, const struct ftl_rwb_entry *entry,
}
static struct ftl_io *
ftl_io_init_child_write(struct ftl_io *parent, struct ftl_addr addr,
void *data, void *md, ftl_io_fn cb)
ftl_io_init_child_write(struct ftl_io *parent, struct ftl_addr addr, ftl_io_fn cb)
{
struct ftl_io *io;
struct spdk_ftl_dev *dev = parent->dev;
@ -1536,14 +1529,7 @@ ftl_io_init_child_write(struct ftl_io *parent, struct ftl_addr addr,
.type = parent->type,
.num_blocks = dev->xfer_size,
.cb_fn = cb,
.iovs = {
{
.iov_base = data,
.iov_len = dev->xfer_size * FTL_BLOCK_SIZE,
}
},
.iovcnt = 1,
.md = md,
.iovcnt = 0,
};
io = ftl_io_init_internal(&opts);
@ -1598,8 +1584,7 @@ ftl_submit_child_write(struct ftl_wptr *wptr, struct ftl_io *io)
}
/* Split IO to child requests and release zone immediately after child is completed */
child = ftl_io_init_child_write(io, addr, ftl_io_iovec_addr(io),
ftl_io_get_md(io), ftl_io_child_write_cb);
child = ftl_io_init_child_write(io, addr, ftl_io_child_write_cb);
if (!child) {
return -EAGAIN;
}

View File

@ -158,79 +158,29 @@ ftl_io_iovec_len_left(struct ftl_io *io)
}
static void
_ftl_io_init_iovec(struct ftl_io *io, const struct iovec *iov, size_t iov_cnt, size_t num_blocks)
ftl_io_init_iovec(struct ftl_io *io, const struct iovec *iov, size_t iov_cnt, size_t iov_off,
size_t num_blocks)
{
size_t iov_off;
size_t offset = 0, num_left;
io->iov_pos = 0;
io->iov_cnt = iov_cnt;
io->iov_cnt = 0;
io->num_blocks = num_blocks;
memcpy(io->iov, iov, iov_cnt * sizeof(*iov));
while (offset < num_blocks) {
assert(io->iov_cnt < FTL_IO_MAX_IOVEC && io->iov_cnt < iov_cnt);
if (num_blocks == 0) {
for (iov_off = 0; iov_off < iov_cnt; ++iov_off) {
io->num_blocks += iov[iov_off].iov_len / FTL_BLOCK_SIZE;
num_left = spdk_min(iov[io->iov_cnt].iov_len / FTL_BLOCK_SIZE - iov_off,
num_blocks);
io->iov[io->iov_cnt].iov_base = (char *)iov[io->iov_cnt].iov_base +
iov_off * FTL_BLOCK_SIZE;
io->iov[io->iov_cnt].iov_len = num_left * FTL_BLOCK_SIZE;
offset += num_left;
io->iov_cnt++;
iov_off = 0;
}
}
}
static void _ftl_io_free(struct ftl_io *io);
static int
ftl_io_add_child(struct ftl_io *io, const struct iovec *iov, size_t iov_cnt)
{
struct ftl_io *child;
child = ftl_io_alloc_child(io);
if (spdk_unlikely(!child)) {
return -ENOMEM;
}
_ftl_io_init_iovec(child, iov, iov_cnt, 0);
if (io->flags & FTL_IO_VECTOR_LBA) {
child->lba.vector = io->lba.vector + io->num_blocks;
} else {
child->lba.single = io->lba.single + io->num_blocks;
}
io->num_blocks += child->num_blocks;
return 0;
}
static int
ftl_io_init_iovec(struct ftl_io *io, const struct iovec *iov, size_t iov_cnt, size_t num_blocks)
{
struct ftl_io *child;
size_t iov_off = 0, iov_left;
int rc;
if (spdk_likely(iov_cnt <= FTL_IO_MAX_IOVEC)) {
_ftl_io_init_iovec(io, iov, iov_cnt, num_blocks);
return 0;
}
while (iov_off < iov_cnt) {
iov_left = spdk_min(iov_cnt - iov_off, FTL_IO_MAX_IOVEC);
rc = ftl_io_add_child(io, &iov[iov_off], iov_left);
if (spdk_unlikely(rc != 0)) {
while ((child = LIST_FIRST(&io->children))) {
assert(LIST_EMPTY(&child->children));
LIST_REMOVE(child, child_entry);
_ftl_io_free(child);
}
return -ENOMEM;
}
iov_off += iov_left;
}
assert(io->num_blocks == num_blocks);
return 0;
}
void
ftl_io_shrink_iovec(struct ftl_io *io, size_t num_blocks)
@ -275,6 +225,8 @@ ftl_io_init_internal(const struct ftl_io_init_opts *opts)
struct ftl_io *io = opts->io;
struct ftl_io *parent = opts->parent;
struct spdk_ftl_dev *dev = opts->dev;
const struct iovec *iov;
size_t iov_cnt, iov_off;
if (!io) {
if (parent) {
@ -302,13 +254,19 @@ ftl_io_init_internal(const struct ftl_io_init_opts *opts)
} else {
io->lba.single = parent->lba.single + parent->pos;
}
iov = &parent->iov[parent->iov_pos];
iov_cnt = parent->iov_cnt - parent->iov_pos;
iov_off = parent->iov_off;
} else {
iov = &opts->iovs[0];
iov_cnt = opts->iovcnt;
iov_off = 0;
}
if (ftl_io_init_iovec(io, opts->iovs, opts->iovcnt, opts->num_blocks)) {
if (!opts->io) {
ftl_io_free(io);
}
return NULL;
/* Some requests (zone resets) do not use iovecs */
if (iov_cnt > 0) {
ftl_io_init_iovec(io, iov, iov_cnt, iov_off, opts->num_blocks);
}
if (opts->flags & FTL_IO_VECTOR_LBA) {