Deleted Added
sdiff udiff text old ( 252267 ) new ( 253109 )
full compact
1/*-
2 * Copyright (C) 2012-2013 Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sbin/nvmecontrol/perftest.c 252267 2013-06-26 23:02:48Z jimharris $");
29
30#include <sys/param.h>
31#include <sys/ioccom.h>
32
33#include <ctype.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <stdbool.h>
37#include <stddef.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <sysexits.h>
42#include <unistd.h>
43
44#include "nvmecontrol.h"
45
46static void
47print_perftest(struct nvme_io_test *io_test, bool perthread)
48{
49 uint32_t i, io_completed = 0, iops, mbps;
50
51 for (i = 0; i < io_test->num_threads; i++)
52 io_completed += io_test->io_completed[i];
53
54 iops = io_completed/io_test->time;
55 mbps = iops * io_test->size / (1024*1024);
56
57 printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n",
58 io_test->num_threads, io_test->size,
59 io_test->opc == NVME_OPC_READ ? "READ" : "WRITE",
60 io_test->time, iops, mbps);
61
62 if (perthread)
63 for (i = 0; i < io_test->num_threads; i++)
64 printf("\t%3d: %8d IO/s\n", i,
65 io_test->io_completed[i]/io_test->time);
66
67 exit(1);
68}
69
70static void
71perftest_usage(void)
72{
73 fprintf(stderr, "usage:\n");
74 fprintf(stderr, PERFTEST_USAGE);
75 exit(EX_USAGE);
76}
77
78void
79perftest(int argc, char *argv[])
80{
81 struct nvme_io_test io_test;
82 int fd;
83 char ch;
84 char *p;
85 u_long ioctl_cmd = NVME_IO_TEST;
86 bool nflag, oflag, sflag, tflag;
87 int perthread = 0;
88
89 nflag = oflag = sflag = tflag = false;
90
91 memset(&io_test, 0, sizeof(io_test));
92
93 while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) {
94 switch (ch) {
95 case 'f':
96 if (!strcmp(optarg, "refthread"))
97 io_test.flags |= NVME_TEST_FLAG_REFTHREAD;
98 break;
99 case 'i':
100 if (!strcmp(optarg, "bio") ||
101 !strcmp(optarg, "wait"))
102 ioctl_cmd = NVME_BIO_TEST;
103 else if (!strcmp(optarg, "io") ||
104 !strcmp(optarg, "intr"))
105 ioctl_cmd = NVME_IO_TEST;
106 break;
107 case 'n':
108 nflag = true;
109 io_test.num_threads = strtoul(optarg, &p, 0);
110 if (p != NULL && *p != '\0') {
111 fprintf(stderr,
112 "\"%s\" not valid number of threads.\n",
113 optarg);
114 perftest_usage();
115 } else if (io_test.num_threads == 0 ||
116 io_test.num_threads > 128) {
117 fprintf(stderr,
118 "\"%s\" not valid number of threads.\n",
119 optarg);
120 perftest_usage();
121 }
122 break;
123 case 'o':
124 oflag = true;
125 if (!strcmp(optarg, "read") || !strcmp(optarg, "READ"))
126 io_test.opc = NVME_OPC_READ;
127 else if (!strcmp(optarg, "write") ||
128 !strcmp(optarg, "WRITE"))
129 io_test.opc = NVME_OPC_WRITE;
130 else {
131 fprintf(stderr, "\"%s\" not valid opcode.\n",
132 optarg);
133 perftest_usage();
134 }
135 break;
136 case 'p':
137 perthread = 1;
138 break;
139 case 's':
140 sflag = true;
141 io_test.size = strtoul(optarg, &p, 0);
142 if (p == NULL || *p == '\0' || toupper(*p) == 'B') {
143 // do nothing
144 } else if (toupper(*p) == 'K') {
145 io_test.size *= 1024;
146 } else if (toupper(*p) == 'M') {
147 io_test.size *= 1024 * 1024;
148 } else {
149 fprintf(stderr, "\"%s\" not valid size.\n",
150 optarg);
151 perftest_usage();
152 }
153 break;
154 case 't':
155 tflag = true;
156 io_test.time = strtoul(optarg, &p, 0);
157 if (p != NULL && *p != '\0') {
158 fprintf(stderr,
159 "\"%s\" not valid time duration.\n",
160 optarg);
161 perftest_usage();
162 }
163 break;
164 }
165 }
166
167 if (!nflag || !oflag || !sflag || !tflag || optind >= argc)
168 perftest_usage();
169
170 open_dev(argv[optind], &fd, 1, 1);
171 if (ioctl(fd, ioctl_cmd, &io_test) < 0) {
172 fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno,
173 strerror(errno));
174 close(fd);
175 exit(EX_IOERR);
176 }
177
178 close(fd);
179 print_perftest(&io_test, perthread);
180 exit(EX_OK);
181}