Cap the number of retry attempts to a configurable number. This ensures
that if a specific I/O repeatedly times out, we don't retry it indefinitely. The default number of retries will be 4, but is adjusted using hw.nvme.retry_count. Sponsored by: Intel Reviewed by: carl
This commit is contained in:
parent
18a3a60fb4
commit
21ee92ac4f
@ -49,7 +49,8 @@ struct nvme_consumer {
|
||||
struct nvme_consumer nvme_consumer[NVME_MAX_CONSUMERS];
|
||||
#define INVALID_CONSUMER_ID 0xFFFF
|
||||
|
||||
uma_zone_t nvme_request_zone;
|
||||
uma_zone_t nvme_request_zone;
|
||||
int32_t nvme_retry_count;
|
||||
|
||||
MALLOC_DEFINE(M_NVME, "nvme", "nvme(4) memory allocations");
|
||||
|
||||
|
@ -731,6 +731,10 @@ nvme_ctrlr_start(void *ctrlr_arg)
|
||||
struct nvme_controller *ctrlr = ctrlr_arg;
|
||||
int i;
|
||||
|
||||
nvme_qpair_reset(&ctrlr->adminq);
|
||||
for (i = 0; i < ctrlr->num_io_queues; i++)
|
||||
nvme_qpair_reset(&ctrlr->ioq[i]);
|
||||
|
||||
nvme_admin_qpair_enable(&ctrlr->adminq);
|
||||
|
||||
if (nvme_ctrlr_identify(ctrlr) != 0)
|
||||
@ -929,6 +933,9 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
|
||||
timeout_period = max(timeout_period, NVME_MIN_TIMEOUT_PERIOD);
|
||||
ctrlr->timeout_period = timeout_period;
|
||||
|
||||
nvme_retry_count = NVME_DEFAULT_RETRY_COUNT;
|
||||
TUNABLE_INT_FETCH("hw.nvme.retry_count", &nvme_retry_count);
|
||||
|
||||
per_cpu_io_queues = 1;
|
||||
TUNABLE_INT_FETCH("hw.nvme.per_cpu_io_queues", &per_cpu_io_queues);
|
||||
ctrlr->per_cpu_io_queues = per_cpu_io_queues ? TRUE : FALSE;
|
||||
|
@ -104,6 +104,8 @@ MALLOC_DECLARE(M_NVME);
|
||||
#define NVME_MIN_TIMEOUT_PERIOD (5)
|
||||
#define NVME_MAX_TIMEOUT_PERIOD (120)
|
||||
|
||||
#define NVME_DEFAULT_RETRY_COUNT (4)
|
||||
|
||||
/* Maximum log page size to fetch for AERs. */
|
||||
#define NVME_MAX_AER_LOG_SIZE (4096)
|
||||
|
||||
@ -111,7 +113,8 @@ MALLOC_DECLARE(M_NVME);
|
||||
#define CACHE_LINE_SIZE (64)
|
||||
#endif
|
||||
|
||||
extern uma_zone_t nvme_request_zone;
|
||||
extern uma_zone_t nvme_request_zone;
|
||||
extern int32_t nvme_retry_count;
|
||||
|
||||
struct nvme_request {
|
||||
|
||||
@ -122,6 +125,7 @@ struct nvme_request {
|
||||
struct uio *uio;
|
||||
nvme_cb_fn_t cb_fn;
|
||||
void *cb_arg;
|
||||
int32_t retries;
|
||||
STAILQ_ENTRY(nvme_request) stailq;
|
||||
};
|
||||
|
||||
@ -409,6 +413,7 @@ void nvme_qpair_submit_tracker(struct nvme_qpair *qpair,
|
||||
void nvme_qpair_process_completions(struct nvme_qpair *qpair);
|
||||
void nvme_qpair_submit_request(struct nvme_qpair *qpair,
|
||||
struct nvme_request *req);
|
||||
void nvme_qpair_reset(struct nvme_qpair *qpair);
|
||||
|
||||
void nvme_admin_qpair_enable(struct nvme_qpair *qpair);
|
||||
void nvme_admin_qpair_disable(struct nvme_qpair *qpair);
|
||||
|
@ -105,7 +105,8 @@ nvme_qpair_complete_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr,
|
||||
|
||||
req = tr->req;
|
||||
error = nvme_completion_is_error(cpl);
|
||||
retry = error && nvme_completion_is_retry(cpl);
|
||||
retry = error && nvme_completion_is_retry(cpl) &&
|
||||
req->retries < nvme_retry_count;
|
||||
|
||||
if (error && print_on_error) {
|
||||
nvme_dump_completion(cpl);
|
||||
@ -122,9 +123,10 @@ nvme_qpair_complete_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr,
|
||||
mtx_lock(&qpair->lock);
|
||||
callout_stop(&tr->timer);
|
||||
|
||||
if (retry)
|
||||
if (retry) {
|
||||
req->retries++;
|
||||
nvme_qpair_submit_tracker(qpair, tr);
|
||||
else {
|
||||
} else {
|
||||
if (req->payload_size > 0 || req->uio != NULL)
|
||||
bus_dmamap_unload(qpair->dma_tag,
|
||||
tr->payload_dma_map);
|
||||
@ -568,6 +570,12 @@ nvme_qpair_enable(struct nvme_qpair *qpair)
|
||||
{
|
||||
|
||||
qpair->is_enabled = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nvme_qpair_reset(struct nvme_qpair *qpair)
|
||||
{
|
||||
|
||||
qpair->sq_head = qpair->sq_tail = qpair->cq_head = 0;
|
||||
|
||||
/*
|
||||
@ -597,19 +605,25 @@ nvme_io_qpair_enable(struct nvme_qpair *qpair)
|
||||
{
|
||||
STAILQ_HEAD(, nvme_request) temp;
|
||||
struct nvme_tracker *tr;
|
||||
struct nvme_tracker *tr_temp;
|
||||
struct nvme_request *req;
|
||||
|
||||
/*
|
||||
* Manually abort each outstanding I/O. This normally results in a
|
||||
* retry, unless the retry count on the associated request has
|
||||
* reached its limit.
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(tr, &qpair->outstanding_tr, tailq, tr_temp) {
|
||||
device_printf(qpair->ctrlr->dev,
|
||||
"aborting outstanding i/o\n");
|
||||
nvme_qpair_manual_complete_tracker(qpair, tr, NVME_SCT_GENERIC,
|
||||
NVME_SC_ABORTED_BY_REQUEST, TRUE);
|
||||
}
|
||||
|
||||
mtx_lock(&qpair->lock);
|
||||
|
||||
nvme_qpair_enable(qpair);
|
||||
|
||||
TAILQ_FOREACH(tr, &qpair->outstanding_tr, tailq) {
|
||||
device_printf(qpair->ctrlr->dev,
|
||||
"resubmitting outstanding i/o\n");
|
||||
nvme_dump_command(&tr->req->cmd);
|
||||
nvme_qpair_submit_tracker(qpair, tr);
|
||||
}
|
||||
|
||||
STAILQ_INIT(&temp);
|
||||
STAILQ_SWAP(&qpair->queued_req, &temp, nvme_request);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user