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
This commit is contained in:
Jim Harris 2013-07-09 21:31:21 +00:00
parent bd6b0ac5be
commit 2528d6a326
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253114
4 changed files with 53 additions and 57 deletions

View File

@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$");
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
@ -194,7 +193,6 @@ identify_ns(int argc, char *argv[])
{ {
struct nvme_namespace_data nsdata; struct nvme_namespace_data nsdata;
char path[64]; char path[64];
char *nsloc;
int ch, fd, hexflag = 0, hexlength, nsid; int ch, fd, hexflag = 0, hexlength, nsid;
int verboseflag = 0; int verboseflag = 0;
@ -223,23 +221,13 @@ identify_ns(int argc, char *argv[])
open_dev(argv[optind], &fd, 1, 1); open_dev(argv[optind], &fd, 1, 1);
close(fd); 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, * We send IDENTIFY commands to the controller, not the namespace,
* since it is an admin cmd. So the path should only include the * since it is an admin cmd. The namespace ID will be specified in
* nvmeX part of the nvmeXnsY string. * 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); open_dev(path, &fd, 1, 1);
read_namespace_data(fd, nsid, &nsdata); read_namespace_data(fd, nsid, &nsdata);
close(fd); close(fd);

View File

@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
@ -242,12 +241,11 @@ logpage_usage(void)
void void
logpage(int argc, char *argv[]) logpage(int argc, char *argv[])
{ {
int fd, nsid, len; int fd, nsid;
int log_page = 0, pageflag = false; int log_page = 0, pageflag = false;
int hexflag = false; int hexflag = false, ns_specified;
int allow_ns = false; char ch, *p;
char ch, *p, *nsloc = NULL; char cname[64];
char *cname = NULL;
uint32_t size; uint32_t size;
void *buf; void *buf;
struct logpage_function *f; struct logpage_function *f;
@ -290,46 +288,31 @@ logpage(int argc, char *argv[])
if (optind >= argc) if (optind >= argc)
logpage_usage(); 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 * The log page attribtues indicate whether or not the controller
* supports the SMART/Health information log page on a per * supports the SMART/Health information log page on a per
* namespace basis. * namespace basis.
*/ */
cname = malloc(strlen(NVME_CTRLR_PREFIX) + 2); if (ns_specified) {
len = strlen(NVME_CTRLR_PREFIX) + 1; if (log_page != NVME_LOG_HEALTH_INFORMATION)
cname = strncpy(cname, argv[optind], len); errx(1, "log page %d valid only at controller level",
open_dev(cname, &fd, 1, 1); log_page);
read_controller_data(fd, &cdata); read_controller_data(fd, &cdata);
if (cdata.lpa.ns_smart == 0)
if (log_page == NVME_LOG_HEALTH_INFORMATION && cdata.lpa.ns_smart != 0) errx(1,
allow_ns = true; "controller does not support per namespace "
"smart/health information");
/* 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;
print_fn = print_hex; print_fn = print_hex;
if (!hexflag) { if (!hexflag) {

View File

@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
@ -198,6 +199,29 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error)
return (0); 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 int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {

View File

@ -63,6 +63,7 @@ void logpage(int argc, char *argv[]);
void firmware(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); 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_controller_data(int fd, struct nvme_controller_data *cdata);
void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata);
void print_hex(void *data, uint32_t length); void print_hex(void *data, uint32_t length);