Remove the NVME_IDENTIFY_CONTROLLER and NVME_IDENTIFY_NAMESPACE IOCTLs and replace
them with the NVMe passthrough equivalent. Sponsored by: Intel
This commit is contained in:
parent
7c3f19d7bb
commit
5076698e19
@ -210,6 +210,53 @@ ns_get_sector_size(struct nvme_namespace_data *nsdata)
|
||||
return (1 << nsdata->lbaf[0].lbads);
|
||||
}
|
||||
|
||||
static void
|
||||
read_controller_data(int fd, struct nvme_controller_data *cdata)
|
||||
{
|
||||
struct nvme_pt_command pt;
|
||||
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
pt.cmd.opc = NVME_OPC_IDENTIFY;
|
||||
pt.cmd.cdw10 = 1;
|
||||
pt.buf = cdata;
|
||||
pt.len = sizeof(*cdata);
|
||||
pt.is_read = 1;
|
||||
|
||||
if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) {
|
||||
printf("Identify request failed. errno=%d (%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
|
||||
if (nvme_completion_is_error(&pt.cpl)) {
|
||||
printf("Passthrough command returned error.\n");
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata)
|
||||
{
|
||||
struct nvme_pt_command pt;
|
||||
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
pt.cmd.opc = NVME_OPC_IDENTIFY;
|
||||
pt.cmd.nsid = nsid;
|
||||
pt.buf = nsdata;
|
||||
pt.len = sizeof(*nsdata);
|
||||
pt.is_read = 1;
|
||||
|
||||
if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) {
|
||||
printf("Identify request failed. errno=%d (%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
|
||||
if (nvme_completion_is_error(&pt.cpl)) {
|
||||
printf("Passthrough command returned error.\n");
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
devlist(int argc, char *argv[])
|
||||
@ -251,33 +298,12 @@ devlist(int argc, char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(fd, NVME_IDENTIFY_CONTROLLER, &cdata) < 0) {
|
||||
printf("Identify request to %s failed. errno=%d (%s)\n",
|
||||
path, errno, strerror(errno));
|
||||
exit_code = EX_IOERR;
|
||||
continue;
|
||||
}
|
||||
|
||||
read_controller_data(fd, &cdata);
|
||||
printf("%6s: %s\n", name, cdata.mn);
|
||||
|
||||
for (i = 0; i < cdata.nn; i++) {
|
||||
sprintf(name, "nvme%dns%d", ctrlr, i+1);
|
||||
sprintf(path, "/dev/%s", name);
|
||||
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
printf("Could not open %s. errno=%d (%s)\n",
|
||||
path, errno, strerror(errno));
|
||||
exit_code = EX_NOPERM;
|
||||
continue;
|
||||
}
|
||||
if (ioctl(fd, NVME_IDENTIFY_NAMESPACE, &nsdata) < 0) {
|
||||
printf("Identify request to %s failed. "
|
||||
"errno=%d (%s)\n", path, errno,
|
||||
strerror(errno));
|
||||
exit_code = EX_IOERR;
|
||||
continue;
|
||||
}
|
||||
read_namespace_data(fd, i+1, &nsdata);
|
||||
printf(" %10s (%lldGB)\n",
|
||||
name,
|
||||
nsdata.nsze *
|
||||
@ -329,11 +355,7 @@ identify_ctrlr(int argc, char *argv[])
|
||||
exit(EX_NOPERM);
|
||||
}
|
||||
|
||||
if (ioctl(fd, NVME_IDENTIFY_CONTROLLER, &cdata) < 0) {
|
||||
printf("Identify request to %s failed. errno=%d (%s)\n", path,
|
||||
errno, strerror(errno));
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
read_controller_data(fd, &cdata);
|
||||
|
||||
if (hexflag == 1) {
|
||||
if (verboseflag == 1)
|
||||
@ -360,7 +382,8 @@ identify_ns(int argc, char *argv[])
|
||||
struct nvme_namespace_data nsdata;
|
||||
struct stat devstat;
|
||||
char path[64];
|
||||
int ch, fd, hexflag = 0, hexlength;
|
||||
char *nsloc;
|
||||
int ch, fd, hexflag = 0, hexlength, nsid;
|
||||
int verboseflag = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "vx")) != -1) {
|
||||
@ -376,8 +399,41 @@ identify_ns(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the specified device node exists before continuing.
|
||||
* This is a cleaner check for cases where the correct controller
|
||||
* is specified, but an invalid namespace on that controller.
|
||||
*/
|
||||
sprintf(path, "/dev/%s", argv[optind]);
|
||||
if (stat(path, &devstat) < 0) {
|
||||
printf("Invalid device node %s. errno=%d (%s)\n", path, errno,
|
||||
strerror(errno));
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
|
||||
nsloc = strstr(argv[optind], "ns");
|
||||
if (nsloc == NULL) {
|
||||
printf("Invalid namepsace %s.\n", argv[optind]);
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pull the namespace id from the string. +2 skips past the "ns" part
|
||||
* of the string.
|
||||
*/
|
||||
nsid = strtol(nsloc + 2, NULL, 10);
|
||||
if (nsid == 0 && errno != 0) {
|
||||
printf("Invalid namespace ID %s.\n", argv[optind]);
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* We send IDENTIFY commands to the controller, not the namespace,
|
||||
* since it is an admin cmd. So the path should only include the
|
||||
* nvmeX part of the nvmeXnsY string.
|
||||
*/
|
||||
sprintf(path, "/dev/");
|
||||
strncat(path, argv[optind], nsloc - argv[optind]);
|
||||
if (stat(path, &devstat) < 0) {
|
||||
printf("Invalid device node %s. errno=%d (%s)\n", path, errno,
|
||||
strerror(errno));
|
||||
@ -391,11 +447,7 @@ identify_ns(int argc, char *argv[])
|
||||
exit(EX_NOPERM);
|
||||
}
|
||||
|
||||
if (ioctl(fd, NVME_IDENTIFY_NAMESPACE, &nsdata) < 0) {
|
||||
printf("Identify request to %s failed. errno=%d (%s)\n", path,
|
||||
errno, strerror(errno));
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
read_namespace_data(fd, nsid, &nsdata);
|
||||
|
||||
if (hexflag == 1) {
|
||||
if (verboseflag == 1)
|
||||
|
@ -33,12 +33,11 @@
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#define NVME_IDENTIFY_CONTROLLER _IOR('n', 0, struct nvme_controller_data)
|
||||
#define NVME_IDENTIFY_NAMESPACE _IOR('n', 1, struct nvme_namespace_data)
|
||||
#define NVME_IO_TEST _IOWR('n', 2, struct nvme_io_test)
|
||||
#define NVME_BIO_TEST _IOWR('n', 4, struct nvme_io_test)
|
||||
#define NVME_RESET_CONTROLLER _IO('n', 5)
|
||||
#define NVME_PASSTHROUGH_CMD _IOWR('n', 6, struct nvme_pt_command)
|
||||
#define NVME_PASSTHROUGH_CMD _IOWR('n', 0, struct nvme_pt_command)
|
||||
#define NVME_RESET_CONTROLLER _IO('n', 1)
|
||||
|
||||
#define NVME_IO_TEST _IOWR('n', 100, struct nvme_io_test)
|
||||
#define NVME_BIO_TEST _IOWR('n', 101, struct nvme_io_test)
|
||||
|
||||
/*
|
||||
* Use to mark a command to apply to all namespaces, or to retrieve global
|
||||
|
@ -976,34 +976,12 @@ static int
|
||||
nvme_ctrlr_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
|
||||
struct thread *td)
|
||||
{
|
||||
struct nvme_completion_poll_status status;
|
||||
struct nvme_controller *ctrlr;
|
||||
struct nvme_pt_command *pt;
|
||||
|
||||
ctrlr = cdev->si_drv1;
|
||||
|
||||
switch (cmd) {
|
||||
case NVME_IDENTIFY_CONTROLLER:
|
||||
#ifdef CHATHAM2
|
||||
/*
|
||||
* Don't refresh data on Chatham, since Chatham returns
|
||||
* garbage on IDENTIFY anyways.
|
||||
*/
|
||||
if (pci_get_devid(ctrlr->dev) == CHATHAM_PCI_ID) {
|
||||
memcpy(arg, &ctrlr->cdata, sizeof(ctrlr->cdata));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* Refresh data before returning to user. */
|
||||
status.done = FALSE;
|
||||
nvme_ctrlr_cmd_identify_controller(ctrlr, &ctrlr->cdata,
|
||||
nvme_completion_poll_cb, &status);
|
||||
while (status.done == FALSE)
|
||||
DELAY(5);
|
||||
if (nvme_completion_is_error(&status.cpl))
|
||||
return (ENXIO);
|
||||
memcpy(arg, &ctrlr->cdata, sizeof(ctrlr->cdata));
|
||||
break;
|
||||
case NVME_RESET_CONTROLLER:
|
||||
nvme_ctrlr_reset(ctrlr);
|
||||
break;
|
||||
|
@ -45,7 +45,6 @@ static int
|
||||
nvme_ns_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
|
||||
struct thread *td)
|
||||
{
|
||||
struct nvme_completion_poll_status status;
|
||||
struct nvme_namespace *ns;
|
||||
struct nvme_controller *ctrlr;
|
||||
struct nvme_pt_command *pt;
|
||||
@ -54,27 +53,6 @@ nvme_ns_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
|
||||
ctrlr = ns->ctrlr;
|
||||
|
||||
switch (cmd) {
|
||||
case NVME_IDENTIFY_NAMESPACE:
|
||||
#ifdef CHATHAM2
|
||||
/*
|
||||
* Don't refresh data on Chatham, since Chatham returns
|
||||
* garbage on IDENTIFY anyways.
|
||||
*/
|
||||
if (pci_get_devid(ctrlr->dev) == CHATHAM_PCI_ID) {
|
||||
memcpy(arg, &ns->data, sizeof(ns->data));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* Refresh data before returning to user. */
|
||||
status.done = FALSE;
|
||||
nvme_ctrlr_cmd_identify_namespace(ctrlr, ns->id, &ns->data,
|
||||
nvme_completion_poll_cb, &status);
|
||||
while (status.done == FALSE)
|
||||
DELAY(5);
|
||||
if (nvme_completion_is_error(&status.cpl))
|
||||
return (ENXIO);
|
||||
memcpy(arg, &ns->data, sizeof(ns->data));
|
||||
break;
|
||||
case NVME_IO_TEST:
|
||||
case NVME_BIO_TEST:
|
||||
nvme_ns_test(ns, cmd, arg);
|
||||
|
Loading…
Reference in New Issue
Block a user