Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Jul 2013 21:31:22 +0000 (UTC)
From:      Jim Harris <jimharris@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r253114 - head/sbin/nvmecontrol
Message-ID:  <201307092131.r69LVM1i051009@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jimharris
Date: Tue Jul  9 21:31:21 2013
New Revision: 253114
URL: http://svnweb.freebsd.org/changeset/base/253114

Log:
  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

Modified:
  head/sbin/nvmecontrol/identify.c
  head/sbin/nvmecontrol/logpage.c
  head/sbin/nvmecontrol/nvmecontrol.c
  head/sbin/nvmecontrol/nvmecontrol.h

Modified: head/sbin/nvmecontrol/identify.c
==============================================================================
--- head/sbin/nvmecontrol/identify.c	Tue Jul  9 21:24:19 2013	(r253113)
+++ head/sbin/nvmecontrol/identify.c	Tue Jul  9 21:31:21 2013	(r253114)
@@ -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);

Modified: head/sbin/nvmecontrol/logpage.c
==============================================================================
--- head/sbin/nvmecontrol/logpage.c	Tue Jul  9 21:24:19 2013	(r253113)
+++ head/sbin/nvmecontrol/logpage.c	Tue Jul  9 21:31:21 2013	(r253114)
@@ -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) {

Modified: head/sbin/nvmecontrol/nvmecontrol.c
==============================================================================
--- head/sbin/nvmecontrol/nvmecontrol.c	Tue Jul  9 21:24:19 2013	(r253113)
+++ head/sbin/nvmecontrol/nvmecontrol.c	Tue Jul  9 21:31:21 2013	(r253114)
@@ -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 s
 	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[])
 {

Modified: head/sbin/nvmecontrol/nvmecontrol.h
==============================================================================
--- head/sbin/nvmecontrol/nvmecontrol.h	Tue Jul  9 21:24:19 2013	(r253113)
+++ head/sbin/nvmecontrol/nvmecontrol.h	Tue Jul  9 21:31:21 2013	(r253114)
@@ -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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307092131.r69LVM1i051009>