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 = { struct ftl_io_init_opts opts = {
.dev = parent->dev, .dev = parent->dev,
.parent = parent, .parent = parent,
.iovs = { .iovcnt = 0,
{
.iov_base = ftl_io_iovec_addr(parent),
.iov_len = num_blocks * FTL_BLOCK_SIZE,
}
},
.iovcnt = 1,
.num_blocks = num_blocks, .num_blocks = num_blocks,
.flags = parent->flags | FTL_IO_CACHE, .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 * static struct ftl_io *
ftl_io_init_child_write(struct ftl_io *parent, struct ftl_addr addr, ftl_io_init_child_write(struct ftl_io *parent, struct ftl_addr addr, ftl_io_fn cb)
void *data, void *md, ftl_io_fn cb)
{ {
struct ftl_io *io; struct ftl_io *io;
struct spdk_ftl_dev *dev = parent->dev; 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, .type = parent->type,
.num_blocks = dev->xfer_size, .num_blocks = dev->xfer_size,
.cb_fn = cb, .cb_fn = cb,
.iovs = { .iovcnt = 0,
{
.iov_base = data,
.iov_len = dev->xfer_size * FTL_BLOCK_SIZE,
}
},
.iovcnt = 1,
.md = md,
}; };
io = ftl_io_init_internal(&opts); 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 */ /* 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), child = ftl_io_init_child_write(io, addr, ftl_io_child_write_cb);
ftl_io_get_md(io), ftl_io_child_write_cb);
if (!child) { if (!child) {
return -EAGAIN; return -EAGAIN;
} }

View File

@ -158,78 +158,28 @@ ftl_io_iovec_len_left(struct ftl_io *io)
} }
static void 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_pos = 0;
io->iov_cnt = iov_cnt; io->iov_cnt = 0;
io->num_blocks = num_blocks; 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) { num_left = spdk_min(iov[io->iov_cnt].iov_len / FTL_BLOCK_SIZE - iov_off,
for (iov_off = 0; iov_off < iov_cnt; ++iov_off) { num_blocks);
io->num_blocks += iov[iov_off].iov_len / FTL_BLOCK_SIZE; 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 void
@ -275,6 +225,8 @@ ftl_io_init_internal(const struct ftl_io_init_opts *opts)
struct ftl_io *io = opts->io; struct ftl_io *io = opts->io;
struct ftl_io *parent = opts->parent; struct ftl_io *parent = opts->parent;
struct spdk_ftl_dev *dev = opts->dev; struct spdk_ftl_dev *dev = opts->dev;
const struct iovec *iov;
size_t iov_cnt, iov_off;
if (!io) { if (!io) {
if (parent) { if (parent) {
@ -302,13 +254,19 @@ ftl_io_init_internal(const struct ftl_io_init_opts *opts)
} else { } else {
io->lba.single = parent->lba.single + parent->pos; 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)) { /* Some requests (zone resets) do not use iovecs */
if (!opts->io) { if (iov_cnt > 0) {
ftl_io_free(io); ftl_io_init_iovec(io, iov, iov_cnt, iov_off, opts->num_blocks);
}
return NULL;
} }
if (opts->flags & FTL_IO_VECTOR_LBA) { if (opts->flags & FTL_IO_VECTOR_LBA) {