Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d5ee2b2 authored by Steve Wise's avatar Steve Wise Committed by Christoph Hellwig
Browse files

nvmet-rdma: support max(16KB, PAGE_SIZE) inline data



The patch enables inline data sizes using up to 4 recv sges, and capping
the size at 16KB or at least 1 page size.  So on a 4K page system, up to
16KB is supported, and for a 64K page system 1 page of 64KB is supported.

We avoid > 0 order page allocations for the inline buffers by using
multiple recv sges, one for each page.  If the device cannot support
the configured inline data size due to lack of enough recv sges, then
log a warning and reduce the inline size.

Add a new configfs port attribute, called param_inline_data_size,
to allow configuring the size of inline data for a given nvmf port.
The maximum size allowed is still enforced by nvmet-rdma with
NVMET_RDMA_MAX_INLINE_DATA_SIZE, which is now max(16KB, PAGE_SIZE).
And the default size, if not specified via configfs, is still PAGE_SIZE.
This preserves the existing behavior, but allows larger inline sizes
for small page systems.  If the configured inline data size exceeds
NVMET_RDMA_MAX_INLINE_DATA_SIZE, a warning is logged and the size is
reduced.  If param_inline_data_size is set to 0, then inline data is
disabled for that nvmf port.

Reviewed-by: default avatarSagi Grimberg <sagi@grimberg.me>
Reviewed-by: default avatarMax Gurtovoy <maxg@mellanox.com>
Signed-off-by: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 64a741c1
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -268,14 +268,14 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
	id->sgls = cpu_to_le32(1 << 0);	/* we always support SGLs */
	id->sgls = cpu_to_le32(1 << 0);	/* we always support SGLs */
	if (ctrl->ops->has_keyed_sgls)
	if (ctrl->ops->has_keyed_sgls)
		id->sgls |= cpu_to_le32(1 << 2);
		id->sgls |= cpu_to_le32(1 << 2);
	if (ctrl->ops->sqe_inline_size)
	if (req->port->inline_data_size)
		id->sgls |= cpu_to_le32(1 << 20);
		id->sgls |= cpu_to_le32(1 << 20);


	strcpy(id->subnqn, ctrl->subsys->subsysnqn);
	strcpy(id->subnqn, ctrl->subsys->subsysnqn);


	/* Max command capsule size is sqe + single page of in-capsule data */
	/* Max command capsule size is sqe + single page of in-capsule data */
	id->ioccsz = cpu_to_le32((sizeof(struct nvme_command) +
	id->ioccsz = cpu_to_le32((sizeof(struct nvme_command) +
				  ctrl->ops->sqe_inline_size) / 16);
				  req->port->inline_data_size) / 16);
	/* Max response capsule size is cqe */
	/* Max response capsule size is cqe */
	id->iorcsz = cpu_to_le32(sizeof(struct nvme_completion) / 16);
	id->iorcsz = cpu_to_le32(sizeof(struct nvme_completion) / 16);


+31 −0
Original line number Original line Diff line number Diff line
@@ -218,6 +218,35 @@ static ssize_t nvmet_addr_trsvcid_store(struct config_item *item,


CONFIGFS_ATTR(nvmet_, addr_trsvcid);
CONFIGFS_ATTR(nvmet_, addr_trsvcid);


static ssize_t nvmet_param_inline_data_size_show(struct config_item *item,
		char *page)
{
	struct nvmet_port *port = to_nvmet_port(item);

	return snprintf(page, PAGE_SIZE, "%d\n", port->inline_data_size);
}

static ssize_t nvmet_param_inline_data_size_store(struct config_item *item,
		const char *page, size_t count)
{
	struct nvmet_port *port = to_nvmet_port(item);
	int ret;

	if (port->enabled) {
		pr_err("Cannot modify inline_data_size while port enabled\n");
		pr_err("Disable the port before modifying\n");
		return -EACCES;
	}
	ret = kstrtoint(page, 0, &port->inline_data_size);
	if (ret) {
		pr_err("Invalid value '%s' for inline_data_size\n", page);
		return -EINVAL;
	}
	return count;
}

CONFIGFS_ATTR(nvmet_, param_inline_data_size);

static ssize_t nvmet_addr_trtype_show(struct config_item *item,
static ssize_t nvmet_addr_trtype_show(struct config_item *item,
		char *page)
		char *page)
{
{
@@ -903,6 +932,7 @@ static struct configfs_attribute *nvmet_port_attrs[] = {
	&nvmet_attr_addr_traddr,
	&nvmet_attr_addr_traddr,
	&nvmet_attr_addr_trsvcid,
	&nvmet_attr_addr_trsvcid,
	&nvmet_attr_addr_trtype,
	&nvmet_attr_addr_trtype,
	&nvmet_attr_param_inline_data_size,
	NULL,
	NULL,
};
};


@@ -932,6 +962,7 @@ static struct config_group *nvmet_ports_make(struct config_group *group,
	INIT_LIST_HEAD(&port->entry);
	INIT_LIST_HEAD(&port->entry);
	INIT_LIST_HEAD(&port->subsystems);
	INIT_LIST_HEAD(&port->subsystems);
	INIT_LIST_HEAD(&port->referrals);
	INIT_LIST_HEAD(&port->referrals);
	port->inline_data_size = -1;	/* < 0 == let the transport choose */


	port->disc_addr.portid = cpu_to_le16(portid);
	port->disc_addr.portid = cpu_to_le16(portid);
	config_group_init_type_name(&port->group, name, &nvmet_port_type);
	config_group_init_type_name(&port->group, name, &nvmet_port_type);
+4 −0
Original line number Original line Diff line number Diff line
@@ -242,6 +242,10 @@ int nvmet_enable_port(struct nvmet_port *port)
		return ret;
		return ret;
	}
	}


	/* If the transport didn't set inline_data_size, then disable it. */
	if (port->inline_data_size < 0)
		port->inline_data_size = 0;

	port->enabled = true;
	port->enabled = true;
	return 0;
	return 0;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -171,7 +171,7 @@ static void nvmet_execute_identify_disc_ctrl(struct nvmet_req *req)
	id->sgls = cpu_to_le32(1 << 0);	/* we always support SGLs */
	id->sgls = cpu_to_le32(1 << 0);	/* we always support SGLs */
	if (ctrl->ops->has_keyed_sgls)
	if (ctrl->ops->has_keyed_sgls)
		id->sgls |= cpu_to_le32(1 << 2);
		id->sgls |= cpu_to_le32(1 << 2);
	if (ctrl->ops->sqe_inline_size)
	if (req->port->inline_data_size)
		id->sgls |= cpu_to_le32(1 << 20);
		id->sgls |= cpu_to_le32(1 << 20);


	strcpy(id->subnqn, ctrl->subsys->subsysnqn);
	strcpy(id->subnqn, ctrl->subsys->subsysnqn);
+1 −1
Original line number Original line Diff line number Diff line
@@ -117,6 +117,7 @@ struct nvmet_port {
	struct list_head		referrals;
	struct list_head		referrals;
	void				*priv;
	void				*priv;
	bool				enabled;
	bool				enabled;
	int				inline_data_size;
};
};


static inline struct nvmet_port *to_nvmet_port(struct config_item *item)
static inline struct nvmet_port *to_nvmet_port(struct config_item *item)
@@ -226,7 +227,6 @@ struct nvmet_req;
struct nvmet_fabrics_ops {
struct nvmet_fabrics_ops {
	struct module *owner;
	struct module *owner;
	unsigned int type;
	unsigned int type;
	unsigned int sqe_inline_size;
	unsigned int msdbd;
	unsigned int msdbd;
	bool has_keyed_sgls : 1;
	bool has_keyed_sgls : 1;
	void (*queue_response)(struct nvmet_req *req);
	void (*queue_response)(struct nvmet_req *req);
Loading