Commit 668847e1 authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

nvme: add max completions limit to I/O polling



nvme_ctrlr_process_io_completions() now takes a second parameter,
max_completions, to let the user limit the number of I/Os completed on
each poll.

If there are many I/Os waiting to be completed, the
nvme_ctrlr_process_io_completions() function could run for a long time
before returning control to the user, so the max_completions parameter
lets the user have more control of latency.

Change-Id: I3173059d94ec1cc5dbb636fc0ffd3dc09f3bfe4b
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 181de7bf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -396,7 +396,7 @@ check_io(struct ns_worker_ctx *ns_ctx)
	} else
#endif
	{
		nvme_ctrlr_process_io_completions(ns_ctx->entry->u.nvme.ctrlr);
		nvme_ctrlr_process_io_completions(ns_ctx->entry->u.nvme.ctrlr, 0);
	}
}

+5 −2
Original line number Diff line number Diff line
@@ -155,12 +155,15 @@ int nvme_ctrlr_cmd_io_raw(struct nvme_controller *ctrlr,
 * This will only process completions for I/O that were submitted on the same thread
 * that this function is called from. This call is also non-blocking, i.e. it only
 * processes completions that are ready at the time of this function call. It does not
 * wait for outstanding commands to finish
 * wait for outstanding commands to finish.
 *
 * \param max_completions Limit the number of completions to be processed in one call, or 0
 * for unlimited.
 *
 * This function is thread safe and can be called at any point after nvme_attach().
 *
 */
void nvme_ctrlr_process_io_completions(struct nvme_controller *ctrlr);
void nvme_ctrlr_process_io_completions(struct nvme_controller *ctrlr, uint32_t max_completions);

/**
 * \brief Send the given admin command to the NVMe controller.
+8 −8
Original line number Diff line number Diff line
@@ -333,7 +333,7 @@ nvme_ctrlr_identify(struct nvme_controller *ctrlr)
	nvme_ctrlr_cmd_identify_controller(ctrlr, &ctrlr->cdata,
					   nvme_completion_poll_cb, &status);
	while (status.done == false) {
		nvme_qpair_process_completions(&ctrlr->adminq);
		nvme_qpair_process_completions(&ctrlr->adminq, 0);
	}
	if (nvme_completion_is_error(&status.cpl)) {
		nvme_printf(ctrlr, "nvme_identify_controller failed!\n");
@@ -369,7 +369,7 @@ nvme_ctrlr_set_num_qpairs(struct nvme_controller *ctrlr)
	nvme_ctrlr_cmd_set_num_queues(ctrlr, max_io_queues,
				      nvme_completion_poll_cb, &status);
	while (status.done == false) {
		nvme_qpair_process_completions(&ctrlr->adminq);
		nvme_qpair_process_completions(&ctrlr->adminq, 0);
	}
	if (nvme_completion_is_error(&status.cpl)) {
		nvme_printf(ctrlr, "nvme_set_num_queues failed!\n");
@@ -412,7 +412,7 @@ nvme_ctrlr_create_qpairs(struct nvme_controller *ctrlr)
		nvme_ctrlr_cmd_create_io_cq(ctrlr, qpair,
					    nvme_completion_poll_cb, &status);
		while (status.done == false) {
			nvme_qpair_process_completions(&ctrlr->adminq);
			nvme_qpair_process_completions(&ctrlr->adminq, 0);
		}
		if (nvme_completion_is_error(&status.cpl)) {
			nvme_printf(ctrlr, "nvme_create_io_cq failed!\n");
@@ -423,7 +423,7 @@ nvme_ctrlr_create_qpairs(struct nvme_controller *ctrlr)
		nvme_ctrlr_cmd_create_io_sq(qpair->ctrlr, qpair,
					    nvme_completion_poll_cb, &status);
		while (status.done == false) {
			nvme_qpair_process_completions(&ctrlr->adminq);
			nvme_qpair_process_completions(&ctrlr->adminq, 0);
		}
		if (nvme_completion_is_error(&status.cpl)) {
			nvme_printf(ctrlr, "nvme_create_io_sq failed!\n");
@@ -566,7 +566,7 @@ nvme_ctrlr_configure_aer(struct nvme_controller *ctrlr)
	nvme_ctrlr_cmd_set_async_event_config(ctrlr, state, nvme_completion_poll_cb, &status);

	while (status.done == false) {
		nvme_qpair_process_completions(&ctrlr->adminq);
		nvme_qpair_process_completions(&ctrlr->adminq, 0);
	}
	if (nvme_completion_is_error(&status.cpl)) {
		nvme_printf(ctrlr, "nvme_ctrlr_cmd_set_async_event_config failed!\n");
@@ -728,17 +728,17 @@ nvme_ctrlr_submit_io_request(struct nvme_controller *ctrlr,
}

void
nvme_ctrlr_process_io_completions(struct nvme_controller *ctrlr)
nvme_ctrlr_process_io_completions(struct nvme_controller *ctrlr, uint32_t max_completions)
{
	nvme_assert(nvme_thread_ioq_index >= 0, ("no ioq_index assigned for thread\n"));
	nvme_qpair_process_completions(&ctrlr->ioq[nvme_thread_ioq_index]);
	nvme_qpair_process_completions(&ctrlr->ioq[nvme_thread_ioq_index], max_completions);
}

void
nvme_ctrlr_process_admin_completions(struct nvme_controller *ctrlr)
{
	nvme_mutex_lock(&ctrlr->ctrlr_lock);
	nvme_qpair_process_completions(&ctrlr->adminq);
	nvme_qpair_process_completions(&ctrlr->adminq, 0);
	nvme_mutex_unlock(&ctrlr->ctrlr_lock);
}

+1 −1
Original line number Diff line number Diff line
@@ -414,7 +414,7 @@ void nvme_qpair_enable(struct nvme_qpair *qpair);
void	nvme_qpair_disable(struct nvme_qpair *qpair);
void	nvme_qpair_submit_tracker(struct nvme_qpair *qpair,
				  struct nvme_tracker *tr);
void	nvme_qpair_process_completions(struct nvme_qpair *qpair);
void	nvme_qpair_process_completions(struct nvme_qpair *qpair, uint32_t max_completions);
void	nvme_qpair_submit_request(struct nvme_qpair *qpair,
				  struct nvme_request *req);
void	nvme_qpair_reset(struct nvme_qpair *qpair);
+1 −1
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ nvme_ns_construct(struct nvme_namespace *ns, uint16_t id,
	nvme_ctrlr_cmd_identify_namespace(ctrlr, id, nsdata,
					  nvme_completion_poll_cb, &status);
	while (status.done == false) {
		nvme_qpair_process_completions(&ctrlr->adminq);
		nvme_qpair_process_completions(&ctrlr->adminq, 0);
	}
	if (nvme_completion_is_error(&status.cpl)) {
		nvme_printf(ctrlr, "nvme_identify_namespace failed\n");
Loading