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