Commit 49d3a5e4 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Jim Harris
Browse files

nvme: The upper layer controls DNR dynamically for I/O aborts



When I/O error resiliency is supported, most DNR parameters for internal
APIs were cleared. However, for some cases, especially for the reset I/O
command, the upper layer wants the NVMe driver to return I/O errors
immediately without retry even if the upper layer enables I/O error retry.

To satisfy such requirement, add an abort_dnr variable to the spdk_nvme_qpair
structure and internal abort APIs use the abort_dnr variable. A public API
spdk_nvme_qpair_set_abort_dnr() can change the abort_dnr variable dynamically.

The public spdk_nvme_transport_ops structure is not changed to avoid
premature changes.

Signed-off-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: I486a1b3ad8411f9fa261a2bf3a45aea9da292e9c
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/17099


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 0ba9ba5c
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1872,6 +1872,16 @@ int32_t spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair,
 */
spdk_nvme_qp_failure_reason spdk_nvme_qpair_get_failure_reason(struct spdk_nvme_qpair *qpair);

/**
 * Control if DNR is set or not for aborted commands.
 *
 * The default value is false.
 *
 * \param qpair The qpair to set.
 * \param dnr Set the DNR bit to 1 if true or 0 if false for aborted commands.
 */
void spdk_nvme_qpair_set_abort_dnr(struct spdk_nvme_qpair *qpair, bool dnr);

/**
 * Send the given admin command to the NVMe controller.
 *
+2 −2
Original line number Diff line number Diff line
@@ -611,7 +611,7 @@ spdk_nvme_ctrlr_free_io_qpair(struct spdk_nvme_qpair *qpair)
	 * with that qpair, since the callbacks will also be foreign to this process.
	 */
	if (qpair->active_proc == nvme_ctrlr_get_current_process(ctrlr)) {
		nvme_qpair_abort_all_queued_reqs(qpair, 0);
		nvme_qpair_abort_all_queued_reqs(qpair);
	}

	nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
@@ -3819,7 +3819,7 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)
			 * resubmitted while the controller is resetting and subsequent commands
			 * would get queued too.
			 */
			nvme_qpair_abort_queued_reqs(ctrlr->adminq, 0);
			nvme_qpair_abort_queued_reqs(ctrlr->adminq);
			break;
		case NVME_QPAIR_DISCONNECTING:
			assert(ctrlr->adminq->async == true);
+5 −3
Original line number Diff line number Diff line
@@ -439,6 +439,8 @@ struct spdk_nvme_qpair {
	uint8_t					transport_failure_reason: 2;
	uint8_t					last_transport_failure_reason: 2;

	uint8_t					abort_dnr: 1;

	enum spdk_nvme_transport_type		trtype;

	uint32_t				num_outstanding_reqs;
@@ -1200,9 +1202,9 @@ void nvme_qpair_deinit(struct spdk_nvme_qpair *qpair);
void	nvme_qpair_complete_error_reqs(struct spdk_nvme_qpair *qpair);
int	nvme_qpair_submit_request(struct spdk_nvme_qpair *qpair,
				  struct nvme_request *req);
void	nvme_qpair_abort_all_queued_reqs(struct spdk_nvme_qpair *qpair, uint32_t dnr);
void	nvme_qpair_abort_all_queued_reqs(struct spdk_nvme_qpair *qpair);
uint32_t nvme_qpair_abort_queued_reqs_with_cbarg(struct spdk_nvme_qpair *qpair, void *cmd_cb_arg);
void	nvme_qpair_abort_queued_reqs(struct spdk_nvme_qpair *qpair, uint32_t dnr);
void	nvme_qpair_abort_queued_reqs(struct spdk_nvme_qpair *qpair);
void	nvme_qpair_resubmit_requests(struct spdk_nvme_qpair *qpair, uint32_t num_requests);
int	nvme_ctrlr_identify_active_ns(struct spdk_nvme_ctrlr *ctrlr);
void	nvme_ns_set_identify_data(struct spdk_nvme_ns *ns);
@@ -1525,7 +1527,7 @@ void nvme_transport_ctrlr_disconnect_qpair(struct spdk_nvme_ctrlr *ctrlr,
void nvme_transport_ctrlr_disconnect_qpair_done(struct spdk_nvme_qpair *qpair);
int nvme_transport_ctrlr_get_memory_domains(const struct spdk_nvme_ctrlr *ctrlr,
		struct spdk_memory_domain **domains, int array_size);
void nvme_transport_qpair_abort_reqs(struct spdk_nvme_qpair *qpair, uint32_t dnr);
void nvme_transport_qpair_abort_reqs(struct spdk_nvme_qpair *qpair);
int nvme_transport_qpair_reset(struct spdk_nvme_qpair *qpair);
int nvme_transport_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *req);
int32_t nvme_transport_qpair_process_completions(struct spdk_nvme_qpair *qpair,
+17 −11
Original line number Diff line number Diff line
@@ -565,7 +565,7 @@ nvme_qpair_manual_complete_request(struct spdk_nvme_qpair *qpair,
}

void
nvme_qpair_abort_queued_reqs(struct spdk_nvme_qpair *qpair, uint32_t dnr)
nvme_qpair_abort_queued_reqs(struct spdk_nvme_qpair *qpair)
{
	struct nvme_request		*req;
	STAILQ_HEAD(, nvme_request)	tmp;
@@ -580,7 +580,7 @@ nvme_qpair_abort_queued_reqs(struct spdk_nvme_qpair *qpair, uint32_t dnr)
			SPDK_ERRLOG("aborting queued i/o\n");
		}
		nvme_qpair_manual_complete_request(qpair, req, SPDK_NVME_SCT_GENERIC,
						   SPDK_NVME_SC_ABORTED_SQ_DELETION, dnr, true);
						   SPDK_NVME_SC_ABORTED_SQ_DELETION, qpair->abort_dnr, true);
	}
}

@@ -654,8 +654,8 @@ nvme_qpair_check_enabled(struct spdk_nvme_qpair *qpair)
		 */
		if (qpair->ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_PCIE &&
		    !qpair->is_new_qpair) {
			nvme_qpair_abort_all_queued_reqs(qpair, 0);
			nvme_transport_qpair_abort_reqs(qpair, 0);
			nvme_qpair_abort_all_queued_reqs(qpair);
			nvme_transport_qpair_abort_reqs(qpair);
		}

		nvme_qpair_set_state(qpair, NVME_QPAIR_ENABLED);
@@ -760,8 +760,8 @@ spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_
			  nvme_qpair_get_state(qpair) != NVME_QPAIR_DISCONNECTING)) {
		if (qpair->ctrlr->is_removed) {
			nvme_qpair_set_state(qpair, NVME_QPAIR_DESTROYING);
			nvme_qpair_abort_all_queued_reqs(qpair, 0);
			nvme_transport_qpair_abort_reqs(qpair, 0);
			nvme_qpair_abort_all_queued_reqs(qpair);
			nvme_transport_qpair_abort_reqs(qpair);
		}
		return -ENXIO;
	}
@@ -783,7 +783,7 @@ spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_
				STAILQ_REMOVE(&qpair->err_req_head, req, nvme_request, stailq);
				nvme_qpair_manual_complete_request(qpair, req,
								   req->cpl.status.sct,
								   req->cpl.status.sc, 0, true);
								   req->cpl.status.sc, qpair->abort_dnr, true);
			}
		}
	}
@@ -830,6 +830,12 @@ spdk_nvme_qpair_get_failure_reason(struct spdk_nvme_qpair *qpair)
	return qpair->transport_failure_reason;
}

void
spdk_nvme_qpair_set_abort_dnr(struct spdk_nvme_qpair *qpair, bool dnr)
{
	qpair->abort_dnr = dnr ? 1 : 0;
}

int
nvme_qpair_init(struct spdk_nvme_qpair *qpair, uint16_t id,
		struct spdk_nvme_ctrlr *ctrlr,
@@ -896,7 +902,7 @@ nvme_qpair_complete_error_reqs(struct spdk_nvme_qpair *qpair)
		STAILQ_REMOVE_HEAD(&qpair->err_req_head, stailq);
		nvme_qpair_manual_complete_request(qpair, req,
						   req->cpl.status.sct,
						   req->cpl.status.sc, 0, true);
						   req->cpl.status.sc, qpair->abort_dnr, true);
	}
}

@@ -905,7 +911,7 @@ nvme_qpair_deinit(struct spdk_nvme_qpair *qpair)
{
	struct nvme_error_cmd *cmd, *entry;

	nvme_qpair_abort_queued_reqs(qpair, 0);
	nvme_qpair_abort_queued_reqs(qpair);
	_nvme_qpair_complete_abort_queued_reqs(qpair);
	nvme_qpair_complete_error_reqs(qpair);

@@ -1111,10 +1117,10 @@ nvme_qpair_resubmit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *
}

void
nvme_qpair_abort_all_queued_reqs(struct spdk_nvme_qpair *qpair, uint32_t dnr)
nvme_qpair_abort_all_queued_reqs(struct spdk_nvme_qpair *qpair)
{
	nvme_qpair_complete_error_reqs(qpair);
	nvme_qpair_abort_queued_reqs(qpair, dnr);
	nvme_qpair_abort_queued_reqs(qpair);
	_nvme_qpair_complete_abort_queued_reqs(qpair);
	if (nvme_qpair_is_admin_queue(qpair)) {
		nvme_ctrlr_abort_queued_aborts(qpair->ctrlr);
+4 −5
Original line number Diff line number Diff line
@@ -539,7 +539,7 @@ nvme_transport_ctrlr_disconnect_qpair_done(struct spdk_nvme_qpair *qpair)
{
	if (qpair->active_proc == nvme_ctrlr_get_current_process(qpair->ctrlr) ||
	    nvme_qpair_is_admin_queue(qpair)) {
		nvme_qpair_abort_all_queued_reqs(qpair, 0);
		nvme_qpair_abort_all_queued_reqs(qpair);
	}
	nvme_qpair_set_state(qpair, NVME_QPAIR_DISCONNECTED);
}
@@ -559,17 +559,16 @@ nvme_transport_ctrlr_get_memory_domains(const struct spdk_nvme_ctrlr *ctrlr,
}

void
nvme_transport_qpair_abort_reqs(struct spdk_nvme_qpair *qpair, uint32_t dnr)
nvme_transport_qpair_abort_reqs(struct spdk_nvme_qpair *qpair)
{
	const struct spdk_nvme_transport *transport;

	assert(dnr <= 1);
	if (spdk_likely(!nvme_qpair_is_admin_queue(qpair))) {
		qpair->transport->ops.qpair_abort_reqs(qpair, dnr);
		qpair->transport->ops.qpair_abort_reqs(qpair, qpair->abort_dnr);
	} else {
		transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
		assert(transport != NULL);
		transport->ops.qpair_abort_reqs(qpair, dnr);
		transport->ops.qpair_abort_reqs(qpair, qpair->abort_dnr);
	}
}

Loading