Skip to content

Commit

Permalink
Merge tag 'nvme-6.10-2024-05-14' of git://git.infradead.org/nvme into…
Browse files Browse the repository at this point in the history
… block-6.10

Pull NVMe updates and fixes from Keith:

"nvme updates for Linux 6.10

 - Fabrics connection retries (Daniel, Hannes)
 - Fabrics logging enhancements (Tokunori)
 - RDMA delete optimization (Sagi)"

* tag 'nvme-6.10-2024-05-14' of git://git.infradead.org/nvme:
  nvme-rdma, nvme-tcp: include max reconnects for reconnect logging
  nvmet-rdma: Avoid o(n^2) loop in delete_ctrl
  nvme: do not retry authentication failures
  nvme-fabrics: short-circuit reconnect retries
  nvme: return kernel error codes for admin queue connect
  nvmet: return DHCHAP status codes from nvmet_setup_auth()
  nvmet: lock config semaphore when accessing DH-HMAC-CHAP key
  • Loading branch information
axboe committed May 14, 2024
2 parents e56d4b6 + 54a76c8 commit 803fbb9
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 111 deletions.
6 changes: 3 additions & 3 deletions drivers/nvme/host/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ static void nvme_queue_auth_work(struct work_struct *work)
NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE);
if (ret) {
chap->status = ret;
chap->error = -ECONNREFUSED;
chap->error = -EKEYREJECTED;
return;
}

Expand Down Expand Up @@ -797,7 +797,7 @@ static void nvme_queue_auth_work(struct work_struct *work)
NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1);
if (ret) {
chap->status = ret;
chap->error = -ECONNREFUSED;
chap->error = -EKEYREJECTED;
return;
}

Expand All @@ -818,7 +818,7 @@ static void nvme_queue_auth_work(struct work_struct *work)
ret = nvme_auth_process_dhchap_success1(ctrl, chap);
if (ret) {
/* Controller authentication failed */
chap->error = -ECONNREFUSED;
chap->error = -EKEYREJECTED;
goto fail2;
}

Expand Down
6 changes: 3 additions & 3 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,14 +383,14 @@ static inline enum nvme_disposition nvme_decide_disposition(struct request *req)
if (likely(nvme_req(req)->status == 0))
return COMPLETE;

if ((nvme_req(req)->status & 0x7ff) == NVME_SC_AUTH_REQUIRED)
return AUTHENTICATE;

if (blk_noretry_request(req) ||
(nvme_req(req)->status & NVME_SC_DNR) ||
nvme_req(req)->retries >= nvme_max_retries)
return COMPLETE;

if ((nvme_req(req)->status & 0x7ff) == NVME_SC_AUTH_REQUIRED)
return AUTHENTICATE;

if (req->cmd_flags & REQ_NVME_MPATH) {
if (nvme_is_path_error(nvme_req(req)->status) ||
blk_queue_dying(req->q))
Expand Down
51 changes: 32 additions & 19 deletions drivers/nvme/host/fabrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,6 @@ static void nvmf_connect_cmd_prep(struct nvme_ctrl *ctrl, u16 qid,
* fabrics-protocol connection of the NVMe Admin queue between the
* host system device and the allocated NVMe controller on the
* target system via a NVMe Fabrics "Connect" command.
*
* Return:
* 0: success
* > 0: NVMe error status code
* < 0: Linux errno error code
*
*/
int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
{
Expand Down Expand Up @@ -467,22 +461,22 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
if (result & NVME_CONNECT_AUTHREQ_ASCR) {
dev_warn(ctrl->device,
"qid 0: secure concatenation is not supported\n");
ret = NVME_SC_AUTH_REQUIRED;
ret = -EOPNOTSUPP;
goto out_free_data;
}
/* Authentication required */
ret = nvme_auth_negotiate(ctrl, 0);
if (ret) {
dev_warn(ctrl->device,
"qid 0: authentication setup failed\n");
ret = NVME_SC_AUTH_REQUIRED;
goto out_free_data;
}
ret = nvme_auth_wait(ctrl, 0);
if (ret)
if (ret) {
dev_warn(ctrl->device,
"qid 0: authentication failed\n");
else
"qid 0: authentication failed, error %d\n",
ret);
} else
dev_info(ctrl->device,
"qid 0: authenticated\n");
}
Expand Down Expand Up @@ -542,20 +536,21 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
if (result & NVME_CONNECT_AUTHREQ_ASCR) {
dev_warn(ctrl->device,
"qid 0: secure concatenation is not supported\n");
ret = NVME_SC_AUTH_REQUIRED;
ret = -EOPNOTSUPP;
goto out_free_data;
}
/* Authentication required */
ret = nvme_auth_negotiate(ctrl, qid);
if (ret) {
dev_warn(ctrl->device,
"qid %d: authentication setup failed\n", qid);
ret = NVME_SC_AUTH_REQUIRED;
} else {
ret = nvme_auth_wait(ctrl, qid);
if (ret)
dev_warn(ctrl->device,
"qid %u: authentication failed\n", qid);
goto out_free_data;
}
ret = nvme_auth_wait(ctrl, qid);
if (ret) {
dev_warn(ctrl->device,
"qid %u: authentication failed, error %d\n",
qid, ret);
}
}
out_free_data:
Expand All @@ -564,8 +559,26 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
}
EXPORT_SYMBOL_GPL(nvmf_connect_io_queue);

bool nvmf_should_reconnect(struct nvme_ctrl *ctrl)
/*
* Evaluate the status information returned by the transport in order to decided
* if a reconnect attempt should be scheduled.
*
* Do not retry when:
*
* - the DNR bit is set and the specification states no further connect
* attempts with the same set of paramenters should be attempted.
*
* - when the authentication attempt fails, because the key was invalid.
* This error code is set on the host side.
*/
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl, int status)
{
if (status > 0 && (status & NVME_SC_DNR))
return false;

if (status == -EKEYREJECTED)
return false;

if (ctrl->opts->max_reconnects == -1 ||
ctrl->nr_reconnects < ctrl->opts->max_reconnects)
return true;
Expand Down
2 changes: 1 addition & 1 deletion drivers/nvme/host/fabrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ int nvmf_register_transport(struct nvmf_transport_ops *ops);
void nvmf_unregister_transport(struct nvmf_transport_ops *ops);
void nvmf_free_options(struct nvmf_ctrl_options *opts);
int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size);
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl);
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl, int status);
bool nvmf_ip_options_match(struct nvme_ctrl *ctrl,
struct nvmf_ctrl_options *opts);
void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues,
Expand Down
4 changes: 1 addition & 3 deletions drivers/nvme/host/fc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3310,12 +3310,10 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
ctrl->cnum, status);
if (status > 0 && (status & NVME_SC_DNR))
recon = false;
} else if (time_after_eq(jiffies, rport->dev_loss_end))
recon = false;

if (recon && nvmf_should_reconnect(&ctrl->ctrl)) {
if (recon && nvmf_should_reconnect(&ctrl->ctrl, status)) {
if (portptr->port_state == FC_OBJSTATE_ONLINE)
dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: Reconnect attempt in %ld "
Expand Down
2 changes: 1 addition & 1 deletion drivers/nvme/host/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,7 @@ static inline int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int qid)
}
static inline int nvme_auth_wait(struct nvme_ctrl *ctrl, int qid)
{
return NVME_SC_AUTH_REQUIRED;
return -EPROTONOSUPPORT;
}
static inline void nvme_auth_free(struct nvme_ctrl *ctrl) {};
#endif
Expand Down
23 changes: 14 additions & 9 deletions drivers/nvme/host/rdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,8 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
kfree(ctrl);
}

static void nvme_rdma_reconnect_or_remove(struct nvme_rdma_ctrl *ctrl)
static void nvme_rdma_reconnect_or_remove(struct nvme_rdma_ctrl *ctrl,
int status)
{
enum nvme_ctrl_state state = nvme_ctrl_state(&ctrl->ctrl);

Expand All @@ -992,7 +993,7 @@ static void nvme_rdma_reconnect_or_remove(struct nvme_rdma_ctrl *ctrl)
return;
}

if (nvmf_should_reconnect(&ctrl->ctrl)) {
if (nvmf_should_reconnect(&ctrl->ctrl, status)) {
dev_info(ctrl->ctrl.device, "Reconnecting in %d seconds...\n",
ctrl->ctrl.opts->reconnect_delay);
queue_delayed_work(nvme_wq, &ctrl->reconnect_work,
Expand Down Expand Up @@ -1104,10 +1105,12 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
{
struct nvme_rdma_ctrl *ctrl = container_of(to_delayed_work(work),
struct nvme_rdma_ctrl, reconnect_work);
int ret;

++ctrl->ctrl.nr_reconnects;

if (nvme_rdma_setup_ctrl(ctrl, false))
ret = nvme_rdma_setup_ctrl(ctrl, false);
if (ret)
goto requeue;

dev_info(ctrl->ctrl.device, "Successfully reconnected (%d attempts)\n",
Expand All @@ -1118,9 +1121,9 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
return;

requeue:
dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n",
ctrl->ctrl.nr_reconnects);
nvme_rdma_reconnect_or_remove(ctrl);
dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d/%d\n",
ctrl->ctrl.nr_reconnects, ctrl->ctrl.opts->max_reconnects);
nvme_rdma_reconnect_or_remove(ctrl, ret);
}

static void nvme_rdma_error_recovery_work(struct work_struct *work)
Expand All @@ -1145,7 +1148,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
return;
}

nvme_rdma_reconnect_or_remove(ctrl);
nvme_rdma_reconnect_or_remove(ctrl, 0);
}

static void nvme_rdma_error_recovery(struct nvme_rdma_ctrl *ctrl)
Expand Down Expand Up @@ -2169,6 +2172,7 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
{
struct nvme_rdma_ctrl *ctrl =
container_of(work, struct nvme_rdma_ctrl, ctrl.reset_work);
int ret;

nvme_stop_ctrl(&ctrl->ctrl);
nvme_rdma_shutdown_ctrl(ctrl, false);
Expand All @@ -2179,14 +2183,15 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
return;
}

if (nvme_rdma_setup_ctrl(ctrl, false))
ret = nvme_rdma_setup_ctrl(ctrl, false);
if (ret)
goto out_fail;

return;

out_fail:
++ctrl->ctrl.nr_reconnects;
nvme_rdma_reconnect_or_remove(ctrl);
nvme_rdma_reconnect_or_remove(ctrl, ret);
}

static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
Expand Down
30 changes: 18 additions & 12 deletions drivers/nvme/host/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2161,7 +2161,8 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
nvme_tcp_destroy_io_queues(ctrl, remove);
}

static void nvme_tcp_reconnect_or_remove(struct nvme_ctrl *ctrl)
static void nvme_tcp_reconnect_or_remove(struct nvme_ctrl *ctrl,
int status)
{
enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);

Expand All @@ -2171,13 +2172,14 @@ static void nvme_tcp_reconnect_or_remove(struct nvme_ctrl *ctrl)
return;
}

if (nvmf_should_reconnect(ctrl)) {
if (nvmf_should_reconnect(ctrl, status)) {
dev_info(ctrl->device, "Reconnecting in %d seconds...\n",
ctrl->opts->reconnect_delay);
queue_delayed_work(nvme_wq, &to_tcp_ctrl(ctrl)->connect_work,
ctrl->opts->reconnect_delay * HZ);
} else {
dev_info(ctrl->device, "Removing controller...\n");
dev_info(ctrl->device, "Removing controller (%d)...\n",
status);
nvme_delete_ctrl(ctrl);
}
}
Expand Down Expand Up @@ -2258,23 +2260,25 @@ static void nvme_tcp_reconnect_ctrl_work(struct work_struct *work)
struct nvme_tcp_ctrl *tcp_ctrl = container_of(to_delayed_work(work),
struct nvme_tcp_ctrl, connect_work);
struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl;
int ret;

++ctrl->nr_reconnects;

if (nvme_tcp_setup_ctrl(ctrl, false))
ret = nvme_tcp_setup_ctrl(ctrl, false);
if (ret)
goto requeue;

dev_info(ctrl->device, "Successfully reconnected (%d attempt)\n",
ctrl->nr_reconnects);
dev_info(ctrl->device, "Successfully reconnected (attempt %d/%d)\n",
ctrl->nr_reconnects, ctrl->opts->max_reconnects);

ctrl->nr_reconnects = 0;

return;

requeue:
dev_info(ctrl->device, "Failed reconnect attempt %d\n",
ctrl->nr_reconnects);
nvme_tcp_reconnect_or_remove(ctrl);
dev_info(ctrl->device, "Failed reconnect attempt %d/%d\n",
ctrl->nr_reconnects, ctrl->opts->max_reconnects);
nvme_tcp_reconnect_or_remove(ctrl, ret);
}

static void nvme_tcp_error_recovery_work(struct work_struct *work)
Expand All @@ -2301,7 +2305,7 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work)
return;
}

nvme_tcp_reconnect_or_remove(ctrl);
nvme_tcp_reconnect_or_remove(ctrl, 0);
}

static void nvme_tcp_teardown_ctrl(struct nvme_ctrl *ctrl, bool shutdown)
Expand All @@ -2321,6 +2325,7 @@ static void nvme_reset_ctrl_work(struct work_struct *work)
{
struct nvme_ctrl *ctrl =
container_of(work, struct nvme_ctrl, reset_work);
int ret;

nvme_stop_ctrl(ctrl);
nvme_tcp_teardown_ctrl(ctrl, false);
Expand All @@ -2334,14 +2339,15 @@ static void nvme_reset_ctrl_work(struct work_struct *work)
return;
}

if (nvme_tcp_setup_ctrl(ctrl, false))
ret = nvme_tcp_setup_ctrl(ctrl, false);
if (ret)
goto out_fail;

return;

out_fail:
++ctrl->nr_reconnects;
nvme_tcp_reconnect_or_remove(ctrl);
nvme_tcp_reconnect_or_remove(ctrl, ret);
}

static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl)
Expand Down
Loading

0 comments on commit 803fbb9

Please sign in to comment.