Add an open_dev() helper function to be used in the various places
where nvmecontrol needs to open a handle to a controller or namespace device node. Sponsored by: Intel MFC after: 3 days
This commit is contained in:
parent
666b0fab76
commit
eadf2a44c2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=252263
@ -1,5 +1,5 @@
|
|||||||
/*-
|
/*-
|
||||||
* Copyright (C) 2012 Intel Corporation
|
* Copyright (C) 2012-2013 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -258,13 +258,42 @@ read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_dev(const char *str, int *fd, int show_error, int exit_on_error)
|
||||||
|
{
|
||||||
|
struct stat devstat;
|
||||||
|
char full_path[64];
|
||||||
|
|
||||||
|
snprintf(full_path, sizeof(full_path), "/dev/%s", str);
|
||||||
|
if (stat(full_path, &devstat) != 0) {
|
||||||
|
if (show_error)
|
||||||
|
fprintf(stderr, "error\n");
|
||||||
|
if (exit_on_error)
|
||||||
|
exit(EX_NOINPUT);
|
||||||
|
else
|
||||||
|
return (EX_NOINPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
*fd = open(full_path, O_RDWR);
|
||||||
|
if (*fd < 0) {
|
||||||
|
if (show_error)
|
||||||
|
printf("Could not open %s. errno=%d (%s)\n", full_path,
|
||||||
|
errno, strerror(errno));
|
||||||
|
if (exit_on_error)
|
||||||
|
exit(EX_NOPERM);
|
||||||
|
else
|
||||||
|
return (EX_NOPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (EX_OK);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
devlist(int argc, char *argv[])
|
devlist(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct nvme_controller_data cdata;
|
struct nvme_controller_data cdata;
|
||||||
struct nvme_namespace_data nsdata;
|
struct nvme_namespace_data nsdata;
|
||||||
struct stat devstat;
|
char name[64];
|
||||||
char name[64], path[64];
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int ch, ctrlr, exit_code, fd, found;
|
int ch, ctrlr, exit_code, fd, found;
|
||||||
|
|
||||||
@ -283,21 +312,18 @@ devlist(int argc, char *argv[])
|
|||||||
while (1) {
|
while (1) {
|
||||||
ctrlr++;
|
ctrlr++;
|
||||||
sprintf(name, "nvme%d", ctrlr);
|
sprintf(name, "nvme%d", ctrlr);
|
||||||
sprintf(path, "/dev/%s", name);
|
|
||||||
|
|
||||||
if (stat(path, &devstat) != 0)
|
exit_code = open_dev(name, &fd, 0, 0);
|
||||||
|
|
||||||
|
if (exit_code == EX_NOINPUT)
|
||||||
break;
|
break;
|
||||||
|
else if (exit_code == EX_NOPERM) {
|
||||||
found++;
|
printf("Could not open /dev/%s, errno = %d (%s)\n",
|
||||||
|
name, errno, strerror(errno));
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found++;
|
||||||
read_controller_data(fd, &cdata);
|
read_controller_data(fd, &cdata);
|
||||||
printf("%6s: %s\n", name, cdata.mn);
|
printf("%6s: %s\n", name, cdata.mn);
|
||||||
|
|
||||||
@ -310,20 +336,20 @@ devlist(int argc, char *argv[])
|
|||||||
(long long)ns_get_sector_size(&nsdata) /
|
(long long)ns_get_sector_size(&nsdata) /
|
||||||
1024 / 1024 / 1024);
|
1024 / 1024 / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found == 0)
|
if (found == 0)
|
||||||
printf("No NVMe controllers found.\n");
|
printf("No NVMe controllers found.\n");
|
||||||
|
|
||||||
exit(exit_code);
|
exit(EX_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
identify_ctrlr(int argc, char *argv[])
|
identify_ctrlr(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct nvme_controller_data cdata;
|
struct nvme_controller_data cdata;
|
||||||
struct stat devstat;
|
|
||||||
char path[64];
|
|
||||||
int ch, fd, hexflag = 0, hexlength;
|
int ch, fd, hexflag = 0, hexlength;
|
||||||
int verboseflag = 0;
|
int verboseflag = 0;
|
||||||
|
|
||||||
@ -340,22 +366,9 @@ identify_ctrlr(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(path, "/dev/%s", argv[optind]);
|
open_dev(argv[optind], &fd, 1, 1);
|
||||||
|
|
||||||
if (stat(path, &devstat) < 0) {
|
|
||||||
printf("Invalid device node %s. errno=%d (%s)\n", path, errno,
|
|
||||||
strerror(errno));
|
|
||||||
exit(EX_IOERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
printf("Could not open %s. errno=%d (%s)\n", path, errno,
|
|
||||||
strerror(errno));
|
|
||||||
exit(EX_NOPERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
read_controller_data(fd, &cdata);
|
read_controller_data(fd, &cdata);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
if (hexflag == 1) {
|
if (hexflag == 1) {
|
||||||
if (verboseflag == 1)
|
if (verboseflag == 1)
|
||||||
@ -380,7 +393,6 @@ static void
|
|||||||
identify_ns(int argc, char *argv[])
|
identify_ns(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct nvme_namespace_data nsdata;
|
struct nvme_namespace_data nsdata;
|
||||||
struct stat devstat;
|
|
||||||
char path[64];
|
char path[64];
|
||||||
char *nsloc;
|
char *nsloc;
|
||||||
int ch, fd, hexflag = 0, hexlength, nsid;
|
int ch, fd, hexflag = 0, hexlength, nsid;
|
||||||
@ -404,25 +416,18 @@ identify_ns(int argc, char *argv[])
|
|||||||
* This is a cleaner check for cases where the correct controller
|
* This is a cleaner check for cases where the correct controller
|
||||||
* is specified, but an invalid namespace on that controller.
|
* is specified, but an invalid namespace on that controller.
|
||||||
*/
|
*/
|
||||||
sprintf(path, "/dev/%s", argv[optind]);
|
open_dev(argv[optind], &fd, 1, 1);
|
||||||
if (stat(path, &devstat) < 0) {
|
close(fd);
|
||||||
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
|
* Pull the namespace id from the string. +2 skips past the "ns" part
|
||||||
* of the string.
|
* of the string. Don't search past 10 characters into the string,
|
||||||
|
* otherwise we know it is malformed.
|
||||||
*/
|
*/
|
||||||
nsid = strtol(nsloc + 2, NULL, 10);
|
nsloc = strnstr(argv[optind], "ns", 10);
|
||||||
if (nsid == 0 && errno != 0) {
|
if (nsloc != NULL)
|
||||||
|
nsid = strtol(nsloc + 2, NULL, 10);
|
||||||
|
if (nsloc == NULL || (nsid == 0 && errno != 0)) {
|
||||||
printf("Invalid namespace ID %s.\n", argv[optind]);
|
printf("Invalid namespace ID %s.\n", argv[optind]);
|
||||||
exit(EX_IOERR);
|
exit(EX_IOERR);
|
||||||
}
|
}
|
||||||
@ -432,22 +437,10 @@ identify_ns(int argc, char *argv[])
|
|||||||
* since it is an admin cmd. So the path should only include the
|
* since it is an admin cmd. So the path should only include the
|
||||||
* nvmeX part of the nvmeXnsY string.
|
* nvmeX part of the nvmeXnsY string.
|
||||||
*/
|
*/
|
||||||
sprintf(path, "/dev/");
|
snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]);
|
||||||
strncat(path, argv[optind], nsloc - argv[optind]);
|
open_dev(path, &fd, 1, 1);
|
||||||
if (stat(path, &devstat) < 0) {
|
|
||||||
printf("Invalid device node %s. errno=%d (%s)\n", path, errno,
|
|
||||||
strerror(errno));
|
|
||||||
exit(EX_IOERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
printf("Could not open %s. errno=%d (%s)\n", path, errno,
|
|
||||||
strerror(errno));
|
|
||||||
exit(EX_NOPERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
read_namespace_data(fd, nsid, &nsdata);
|
read_namespace_data(fd, nsid, &nsdata);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
if (hexflag == 1) {
|
if (hexflag == 1) {
|
||||||
if (verboseflag == 1)
|
if (verboseflag == 1)
|
||||||
@ -480,12 +473,6 @@ identify(int argc, char *argv[])
|
|||||||
|
|
||||||
target = argv[optind];
|
target = argv[optind];
|
||||||
|
|
||||||
/* Specified device node must have "nvme" in it. */
|
|
||||||
if (strstr(argv[optind], "nvme") == NULL) {
|
|
||||||
printf("Invalid device node '%s'.\n", argv[optind]);
|
|
||||||
exit(EX_IOERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
optreset = 1;
|
optreset = 1;
|
||||||
optind = 1;
|
optind = 1;
|
||||||
|
|
||||||
@ -538,14 +525,11 @@ perftest(int argc, char *argv[])
|
|||||||
int fd;
|
int fd;
|
||||||
char ch;
|
char ch;
|
||||||
char *p;
|
char *p;
|
||||||
const char *name;
|
|
||||||
char path[64];
|
|
||||||
u_long ioctl_cmd = NVME_IO_TEST;
|
u_long ioctl_cmd = NVME_IO_TEST;
|
||||||
bool nflag, oflag, sflag, tflag;
|
bool nflag, oflag, sflag, tflag;
|
||||||
int perthread = 0;
|
int perthread = 0;
|
||||||
|
|
||||||
nflag = oflag = sflag = tflag = false;
|
nflag = oflag = sflag = tflag = false;
|
||||||
name = NULL;
|
|
||||||
|
|
||||||
memset(&io_test, 0, sizeof(io_test));
|
memset(&io_test, 0, sizeof(io_test));
|
||||||
|
|
||||||
@ -623,26 +607,18 @@ perftest(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name = argv[optind];
|
if (!nflag || !oflag || !sflag || !tflag || optind >= argc)
|
||||||
|
|
||||||
if (!nflag || !oflag || !sflag || !tflag || name == NULL)
|
|
||||||
perftest_usage();
|
perftest_usage();
|
||||||
|
|
||||||
sprintf(path, "/dev/%s", name);
|
open_dev(argv[optind], &fd, 1, 1);
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "%s not valid device. errno=%d (%s)\n", path,
|
|
||||||
errno, strerror(errno));
|
|
||||||
perftest_usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(fd, ioctl_cmd, &io_test) < 0) {
|
if (ioctl(fd, ioctl_cmd, &io_test) < 0) {
|
||||||
fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno,
|
fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
close(fd);
|
||||||
exit(EX_IOERR);
|
exit(EX_IOERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
print_perftest(&io_test, perthread);
|
print_perftest(&io_test, perthread);
|
||||||
exit(EX_OK);
|
exit(EX_OK);
|
||||||
}
|
}
|
||||||
@ -650,9 +626,7 @@ perftest(int argc, char *argv[])
|
|||||||
static void
|
static void
|
||||||
reset_ctrlr(int argc, char *argv[])
|
reset_ctrlr(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct stat devstat;
|
int ch, fd;
|
||||||
char path[64];
|
|
||||||
int ch, fd;
|
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "")) != -1) {
|
while ((ch = getopt(argc, argv, "")) != -1) {
|
||||||
switch ((char)ch) {
|
switch ((char)ch) {
|
||||||
@ -661,24 +635,10 @@ reset_ctrlr(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(path, "/dev/%s", argv[optind]);
|
open_dev(argv[optind], &fd, 1, 1);
|
||||||
|
|
||||||
if (stat(path, &devstat) < 0) {
|
|
||||||
printf("Invalid device node %s. errno=%d (%s)\n", path, errno,
|
|
||||||
strerror(errno));
|
|
||||||
exit(EX_IOERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
printf("Could not open %s. errno=%d (%s)\n", path, errno,
|
|
||||||
strerror(errno));
|
|
||||||
exit(EX_NOPERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) {
|
if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) {
|
||||||
printf("Reset request to %s failed. errno=%d (%s)\n", path,
|
printf("Reset request to %s failed. errno=%d (%s)\n",
|
||||||
errno, strerror(errno));
|
argv[optind], errno, strerror(errno));
|
||||||
exit(EX_IOERR);
|
exit(EX_IOERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user