summaryrefslogtreecommitdiffstats
path: root/sbin/nvmecontrol
diff options
context:
space:
mode:
authorjimharris <jimharris@FreeBSD.org>2013-07-09 21:31:21 +0000
committerjimharris <jimharris@FreeBSD.org>2013-07-09 21:31:21 +0000
commite9bddbcfa54c66d580d0e618ff4212c3a548837a (patch)
treed5f163d9caa466ceafbf43d39ff55ebfb5091c4b /sbin/nvmecontrol
parent6a4189c5fdf3d1448e04e1e52f11439d89305424 (diff)
downloadFreeBSD-src-e9bddbcfa54c66d580d0e618ff4212c3a548837a.zip
FreeBSD-src-e9bddbcfa54c66d580d0e618ff4212c3a548837a.tar.gz
Send per-namespace logpage commands to the controller devnode, so they
are processed as admin commands, not I/O commands. As part of this change, pull out the code for parsing a namespace node string into a separate function, since it is used for both identify and logpage commands. Sponsored by: Intel MFC after: 3 days
Diffstat (limited to 'sbin/nvmecontrol')
-rw-r--r--sbin/nvmecontrol/identify.c20
-rw-r--r--sbin/nvmecontrol/logpage.c65
-rw-r--r--sbin/nvmecontrol/nvmecontrol.c24
-rw-r--r--sbin/nvmecontrol/nvmecontrol.h1
4 files changed, 53 insertions, 57 deletions
diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c
index 1fe2a34..189f164 100644
--- a/sbin/nvmecontrol/identify.c
+++ b/sbin/nvmecontrol/identify.c
@@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
-#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
@@ -194,7 +193,6 @@ identify_ns(int argc, char *argv[])
{
struct nvme_namespace_data nsdata;
char path[64];
- char *nsloc;
int ch, fd, hexflag = 0, hexlength, nsid;
int verboseflag = 0;
@@ -224,22 +222,12 @@ identify_ns(int argc, char *argv[])
close(fd);
/*
- * Pull the namespace id from the string. +2 skips past the "ns" part
- * of the string. Don't search past 10 characters into the string,
- * otherwise we know it is malformed.
- */
- nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10);
- if (nsloc != NULL)
- nsid = strtol(nsloc + 2, NULL, 10);
- if (nsloc == NULL || (nsid == 0 && errno != 0))
- errx(1, "invalid namespace ID '%s'", argv[optind]);
-
- /*
* 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.
+ * since it is an admin cmd. The namespace ID will be specified in
+ * the IDENTIFY command itself. So parse the namespace's device node
+ * string to get the controller substring and namespace ID.
*/
- snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]);
+ parse_ns_str(argv[optind], path, &nsid);
open_dev(path, &fd, 1, 1);
read_namespace_data(fd, nsid, &nsdata);
close(fd);
diff --git a/sbin/nvmecontrol/logpage.c b/sbin/nvmecontrol/logpage.c
index a26ce04..e330988 100644
--- a/sbin/nvmecontrol/logpage.c
+++ b/sbin/nvmecontrol/logpage.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
-#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
@@ -242,12 +241,11 @@ logpage_usage(void)
void
logpage(int argc, char *argv[])
{
- int fd, nsid, len;
+ int fd, nsid;
int log_page = 0, pageflag = false;
- int hexflag = false;
- int allow_ns = false;
- char ch, *p, *nsloc = NULL;
- char *cname = NULL;
+ int hexflag = false, ns_specified;
+ char ch, *p;
+ char cname[64];
uint32_t size;
void *buf;
struct logpage_function *f;
@@ -290,46 +288,31 @@ logpage(int argc, char *argv[])
if (optind >= argc)
logpage_usage();
+ if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) {
+ ns_specified = true;
+ parse_ns_str(argv[optind], cname, &nsid);
+ open_dev(cname, &fd, 1, 1);
+ } else {
+ ns_specified = false;
+ nsid = NVME_GLOBAL_NAMESPACE_TAG;
+ open_dev(argv[optind], &fd, 1, 1);
+ }
+
/*
* The log page attribtues indicate whether or not the controller
* supports the SMART/Health information log page on a per
* namespace basis.
*/
- cname = malloc(strlen(NVME_CTRLR_PREFIX) + 2);
- len = strlen(NVME_CTRLR_PREFIX) + 1;
- cname = strncpy(cname, argv[optind], len);
- open_dev(cname, &fd, 1, 1);
- read_controller_data(fd, &cdata);
-
- if (log_page == NVME_LOG_HEALTH_INFORMATION && cdata.lpa.ns_smart != 0)
- allow_ns = true;
-
- /* If a namespace id was specified, validate it's use */
- if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) {
- if (!allow_ns) {
- if (log_page != NVME_LOG_HEALTH_INFORMATION)
- errx(1,
- "log page %d valid only at controller level",
- log_page);
- else if (cdata.lpa.ns_smart == 0)
- errx(1,
- "controller does not support per "
- "namespace smart/health information");
- }
- nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10);
- if (nsloc != NULL)
- nsid = strtol(nsloc + 2, NULL, 10);
- if (nsloc == NULL || (nsid == 0 && errno != 0))
- errx(1, "invalid namespace id '%s'", argv[optind]);
-
- /*
- * User is asking for per namespace log page information
- * so close the controller and open up the namespace.
- */
- close(fd);
- open_dev(argv[optind], &fd, 1, 1);
- } else
- nsid = NVME_GLOBAL_NAMESPACE_TAG;
+ if (ns_specified) {
+ if (log_page != NVME_LOG_HEALTH_INFORMATION)
+ errx(1, "log page %d valid only at controller level",
+ log_page);
+ read_controller_data(fd, &cdata);
+ if (cdata.lpa.ns_smart == 0)
+ errx(1,
+ "controller does not support per namespace "
+ "smart/health information");
+ }
print_fn = print_hex;
if (!hexflag) {
diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c
index c566bb3..63cec3c 100644
--- a/sbin/nvmecontrol/nvmecontrol.c
+++ b/sbin/nvmecontrol/nvmecontrol.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
@@ -198,6 +199,29 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error)
return (0);
}
+void
+parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid)
+{
+ char *nsloc;
+
+ /*
+ * Pull the namespace id from the string. +2 skips past the "ns" part
+ * of the string. Don't search past 10 characters into the string,
+ * otherwise we know it is malformed.
+ */
+ nsloc = strnstr(ns_str, NVME_NS_PREFIX, 10);
+ if (nsloc != NULL)
+ *nsid = strtol(nsloc + 2, NULL, 10);
+ if (nsloc == NULL || (*nsid == 0 && errno != 0))
+ errx(1, "invalid namespace ID '%s'", ns_str);
+
+ /*
+ * The controller string will include only the nvmX part of the
+ * nvmeXnsY string.
+ */
+ snprintf(ctrlr_str, nsloc - ns_str + 1, "%s", ns_str);
+}
+
int
main(int argc, char *argv[])
{
diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h
index f7a35b4..99075f6 100644
--- a/sbin/nvmecontrol/nvmecontrol.h
+++ b/sbin/nvmecontrol/nvmecontrol.h
@@ -63,6 +63,7 @@ void logpage(int argc, char *argv[]);
void firmware(int argc, char *argv[]);
int open_dev(const char *str, int *fd, int show_error, int exit_on_error);
+void parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid);
void read_controller_data(int fd, struct nvme_controller_data *cdata);
void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata);
void print_hex(void *data, uint32_t length);
OpenPOWER on IntegriCloud