Skip to content

Commit 108d696

Browse files
committed
mi: Introduce a helper for response status, unify values with ioctls
Currently, every admin command function has a similar pattern for catching an error from one of: - the MI transport; or - the admin cdw0 field, sometimes populated to a result pointer This change adds a helper for that pattern. Then, instead of using cdw0 for the return value, we should be using cdw3 instead, as cdw0 is command-specific, and may not always indicate an error. We can then return the proper status type & status, in the same way that the ioctl commands do. This goes part way to fixing #456, but we still have an issue where the MI return values may alias the cdw3 return values. Signed-off-by: Jeremy Kerr <[email protected]>
1 parent 901bd0a commit 108d696

1 file changed

Lines changed: 68 additions & 59 deletions

File tree

src/nvme/mi.c

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,53 @@ static void nvme_mi_admin_init_resp(struct nvme_mi_resp *resp,
295295
resp->hdr_len = sizeof(*hdr);
296296
}
297297

298+
static int nvme_mi_admin_parse_status(struct nvme_mi_resp *resp, __u32 *result)
299+
{
300+
struct nvme_mi_admin_resp_hdr *admin_hdr;
301+
struct nvme_mi_msg_resp *resp_hdr;
302+
__u32 nvme_status;
303+
__u32 nvme_result;
304+
305+
/* we have a few different sources of "result" here: the status header
306+
* in the MI response, the cdw3 status field, and (command specific)
307+
* return values in cdw0. The latter is returned in the result pointer,
308+
* the former two generate return values here
309+
*/
310+
311+
if (resp->hdr_len < sizeof(*resp_hdr)) {
312+
errno = -EPROTO;
313+
return -1;
314+
}
315+
resp_hdr = (struct nvme_mi_msg_resp *)resp->hdr;
316+
317+
/* If we have a MI error, we can't be sure there's an admin header
318+
* following; return just the MI status
319+
*
320+
* TODO: this may alias the cdw3 result values, see
321+
* https://github.com/linux-nvme/libnvme/issues/456
322+
*/
323+
if (resp_hdr->status)
324+
return resp_hdr->status;
325+
326+
/* We shouldn't hit this, as we'd have an error reported earlier.
327+
* However, for pointer safety, ensure we have a full admin header
328+
*/
329+
if (resp->hdr_len < sizeof(*admin_hdr)) {
330+
errno = EPROTO;
331+
return -1;
332+
}
333+
334+
admin_hdr = (struct nvme_mi_admin_resp_hdr *)resp->hdr;
335+
nvme_result = le32_to_cpu(admin_hdr->cdw0);
336+
nvme_status = le32_to_cpu(admin_hdr->cdw3) >> 16;
337+
338+
/* the result pointer, optionally stored if the caller needs it */
339+
if (result)
340+
*result = nvme_result;
341+
342+
return nvme_status;
343+
}
344+
298345
int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl,
299346
struct nvme_mi_admin_req_hdr *admin_req,
300347
size_t req_data_size,
@@ -414,11 +461,9 @@ int nvme_mi_admin_identify_partial(nvme_mi_ctrl_t ctrl,
414461
if (rc)
415462
return rc;
416463

417-
if (resp_hdr.status)
418-
return resp_hdr.status;
419-
420-
if (args->result)
421-
*args->result = le32_to_cpu(resp_hdr.cdw0);
464+
rc = nvme_mi_admin_parse_status(&resp, args->result);
465+
if (rc)
466+
return rc;
422467

423468
/* callers will expect a full response; if the data buffer isn't
424469
* fully valid, return an error */
@@ -489,12 +534,11 @@ static int __nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl,
489534
if (rc)
490535
return rc;
491536

492-
if (resp_hdr.status)
493-
return resp_hdr.status;
494-
495-
*lenp = resp.data_len;
537+
rc = nvme_mi_admin_parse_status(&resp, args->result);
538+
if (!rc)
539+
*lenp = resp.data_len;
496540

497-
return 0;
541+
return rc;
498542
}
499543

500544
int nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, struct nvme_get_log_args *args)
@@ -580,13 +624,7 @@ int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl,
580624
if (rc)
581625
return rc;
582626

583-
if (resp_hdr.status)
584-
return resp_hdr.status;
585-
586-
if (args->result)
587-
*args->result = le32_to_cpu(resp_hdr.cdw0);
588-
589-
return 0;
627+
return nvme_mi_admin_parse_status(&resp, args->result);
590628
}
591629

592630
int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl,
@@ -632,11 +670,9 @@ int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl,
632670
if (rc)
633671
return rc;
634672

635-
if (resp_hdr.status)
636-
return resp_hdr.status;
637-
638-
if (args->result)
639-
*args->result = resp_hdr.cdw0;
673+
rc = nvme_mi_admin_parse_status(&resp, args->result);
674+
if (rc)
675+
return rc;
640676

641677
args->data_len = resp.data_len;
642678

@@ -673,11 +709,9 @@ int nvme_mi_admin_get_features(nvme_mi_ctrl_t ctrl,
673709
if (rc)
674710
return rc;
675711

676-
if (resp_hdr.status)
677-
return resp_hdr.status;
678-
679-
if (args->result)
680-
*args->result = le32_to_cpu(resp_hdr.cdw0);
712+
rc = nvme_mi_admin_parse_status(&resp, args->result);
713+
if (rc)
714+
return rc;
681715

682716
args->data_len = resp.data_len;
683717

@@ -719,11 +753,10 @@ int nvme_mi_admin_set_features(nvme_mi_ctrl_t ctrl,
719753
if (rc)
720754
return rc;
721755

722-
if (resp_hdr.status)
723-
return resp_hdr.status;
756+
rc = nvme_mi_admin_parse_status(&resp, args->result);
757+
if (rc)
758+
return rc;
724759

725-
if (args->result)
726-
*args->result = le32_to_cpu(resp_hdr.cdw0);
727760
args->data_len = resp.data_len;
728761

729762
return 0;
@@ -762,13 +795,7 @@ int nvme_mi_admin_ns_mgmt(nvme_mi_ctrl_t ctrl,
762795
if (rc)
763796
return rc;
764797

765-
if (resp_hdr.status)
766-
return resp_hdr.status;
767-
768-
if (args->result)
769-
*args->result = le32_to_cpu(resp_hdr.cdw0);
770-
771-
return 0;
798+
return nvme_mi_admin_parse_status(&resp, args->result);
772799
}
773800

774801
int nvme_mi_admin_ns_attach(nvme_mi_ctrl_t ctrl,
@@ -801,13 +828,7 @@ int nvme_mi_admin_ns_attach(nvme_mi_ctrl_t ctrl,
801828
if (rc)
802829
return rc;
803830

804-
if (resp_hdr.status)
805-
return resp_hdr.status;
806-
807-
if (args->result)
808-
*args->result = le32_to_cpu(resp_hdr.cdw0);
809-
810-
return 0;
831+
return nvme_mi_admin_parse_status(&resp, args->result);
811832
}
812833

813834
int nvme_mi_admin_format_nvm(nvme_mi_ctrl_t ctrl,
@@ -841,13 +862,7 @@ int nvme_mi_admin_format_nvm(nvme_mi_ctrl_t ctrl,
841862
if (rc)
842863
return rc;
843864

844-
if (resp_hdr.status)
845-
return resp_hdr.status;
846-
847-
if (args->result)
848-
*args->result = le32_to_cpu(resp_hdr.cdw0);
849-
850-
return 0;
865+
return nvme_mi_admin_parse_status(&resp, args->result);
851866
}
852867

853868
int nvme_mi_admin_sanitize_nvm(nvme_mi_ctrl_t ctrl,
@@ -880,13 +895,7 @@ int nvme_mi_admin_sanitize_nvm(nvme_mi_ctrl_t ctrl,
880895
if (rc)
881896
return rc;
882897

883-
if (resp_hdr.status)
884-
return resp_hdr.status;
885-
886-
if (args->result)
887-
*args->result = le32_to_cpu(resp_hdr.cdw0);
888-
889-
return 0;
898+
return nvme_mi_admin_parse_status(&resp, args->result);
890899
}
891900

892901
static int nvme_mi_read_data(nvme_mi_ep_t ep, __u32 cdw0,

0 commit comments

Comments
 (0)