aboutsummaryrefslogtreecommitdiff
path: root/sbin/nvmecontrol/nvmecontrol.c
diff options
context:
space:
mode:
authorJim Harris <jimharris@FreeBSD.org>2013-03-26 19:50:46 +0000
committerJim Harris <jimharris@FreeBSD.org>2013-03-26 19:50:46 +0000
commitb846efd7ece4a1f007bed1d320e5f6394beb3db9 (patch)
tree82359dedd1ed281aa3fd524aef64c2d6bb5a5a28 /sbin/nvmecontrol/nvmecontrol.c
parent3feffbd79665bf3111ec086058bbb6bee17f7f3d (diff)
downloadsrc-b846efd7ece4a1f007bed1d320e5f6394beb3db9.tar.gz
src-b846efd7ece4a1f007bed1d320e5f6394beb3db9.zip
Add controller reset capability to nvme(4) and ability to explicitly
invoke it from nvmecontrol(8). Controller reset will be performed in cases where I/O are repeatedly timing out, the controller reports an unrecoverable condition, or when explicitly requested via IOCTL or an nvme consumer. Since the controller may be in such a state where it cannot even process queue deletion requests, we will perform a controller reset without trying to clean up anything on the controller first. Sponsored by: Intel Reviewed by: carl
Notes
Notes: svn path=/head/; revision=248746
Diffstat (limited to 'sbin/nvmecontrol/nvmecontrol.c')
-rw-r--r--sbin/nvmecontrol/nvmecontrol.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c
index 6abd3f5d1d7a..b6b6908ea524 100644
--- a/sbin/nvmecontrol/nvmecontrol.c
+++ b/sbin/nvmecontrol/nvmecontrol.c
@@ -56,6 +56,9 @@ __FBSDID("$FreeBSD$");
" <-i intr|wait> [-f refthread] [-p]\n" \
" <namespace id>\n"
+#define RESET_USAGE \
+" nvmecontrol reset <controller id>\n"
+
static void perftest_usage(void);
static void
@@ -64,6 +67,7 @@ usage(void)
fprintf(stderr, "usage:\n");
fprintf(stderr, DEVLIST_USAGE);
fprintf(stderr, IDENTIFY_USAGE);
+ fprintf(stderr, RESET_USAGE);
fprintf(stderr, PERFTEST_USAGE);
exit(EX_USAGE);
}
@@ -580,6 +584,41 @@ perftest(int argc, char *argv[])
exit(EX_OK);
}
+static void
+reset_ctrlr(int argc, char *argv[])
+{
+ struct stat devstat;
+ char path[64];
+ int ch, fd;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch ((char)ch) {
+ default:
+ usage();
+ }
+ }
+
+ sprintf(path, "/dev/%s", argv[optind]);
+
+ if (stat(path, &devstat) != 0) {
+ printf("Invalid device node '%s'.\n", path);
+ exit(EX_IOERR);
+ }
+
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ printf("Could not open %s.\n", path);
+ exit(EX_NOPERM);
+ }
+
+ if (ioctl(fd, NVME_RESET_CONTROLLER) == -1) {
+ printf("ioctl to %s failed.\n", path);
+ exit(EX_IOERR);
+ }
+
+ exit(EX_OK);
+}
+
int
main(int argc, char *argv[])
{
@@ -593,6 +632,8 @@ main(int argc, char *argv[])
identify(argc-1, &argv[1]);
else if (strcmp(argv[1], "perftest") == 0)
perftest(argc-1, &argv[1]);
+ else if (strcmp(argv[1], "reset") == 0)
+ reset_ctrlr(argc-1, &argv[1]);
usage();