perftest.c revision 253109
1193326Sed/*-
2193326Sed * Copyright (C) 2012-2013 Intel Corporation
3193326Sed * All rights reserved.
4193326Sed *
5193326Sed * Redistribution and use in source and binary forms, with or without
6193326Sed * modification, are permitted provided that the following conditions
7193326Sed * are met:
8193326Sed * 1. Redistributions of source code must retain the above copyright
9193326Sed *    notice, this list of conditions and the following disclaimer.
10193326Sed * 2. Redistributions in binary form must reproduce the above copyright
11193326Sed *    notice, this list of conditions and the following disclaimer in the
12193326Sed *    documentation and/or other materials provided with the distribution.
13193326Sed *
14193326Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15193326Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16193326Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17193326Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18252723Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19226890Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20252723Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21201361Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22193326Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23245431Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24218893Sdim * SUCH DAMAGE.
25193326Sed */
26193326Sed
27193326Sed#include <sys/cdefs.h>
28226890Sdim__FBSDID("$FreeBSD: head/sbin/nvmecontrol/perftest.c 253109 2013-07-09 21:14:15Z jimharris $");
29193326Sed
30193326Sed#include <sys/param.h>
31193326Sed#include <sys/ioccom.h>
32193326Sed
33218893Sdim#include <ctype.h>
34218893Sdim#include <err.h>
35198092Srdivacky#include <fcntl.h>
36193326Sed#include <stdbool.h>
37193326Sed#include <stddef.h>
38193326Sed#include <stdio.h>
39193326Sed#include <stdlib.h>
40193326Sed#include <string.h>
41198092Srdivacky#include <unistd.h>
42193326Sed
43193326Sed#include "nvmecontrol.h"
44193326Sed
45193326Sedstatic void
46198092Srdivackyprint_perftest(struct nvme_io_test *io_test, bool perthread)
47193326Sed{
48198092Srdivacky	uint32_t i, io_completed = 0, iops, mbps;
49235633Sdim
50198092Srdivacky	for (i = 0; i < io_test->num_threads; i++)
51193326Sed		io_completed += io_test->io_completed[i];
52245431Sdim
53245431Sdim	iops = io_completed/io_test->time;
54245431Sdim	mbps = iops * io_test->size / (1024*1024);
55193326Sed
56193326Sed	printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n",
57193326Sed	    io_test->num_threads, io_test->size,
58193326Sed	    io_test->opc == NVME_OPC_READ ? "READ" : "WRITE",
59193326Sed	    io_test->time, iops, mbps);
60193326Sed
61198092Srdivacky	if (perthread)
62198092Srdivacky		for (i = 0; i < io_test->num_threads; i++)
63198092Srdivacky			printf("\t%3d: %8d IO/s\n", i,
64193326Sed			    io_test->io_completed[i]/io_test->time);
65193326Sed
66193326Sed	exit(1);
67193326Sed}
68193326Sed
69235633Sdimstatic void
70235633Sdimperftest_usage(void)
71235633Sdim{
72193326Sed	fprintf(stderr, "usage:\n");
73235633Sdim	fprintf(stderr, PERFTEST_USAGE);
74235633Sdim	exit(1);
75235633Sdim}
76235633Sdim
77235633Sdimvoid
78235633Sdimperftest(int argc, char *argv[])
79235633Sdim{
80235633Sdim	struct nvme_io_test		io_test;
81198092Srdivacky	int				fd;
82263509Sdim	char				ch;
83263509Sdim	char				*p;
84193326Sed	u_long				ioctl_cmd = NVME_IO_TEST;
85198092Srdivacky	bool				nflag, oflag, sflag, tflag;
86193326Sed	int				perthread = 0;
87193326Sed
88193326Sed	nflag = oflag = sflag = tflag = false;
89193326Sed
90193326Sed	memset(&io_test, 0, sizeof(io_test));
91198092Srdivacky
92193326Sed	while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) {
93193326Sed		switch (ch) {
94193326Sed		case 'f':
95193326Sed			if (!strcmp(optarg, "refthread"))
96193326Sed				io_test.flags |= NVME_TEST_FLAG_REFTHREAD;
97201361Srdivacky			break;
98193326Sed		case 'i':
99198092Srdivacky			if (!strcmp(optarg, "bio") ||
100198092Srdivacky			    !strcmp(optarg, "wait"))
101193326Sed				ioctl_cmd = NVME_BIO_TEST;
102198092Srdivacky			else if (!strcmp(optarg, "io") ||
103263509Sdim				 !strcmp(optarg, "intr"))
104263509Sdim				ioctl_cmd = NVME_IO_TEST;
105263509Sdim			break;
106263509Sdim		case 'n':
107263509Sdim			nflag = true;
108263509Sdim			io_test.num_threads = strtoul(optarg, &p, 0);
109263509Sdim			if (p != NULL && *p != '\0') {
110263509Sdim				fprintf(stderr,
111193326Sed				    "\"%s\" not valid number of threads.\n",
112193326Sed				    optarg);
113193326Sed				perftest_usage();
114263509Sdim			} else if (io_test.num_threads == 0 ||
115193326Sed				   io_test.num_threads > 128) {
116193326Sed				fprintf(stderr,
117193326Sed				    "\"%s\" not valid number of threads.\n",
118198092Srdivacky				    optarg);
119193326Sed				perftest_usage();
120193326Sed			}
121193326Sed			break;
122263509Sdim		case 'o':
123263509Sdim			oflag = true;
124193326Sed			if (!strcmp(optarg, "read") || !strcmp(optarg, "READ"))
125193326Sed				io_test.opc = NVME_OPC_READ;
126193326Sed			else if (!strcmp(optarg, "write") ||
127198092Srdivacky				 !strcmp(optarg, "WRITE"))
128193326Sed				io_test.opc = NVME_OPC_WRITE;
129193326Sed			else {
130193326Sed				fprintf(stderr, "\"%s\" not valid opcode.\n",
131263509Sdim				    optarg);
132193326Sed				perftest_usage();
133193326Sed			}
134193326Sed			break;
135198092Srdivacky		case 'p':
136193326Sed			perthread = 1;
137193326Sed			break;
138193326Sed		case 's':
139263509Sdim			sflag = true;
140263509Sdim			io_test.size = strtoul(optarg, &p, 0);
141193326Sed			if (p == NULL || *p == '\0' || toupper(*p) == 'B') {
142193326Sed				// do nothing
143193326Sed			} else if (toupper(*p) == 'K') {
144198092Srdivacky				io_test.size *= 1024;
145193326Sed			} else if (toupper(*p) == 'M') {
146193326Sed				io_test.size *= 1024 * 1024;
147193326Sed			} else {
148193326Sed				fprintf(stderr, "\"%s\" not valid size.\n",
149193326Sed				    optarg);
150193326Sed				perftest_usage();
151226890Sdim			}
152193326Sed			break;
153193326Sed		case 't':
154235633Sdim			tflag = true;
155235633Sdim			io_test.time = strtoul(optarg, &p, 0);
156193326Sed			if (p != NULL && *p != '\0') {
157193326Sed				fprintf(stderr,
158226890Sdim				    "\"%s\" not valid time duration.\n",
159226890Sdim				    optarg);
160193326Sed				perftest_usage();
161193326Sed			}
162226890Sdim			break;
163226890Sdim		}
164226890Sdim	}
165226890Sdim
166193326Sed	if (!nflag || !oflag || !sflag || !tflag || optind >= argc)
167193326Sed		perftest_usage();
168235633Sdim
169235633Sdim	open_dev(argv[optind], &fd, 1, 1);
170235633Sdim	if (ioctl(fd, ioctl_cmd, &io_test) < 0)
171235633Sdim		err(1, "ioctl NVME_IO_TEST failed");
172235633Sdim
173193326Sed	close(fd);
174193326Sed	print_perftest(&io_test, perthread);
175193326Sed	exit(0);
176193326Sed}
177193326Sed