Commit c7feb85d authored by Haoqian He's avatar Haoqian He Committed by Tomasz Zawadzki
Browse files

nvmf: set max discard size and max write_zeroes size



For Linux kernel version >= 5.13, when host connects the admin
queue successfully, it will call nvme_init_non_mdts_limits() to
post a NVME_ID_CNS_CS_CTRL identify cmd and init max discard size
with dmrl, dmrsl and max write_zeroes size with wzsl in response.

So we add the NVME_ID_CNS_CS_CTRL identify cmd handler in the nvmf
target side and add two new parameters to RPC nvmf_create_subsystem.

Change-Id: Ib72d6caa34fced68d63df9c01760a58effa5ca34
Signed-off-by: default avatarHaoqian He <haoqian.he@smartx.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/19632


Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent f3244a4f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -31,6 +31,11 @@ A new transport option `rdma_max_cq_size` was added to limit indefinite growth o

Added SPDK commandline parameter --no-huge, which enables SPDK to run without hugepages.

### nvmf

Added `max_discard_size_kib` and `max_write_zeroes_size_kib` to `nvmf_create_subsystem` to set the
maximum discard size and maximum write_zeroes size.

## v23.09

### accel
+13 −11
Original line number Diff line number Diff line
@@ -8050,7 +8050,7 @@ Construct an NVMe over Fabrics target subsystem.
#### Parameters

Name                       | Optional | Type        | Description
----------------------- | -------- | ----------- | -----------
-------------------------- | -------- | ----------- | -----------
nqn                        | Required | string      | Subsystem NQN
tgt_name                   | Optional | string      | Parent NVMe-oF target name.
serial_number              | Optional | string      | Serial number of virtual controller
@@ -8060,6 +8060,8 @@ allow_any_host | Optional | boolean | Allow any host (`true`) or en
ana_reporting              | Optional | boolean     | Enable ANA reporting feature (default: `false`).
min_cntlid                 | Optional | number      | Minimum controller ID. Default: 1
max_cntlid                 | Optional | number      | Maximum controller ID. Default: 0xffef
max_discard_size_kib       | Optional | number      | Maximum discard size (Kib). Default: 0
max_write_zeroes_size_kib  | Optional | number      | Maximum write_zeroes size (Kib). Default: 0

#### Example

+23 −0
Original line number Diff line number Diff line
@@ -2960,6 +2960,29 @@ struct spdk_nvme_ns_data {
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_ns_data) == 4096, "Incorrect size");

struct spdk_nvme_nvm_ctrlr_data {
	/* verify size limit */
	uint8_t			vsl;

	/* write zeroes size limit */
	uint8_t			wzsl;

	/* write uncorrectable size limit */
	uint8_t			wusl;

	/* dataset management ranges limit */
	uint8_t			dmrl;

	/* dataset management range size limit */
	uint32_t		dmrsl;

	/* dataset management size limit */
	uint64_t		dmsl;

	uint8_t			rsvd16[4080];
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_nvm_ctrlr_data) == 4096, "Incorrect size");

struct spdk_nvme_zns_ns_data {
	/** zone operation characteristics */
	struct {
+27 −0
Original line number Diff line number Diff line
@@ -2904,6 +2904,31 @@ spdk_nvmf_ns_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

static int
nvmf_ctrlr_identify_iocs_nvm(struct spdk_nvmf_ctrlr *ctrlr,
			     struct spdk_nvme_cmd *cmd,
			     struct spdk_nvme_cpl *rsp,
			     struct spdk_nvme_nvm_ctrlr_data *cdata_nvm)
{
	/* The unit of max_write_zeroes_size_kib is KiB.
	 * The unit of wzsl is the minimum memory page size(2 ^ (12 + CAP.MPSMIN) bytes)
	 * and is reported as a power of two (2^n).
	 */
	cdata_nvm->wzsl = spdk_u64log2(ctrlr->subsys->max_write_zeroes_size_kib >>
				       (2 + ctrlr->vcprop.cap.bits.mpsmin));

	/* The unit of max_discard_size_kib is KiB.
	 * The dmrsl indicates the maximum number of logical blocks for
	 * dataset management command.
	 */
	cdata_nvm->dmrsl = ctrlr->subsys->max_discard_size_kib << 1;
	cdata_nvm->dmrl = 1;

	rsp->status.sct = SPDK_NVME_SCT_GENERIC;
	rsp->status.sc = SPDK_NVME_SC_SUCCESS;
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

static int
nvmf_ctrlr_identify_iocs_zns(struct spdk_nvmf_ctrlr *ctrlr,
			     struct spdk_nvme_cmd *cmd,
@@ -2934,6 +2959,8 @@ spdk_nvmf_ctrlr_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
	memset(cdata, 0, cdata_size);

	switch (csi) {
	case SPDK_NVME_CSI_NVM:
		return nvmf_ctrlr_identify_iocs_nvm(ctrlr, cmd, rsp, cdata);
	case SPDK_NVME_CSI_ZNS:
		return nvmf_ctrlr_identify_iocs_zns(ctrlr, cmd, rsp, cdata);
	default:
+16 −0
Original line number Diff line number Diff line
@@ -473,11 +473,19 @@ nvmf_bdev_ctrlr_write_zeroes_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *
	uint64_t bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
	struct spdk_nvme_cpl *rsp = &req->rsp->nvme_cpl;
	uint64_t max_write_zeroes_size = req->qpair->ctrlr->subsys->max_write_zeroes_size_kib;
	uint64_t start_lba;
	uint64_t num_blocks;
	int rc;

	nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks);
	if (spdk_unlikely(max_write_zeroes_size > 0 &&
			  num_blocks > (max_write_zeroes_size << 10) / spdk_bdev_get_block_size(bdev))) {
		SPDK_ERRLOG("invalid write zeroes size, should not exceed %" PRIu64 "Kib\n", max_write_zeroes_size);
		rsp->status.sct = SPDK_NVME_SCT_GENERIC;
		rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) {
		SPDK_ERRLOG("end of media\n");
@@ -590,6 +598,8 @@ nvmf_bdev_ctrlr_unmap(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
	uint16_t nr, i;
	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
	struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
	uint64_t max_discard_size = req->qpair->ctrlr->subsys->max_discard_size_kib;
	uint32_t block_size = spdk_bdev_get_block_size(bdev);
	struct spdk_iov_xfer ix;
	uint64_t lba;
	uint32_t lba_count;
@@ -629,6 +639,12 @@ nvmf_bdev_ctrlr_unmap(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,

		lba = dsm_range.starting_lba;
		lba_count = dsm_range.length;
		if (max_discard_size > 0 && lba_count > (max_discard_size << 10) / block_size) {
			SPDK_ERRLOG("invalid unmap size, should not exceed %" PRIu64 "Kib\n", max_discard_size);
			response->status.sct = SPDK_NVME_SCT_GENERIC;
			response->status.sc = SPDK_NVME_SC_INVALID_FIELD;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		unmap_ctx->count++;

Loading