perftest.c revision 252267
1252267Sjimharris/*- 2252267Sjimharris * Copyright (C) 2012-2013 Intel Corporation 3252267Sjimharris * All rights reserved. 4252267Sjimharris * 5252267Sjimharris * Redistribution and use in source and binary forms, with or without 6252267Sjimharris * modification, are permitted provided that the following conditions 7252267Sjimharris * are met: 8252267Sjimharris * 1. Redistributions of source code must retain the above copyright 9252267Sjimharris * notice, this list of conditions and the following disclaimer. 10252267Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 11252267Sjimharris * notice, this list of conditions and the following disclaimer in the 12252267Sjimharris * documentation and/or other materials provided with the distribution. 13252267Sjimharris * 14252267Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15252267Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16252267Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17252267Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18252267Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19252267Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20252267Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21252267Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22252267Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23252267Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24252267Sjimharris * SUCH DAMAGE. 25252267Sjimharris */ 26252267Sjimharris 27252267Sjimharris#include <sys/cdefs.h> 28252267Sjimharris__FBSDID("$FreeBSD: head/sbin/nvmecontrol/perftest.c 252267 2013-06-26 23:02:48Z jimharris $"); 29252267Sjimharris 30252267Sjimharris#include <sys/param.h> 31252267Sjimharris#include <sys/ioccom.h> 32252267Sjimharris 33252267Sjimharris#include <ctype.h> 34252267Sjimharris#include <errno.h> 35252267Sjimharris#include <fcntl.h> 36252267Sjimharris#include <stdbool.h> 37252267Sjimharris#include <stddef.h> 38252267Sjimharris#include <stdio.h> 39252267Sjimharris#include <stdlib.h> 40252267Sjimharris#include <string.h> 41252267Sjimharris#include <sysexits.h> 42252267Sjimharris#include <unistd.h> 43252267Sjimharris 44252267Sjimharris#include "nvmecontrol.h" 45252267Sjimharris 46252267Sjimharrisstatic void 47252267Sjimharrisprint_perftest(struct nvme_io_test *io_test, bool perthread) 48252267Sjimharris{ 49252267Sjimharris uint32_t i, io_completed = 0, iops, mbps; 50252267Sjimharris 51252267Sjimharris for (i = 0; i < io_test->num_threads; i++) 52252267Sjimharris io_completed += io_test->io_completed[i]; 53252267Sjimharris 54252267Sjimharris iops = io_completed/io_test->time; 55252267Sjimharris mbps = iops * io_test->size / (1024*1024); 56252267Sjimharris 57252267Sjimharris printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n", 58252267Sjimharris io_test->num_threads, io_test->size, 59252267Sjimharris io_test->opc == NVME_OPC_READ ? "READ" : "WRITE", 60252267Sjimharris io_test->time, iops, mbps); 61252267Sjimharris 62252267Sjimharris if (perthread) 63252267Sjimharris for (i = 0; i < io_test->num_threads; i++) 64252267Sjimharris printf("\t%3d: %8d IO/s\n", i, 65252267Sjimharris io_test->io_completed[i]/io_test->time); 66252267Sjimharris 67252267Sjimharris exit(1); 68252267Sjimharris} 69252267Sjimharris 70252267Sjimharrisstatic void 71252267Sjimharrisperftest_usage(void) 72252267Sjimharris{ 73252267Sjimharris fprintf(stderr, "usage:\n"); 74252267Sjimharris fprintf(stderr, PERFTEST_USAGE); 75252267Sjimharris exit(EX_USAGE); 76252267Sjimharris} 77252267Sjimharris 78252267Sjimharrisvoid 79252267Sjimharrisperftest(int argc, char *argv[]) 80252267Sjimharris{ 81252267Sjimharris struct nvme_io_test io_test; 82252267Sjimharris int fd; 83252267Sjimharris char ch; 84252267Sjimharris char *p; 85252267Sjimharris u_long ioctl_cmd = NVME_IO_TEST; 86252267Sjimharris bool nflag, oflag, sflag, tflag; 87252267Sjimharris int perthread = 0; 88252267Sjimharris 89252267Sjimharris nflag = oflag = sflag = tflag = false; 90252267Sjimharris 91252267Sjimharris memset(&io_test, 0, sizeof(io_test)); 92252267Sjimharris 93252267Sjimharris while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) { 94252267Sjimharris switch (ch) { 95252267Sjimharris case 'f': 96252267Sjimharris if (!strcmp(optarg, "refthread")) 97252267Sjimharris io_test.flags |= NVME_TEST_FLAG_REFTHREAD; 98252267Sjimharris break; 99252267Sjimharris case 'i': 100252267Sjimharris if (!strcmp(optarg, "bio") || 101252267Sjimharris !strcmp(optarg, "wait")) 102252267Sjimharris ioctl_cmd = NVME_BIO_TEST; 103252267Sjimharris else if (!strcmp(optarg, "io") || 104252267Sjimharris !strcmp(optarg, "intr")) 105252267Sjimharris ioctl_cmd = NVME_IO_TEST; 106252267Sjimharris break; 107252267Sjimharris case 'n': 108252267Sjimharris nflag = true; 109252267Sjimharris io_test.num_threads = strtoul(optarg, &p, 0); 110252267Sjimharris if (p != NULL && *p != '\0') { 111252267Sjimharris fprintf(stderr, 112252267Sjimharris "\"%s\" not valid number of threads.\n", 113252267Sjimharris optarg); 114252267Sjimharris perftest_usage(); 115252267Sjimharris } else if (io_test.num_threads == 0 || 116252267Sjimharris io_test.num_threads > 128) { 117252267Sjimharris fprintf(stderr, 118252267Sjimharris "\"%s\" not valid number of threads.\n", 119252267Sjimharris optarg); 120252267Sjimharris perftest_usage(); 121252267Sjimharris } 122252267Sjimharris break; 123252267Sjimharris case 'o': 124252267Sjimharris oflag = true; 125252267Sjimharris if (!strcmp(optarg, "read") || !strcmp(optarg, "READ")) 126252267Sjimharris io_test.opc = NVME_OPC_READ; 127252267Sjimharris else if (!strcmp(optarg, "write") || 128252267Sjimharris !strcmp(optarg, "WRITE")) 129252267Sjimharris io_test.opc = NVME_OPC_WRITE; 130252267Sjimharris else { 131252267Sjimharris fprintf(stderr, "\"%s\" not valid opcode.\n", 132252267Sjimharris optarg); 133252267Sjimharris perftest_usage(); 134252267Sjimharris } 135252267Sjimharris break; 136252267Sjimharris case 'p': 137252267Sjimharris perthread = 1; 138252267Sjimharris break; 139252267Sjimharris case 's': 140252267Sjimharris sflag = true; 141252267Sjimharris io_test.size = strtoul(optarg, &p, 0); 142252267Sjimharris if (p == NULL || *p == '\0' || toupper(*p) == 'B') { 143252267Sjimharris // do nothing 144252267Sjimharris } else if (toupper(*p) == 'K') { 145252267Sjimharris io_test.size *= 1024; 146252267Sjimharris } else if (toupper(*p) == 'M') { 147252267Sjimharris io_test.size *= 1024 * 1024; 148252267Sjimharris } else { 149252267Sjimharris fprintf(stderr, "\"%s\" not valid size.\n", 150252267Sjimharris optarg); 151252267Sjimharris perftest_usage(); 152252267Sjimharris } 153252267Sjimharris break; 154252267Sjimharris case 't': 155252267Sjimharris tflag = true; 156252267Sjimharris io_test.time = strtoul(optarg, &p, 0); 157252267Sjimharris if (p != NULL && *p != '\0') { 158252267Sjimharris fprintf(stderr, 159252267Sjimharris "\"%s\" not valid time duration.\n", 160252267Sjimharris optarg); 161252267Sjimharris perftest_usage(); 162252267Sjimharris } 163252267Sjimharris break; 164252267Sjimharris } 165252267Sjimharris } 166252267Sjimharris 167252267Sjimharris if (!nflag || !oflag || !sflag || !tflag || optind >= argc) 168252267Sjimharris perftest_usage(); 169252267Sjimharris 170252267Sjimharris open_dev(argv[optind], &fd, 1, 1); 171252267Sjimharris if (ioctl(fd, ioctl_cmd, &io_test) < 0) { 172252267Sjimharris fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno, 173252267Sjimharris strerror(errno)); 174252267Sjimharris close(fd); 175252267Sjimharris exit(EX_IOERR); 176252267Sjimharris } 177252267Sjimharris 178252267Sjimharris close(fd); 179252267Sjimharris print_perftest(&io_test, perthread); 180252267Sjimharris exit(EX_OK); 181252267Sjimharris} 182