diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index e5c726de5..ae723bc8d 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -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; } diff --git a/lib/ftl/ftl_io.c b/lib/ftl/ftl_io.c index dafcc829c..e14b47efb 100644 --- a/lib/ftl/ftl_io.c +++ b/lib/ftl/ftl_io.c @@ -158,80 +158,30 @@ 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) {