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:
parent
bd6b0ac5be
commit
2528d6a326
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253114
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user