summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/nvmecontrol/nvmecontrol.c120
-rw-r--r--sys/dev/nvme/nvme.h11
-rw-r--r--sys/dev/nvme/nvme_ctrlr.c22
-rw-r--r--sys/dev/nvme/nvme_ns.c22
4 files changed, 91 insertions, 84 deletions
diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c
index cbb365b..fd55b42 100644
--- a/sbin/nvmecontrol/nvmecontrol.c
+++ b/sbin/nvmecontrol/nvmecontrol.c
@@ -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)
diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h
index f108dd9..d8dcc31 100644
--- a/sys/dev/nvme/nvme.h
+++ b/sys/dev/nvme/nvme.h
@@ -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
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index 5116e7e..a9d5a83 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -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;
diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c
index e3e2008..b7a8d09 100644
--- a/sys/dev/nvme/nvme_ns.c
+++ b/sys/dev/nvme/nvme_ns.c
@@ -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);
OpenPOWER on IntegriCloud