Commit f4e42560 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Tomasz Zawadzki
Browse files

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: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/898


Reviewed-by: default avatarWojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarMaciej Szczepaniak <maciej.szczepaniak@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 4a3bf3a9
Loading
Loading
Loading
Loading
+4 −19
Original line number Diff line number Diff line
@@ -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;
	}
+27 −69
Original line number Diff line number Diff line
@@ -158,78 +158,28 @@ 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));

	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;
		}
	}
}

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;
	}
	while (offset < num_blocks) {
		assert(io->iov_cnt < FTL_IO_MAX_IOVEC && io->iov_cnt < iov_cnt);

	_ftl_io_init_iovec(child, iov, iov_cnt, 0);
		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;

	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;
		offset += num_left;
		io->iov_cnt++;
		iov_off = 0;
	}

	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
@@ -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;
		}
	}

	if (ftl_io_init_iovec(io, opts->iovs, opts->iovcnt, opts->num_blocks)) {
		if (!opts->io) {
			ftl_io_free(io);
		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;
	}
		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) {