nvmecontrol.c revision 252654
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: stable/9/sbin/nvmecontrol/nvmecontrol.c 252654 2013-07-03 23:40:43Z jimharris $"); 29 30#include <sys/param.h> 31#include <sys/ioccom.h> 32#include <sys/stat.h> 33 34#include <dev/nvme/nvme.h> 35 36#include <ctype.h> 37#include <errno.h> 38#include <fcntl.h> 39#include <stdbool.h> 40#include <stddef.h> 41#include <stdio.h> 42#include <stdlib.h> 43#include <string.h> 44#include <sysexits.h> 45#include <unistd.h> 46 47#define DEVLIST_USAGE \ 48" nvmecontrol devlist\n" 49 50#define IDENTIFY_USAGE \ 51" nvmecontrol identify <controller id|namespace id>\n" 52 53#define PERFTEST_USAGE \ 54" nvmecontrol perftest <-n num_threads> <-o read|write>\n" \ 55" <-s size_in_bytes> <-t time_in_seconds>\n" \ 56" <-i intr|wait> [-f refthread] [-p]\n" \ 57" <namespace id>\n" 58 59#define RESET_USAGE \ 60" nvmecontrol reset <controller id>\n" 61 62static void perftest_usage(void); 63 64static void 65usage(void) 66{ 67 fprintf(stderr, "usage:\n"); 68 fprintf(stderr, DEVLIST_USAGE); 69 fprintf(stderr, IDENTIFY_USAGE); 70 fprintf(stderr, RESET_USAGE); 71 fprintf(stderr, PERFTEST_USAGE); 72 exit(EX_USAGE); 73} 74 75static void 76print_controller_hex(struct nvme_controller_data *cdata, uint32_t length) 77{ 78 uint32_t *p; 79 uint32_t i, j; 80 81 p = (uint32_t *)cdata; 82 length /= sizeof(uint32_t); 83 84 for (i = 0; i < length; i+=8) { 85 printf("%03x: ", i*4); 86 for (j = 0; j < 8; j++) 87 printf("%08x ", p[i+j]); 88 printf("\n"); 89 } 90 91 printf("\n"); 92} 93 94static void 95print_controller(struct nvme_controller_data *cdata) 96{ 97 printf("Controller Capabilities/Features\n"); 98 printf("================================\n"); 99 printf("Vendor ID: %04x\n", cdata->vid); 100 printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); 101 printf("Serial Number: %s\n", cdata->sn); 102 printf("Model Number: %s\n", cdata->mn); 103 printf("Firmware Version: %s\n", cdata->fr); 104 printf("Recommended Arb Burst: %d\n", cdata->rab); 105 printf("IEEE OUI Identifier: %02x %02x %02x\n", 106 cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); 107 printf("Multi-Interface Cap: %02x\n", cdata->mic); 108 /* TODO: Use CAP.MPSMIN to determine true memory page size. */ 109 printf("Max Data Transfer Size: "); 110 if (cdata->mdts == 0) 111 printf("Unlimited\n"); 112 else 113 printf("%d\n", PAGE_SIZE * (1 << cdata->mdts)); 114 printf("\n"); 115 116 printf("Admin Command Set Attributes\n"); 117 printf("============================\n"); 118 printf("Security Send/Receive: %s\n", 119 cdata->oacs.security ? "Supported" : "Not Supported"); 120 printf("Format NVM: %s\n", 121 cdata->oacs.format ? "Supported" : "Not Supported"); 122 printf("Firmware Activate/Download: %s\n", 123 cdata->oacs.firmware ? "Supported" : "Not Supported"); 124 printf("Abort Command Limit: %d\n", cdata->acl+1); 125 printf("Async Event Request Limit: %d\n", cdata->aerl+1); 126 printf("Number of Firmware Slots: "); 127 if (cdata->oacs.firmware != 0) 128 printf("%d\n", cdata->frmw.num_slots); 129 else 130 printf("N/A\n"); 131 printf("Firmware Slot 1 Read-Only: "); 132 if (cdata->oacs.firmware != 0) 133 printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No"); 134 else 135 printf("N/A\n"); 136 printf("Per-Namespace SMART Log: %s\n", 137 cdata->lpa.ns_smart ? "Yes" : "No"); 138 printf("Error Log Page Entries: %d\n", cdata->elpe+1); 139 printf("Number of Power States: %d\n", cdata->npss+1); 140 printf("\n"); 141 142 printf("NVM Command Set Attributes\n"); 143 printf("==========================\n"); 144 printf("Submission Queue Entry Size\n"); 145 printf(" Max: %d\n", 1 << cdata->sqes.max); 146 printf(" Min: %d\n", 1 << cdata->sqes.min); 147 printf("Completion Queue Entry Size\n"); 148 printf(" Max: %d\n", 1 << cdata->cqes.max); 149 printf(" Min: %d\n", 1 << cdata->cqes.min); 150 printf("Number of Namespaces: %d\n", cdata->nn); 151 printf("Compare Command: %s\n", 152 cdata->oncs.compare ? "Supported" : "Not Supported"); 153 printf("Write Uncorrectable Command: %s\n", 154 cdata->oncs.write_unc ? "Supported" : "Not Supported"); 155 printf("Dataset Management Command: %s\n", 156 cdata->oncs.dsm ? "Supported" : "Not Supported"); 157 printf("Volatile Write Cache: %s\n", 158 cdata->vwc.present ? "Present" : "Not Present"); 159} 160 161static void 162print_namespace_hex(struct nvme_namespace_data *nsdata, uint32_t length) 163{ 164 uint32_t *p; 165 uint32_t i, j; 166 167 p = (uint32_t *)nsdata; 168 length /= sizeof(uint32_t); 169 170 for (i = 0; i < length; i+=8) { 171 printf("%03x: ", i*4); 172 for (j = 0; j < 8; j++) 173 printf("%08x ", p[i+j]); 174 printf("\n"); 175 } 176 177 printf("\n"); 178} 179 180static void 181print_namespace(struct nvme_namespace_data *nsdata) 182{ 183 uint32_t i; 184 185 printf("Size (in LBAs): %lld (%lldM)\n", 186 (long long)nsdata->nsze, 187 (long long)nsdata->nsze / 1024 / 1024); 188 printf("Capacity (in LBAs): %lld (%lldM)\n", 189 (long long)nsdata->ncap, 190 (long long)nsdata->ncap / 1024 / 1024); 191 printf("Utilization (in LBAs): %lld (%lldM)\n", 192 (long long)nsdata->nuse, 193 (long long)nsdata->nuse / 1024 / 1024); 194 printf("Thin Provisioning: %s\n", 195 nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported"); 196 printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); 197 printf("Current LBA Format: LBA Format #%d\n", 198 nsdata->flbas.format); 199 for (i = 0; i <= nsdata->nlbaf; i++) { 200 printf("LBA Format #%d:\n", i); 201 printf(" LBA Data Size: %d\n", 202 1 << nsdata->lbaf[i].lbads); 203 } 204} 205 206static uint32_t 207ns_get_sector_size(struct nvme_namespace_data *nsdata) 208{ 209 210 return (1 << nsdata->lbaf[0].lbads); 211} 212 213static void 214read_controller_data(int fd, struct nvme_controller_data *cdata) 215{ 216 struct nvme_pt_command pt; 217 218 memset(&pt, 0, sizeof(pt)); 219 pt.cmd.opc = NVME_OPC_IDENTIFY; 220 pt.cmd.cdw10 = 1; 221 pt.buf = cdata; 222 pt.len = sizeof(*cdata); 223 pt.is_read = 1; 224 225 if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { 226 printf("Identify request failed. errno=%d (%s)\n", 227 errno, strerror(errno)); 228 exit(EX_IOERR); 229 } 230 231 if (nvme_completion_is_error(&pt.cpl)) { 232 printf("Passthrough command returned error.\n"); 233 exit(EX_IOERR); 234 } 235} 236 237static void 238read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) 239{ 240 struct nvme_pt_command pt; 241 242 memset(&pt, 0, sizeof(pt)); 243 pt.cmd.opc = NVME_OPC_IDENTIFY; 244 pt.cmd.nsid = nsid; 245 pt.buf = nsdata; 246 pt.len = sizeof(*nsdata); 247 pt.is_read = 1; 248 249 if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { 250 printf("Identify request failed. errno=%d (%s)\n", 251 errno, strerror(errno)); 252 exit(EX_IOERR); 253 } 254 255 if (nvme_completion_is_error(&pt.cpl)) { 256 printf("Passthrough command returned error.\n"); 257 exit(EX_IOERR); 258 } 259} 260 261static int 262open_dev(const char *str, int *fd, int show_error, int exit_on_error) 263{ 264 struct stat devstat; 265 char full_path[64]; 266 267 snprintf(full_path, sizeof(full_path), "/dev/%s", str); 268 if (stat(full_path, &devstat) != 0) { 269 if (show_error) 270 fprintf(stderr, "error\n"); 271 if (exit_on_error) 272 exit(EX_NOINPUT); 273 else 274 return (EX_NOINPUT); 275 } 276 277 *fd = open(full_path, O_RDWR); 278 if (*fd < 0) { 279 if (show_error) 280 printf("Could not open %s. errno=%d (%s)\n", full_path, 281 errno, strerror(errno)); 282 if (exit_on_error) 283 exit(EX_NOPERM); 284 else 285 return (EX_NOPERM); 286 } 287 288 return (EX_OK); 289} 290 291static void 292devlist(int argc, char *argv[]) 293{ 294 struct nvme_controller_data cdata; 295 struct nvme_namespace_data nsdata; 296 char name[64]; 297 uint32_t i; 298 int ch, ctrlr, exit_code, fd, found; 299 300 exit_code = EX_OK; 301 302 while ((ch = getopt(argc, argv, "")) != -1) { 303 switch ((char)ch) { 304 default: 305 usage(); 306 } 307 } 308 309 ctrlr = -1; 310 found = 0; 311 312 while (1) { 313 ctrlr++; 314 sprintf(name, "nvme%d", ctrlr); 315 316 exit_code = open_dev(name, &fd, 0, 0); 317 318 if (exit_code == EX_NOINPUT) 319 break; 320 else if (exit_code == EX_NOPERM) { 321 printf("Could not open /dev/%s, errno = %d (%s)\n", 322 name, errno, strerror(errno)); 323 continue; 324 } 325 326 found++; 327 read_controller_data(fd, &cdata); 328 printf("%6s: %s\n", name, cdata.mn); 329 330 for (i = 0; i < cdata.nn; i++) { 331 sprintf(name, "nvme%dns%d", ctrlr, i+1); 332 read_namespace_data(fd, i+1, &nsdata); 333 printf(" %10s (%lldGB)\n", 334 name, 335 nsdata.nsze * 336 (long long)ns_get_sector_size(&nsdata) / 337 1024 / 1024 / 1024); 338 } 339 340 close(fd); 341 } 342 343 if (found == 0) 344 printf("No NVMe controllers found.\n"); 345 346 exit(EX_OK); 347} 348 349static void 350identify_ctrlr(int argc, char *argv[]) 351{ 352 struct nvme_controller_data cdata; 353 int ch, fd, hexflag = 0, hexlength; 354 int verboseflag = 0; 355 356 while ((ch = getopt(argc, argv, "vx")) != -1) { 357 switch ((char)ch) { 358 case 'v': 359 verboseflag = 1; 360 break; 361 case 'x': 362 hexflag = 1; 363 break; 364 default: 365 usage(); 366 } 367 } 368 369 open_dev(argv[optind], &fd, 1, 1); 370 read_controller_data(fd, &cdata); 371 close(fd); 372 373 if (hexflag == 1) { 374 if (verboseflag == 1) 375 hexlength = sizeof(struct nvme_controller_data); 376 else 377 hexlength = offsetof(struct nvme_controller_data, 378 reserved5); 379 print_controller_hex(&cdata, hexlength); 380 exit(EX_OK); 381 } 382 383 if (verboseflag == 1) { 384 printf("-v not currently supported without -x.\n"); 385 usage(); 386 } 387 388 print_controller(&cdata); 389 exit(EX_OK); 390} 391 392static void 393identify_ns(int argc, char *argv[]) 394{ 395 struct nvme_namespace_data nsdata; 396 char path[64]; 397 char *nsloc; 398 int ch, fd, hexflag = 0, hexlength, nsid; 399 int verboseflag = 0; 400 401 while ((ch = getopt(argc, argv, "vx")) != -1) { 402 switch ((char)ch) { 403 case 'v': 404 verboseflag = 1; 405 break; 406 case 'x': 407 hexflag = 1; 408 break; 409 default: 410 usage(); 411 } 412 } 413 414 /* 415 * Check if the specified device node exists before continuing. 416 * This is a cleaner check for cases where the correct controller 417 * is specified, but an invalid namespace on that controller. 418 */ 419 open_dev(argv[optind], &fd, 1, 1); 420 close(fd); 421 422 /* 423 * Pull the namespace id from the string. +2 skips past the "ns" part 424 * of the string. Don't search past 10 characters into the string, 425 * otherwise we know it is malformed. 426 */ 427 nsloc = strnstr(argv[optind], "ns", 10); 428 if (nsloc != NULL) 429 nsid = strtol(nsloc + 2, NULL, 10); 430 if (nsloc == NULL || (nsid == 0 && errno != 0)) { 431 printf("Invalid namespace ID %s.\n", argv[optind]); 432 exit(EX_IOERR); 433 } 434 435 /* 436 * We send IDENTIFY commands to the controller, not the namespace, 437 * since it is an admin cmd. So the path should only include the 438 * nvmeX part of the nvmeXnsY string. 439 */ 440 snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]); 441 open_dev(path, &fd, 1, 1); 442 read_namespace_data(fd, nsid, &nsdata); 443 close(fd); 444 445 if (hexflag == 1) { 446 if (verboseflag == 1) 447 hexlength = sizeof(struct nvme_namespace_data); 448 else 449 hexlength = offsetof(struct nvme_namespace_data, 450 reserved6); 451 print_namespace_hex(&nsdata, hexlength); 452 exit(EX_OK); 453 } 454 455 if (verboseflag == 1) { 456 printf("-v not currently supported without -x.\n"); 457 usage(); 458 } 459 460 print_namespace(&nsdata); 461 exit(EX_OK); 462} 463 464static void 465identify(int argc, char *argv[]) 466{ 467 char *target; 468 469 if (argc < 2) 470 usage(); 471 472 while (getopt(argc, argv, "vx") != -1) ; 473 474 target = argv[optind]; 475 476 optreset = 1; 477 optind = 1; 478 479 /* 480 * If device node contains "ns", we consider it a namespace, 481 * otherwise, consider it a controller. 482 */ 483 if (strstr(target, "ns") == NULL) 484 identify_ctrlr(argc, argv); 485 else 486 identify_ns(argc, argv); 487} 488 489static void 490print_perftest(struct nvme_io_test *io_test, bool perthread) 491{ 492 uint32_t i, io_completed = 0, iops, mbps; 493 494 for (i = 0; i < io_test->num_threads; i++) 495 io_completed += io_test->io_completed[i]; 496 497 iops = io_completed/io_test->time; 498 mbps = iops * io_test->size / (1024*1024); 499 500 printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n", 501 io_test->num_threads, io_test->size, 502 io_test->opc == NVME_OPC_READ ? "READ" : "WRITE", 503 io_test->time, iops, mbps); 504 505 if (perthread) 506 for (i = 0; i < io_test->num_threads; i++) 507 printf("\t%3d: %8d IO/s\n", i, 508 io_test->io_completed[i]/io_test->time); 509 510 exit(1); 511} 512 513static void 514perftest_usage(void) 515{ 516 fprintf(stderr, "usage:\n"); 517 fprintf(stderr, PERFTEST_USAGE); 518 exit(EX_USAGE); 519} 520 521static void 522perftest(int argc, char *argv[]) 523{ 524 struct nvme_io_test io_test; 525 int fd; 526 char ch; 527 char *p; 528 u_long ioctl_cmd = NVME_IO_TEST; 529 bool nflag, oflag, sflag, tflag; 530 int perthread = 0; 531 532 nflag = oflag = sflag = tflag = false; 533 534 memset(&io_test, 0, sizeof(io_test)); 535 536 while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) { 537 switch (ch) { 538 case 'f': 539 if (!strcmp(optarg, "refthread")) 540 io_test.flags |= NVME_TEST_FLAG_REFTHREAD; 541 break; 542 case 'i': 543 if (!strcmp(optarg, "bio") || 544 !strcmp(optarg, "wait")) 545 ioctl_cmd = NVME_BIO_TEST; 546 else if (!strcmp(optarg, "io") || 547 !strcmp(optarg, "intr")) 548 ioctl_cmd = NVME_IO_TEST; 549 break; 550 case 'n': 551 nflag = true; 552 io_test.num_threads = strtoul(optarg, &p, 0); 553 if (p != NULL && *p != '\0') { 554 fprintf(stderr, 555 "\"%s\" not valid number of threads.\n", 556 optarg); 557 perftest_usage(); 558 } else if (io_test.num_threads == 0 || 559 io_test.num_threads > 128) { 560 fprintf(stderr, 561 "\"%s\" not valid number of threads.\n", 562 optarg); 563 perftest_usage(); 564 } 565 break; 566 case 'o': 567 oflag = true; 568 if (!strcmp(optarg, "read") || !strcmp(optarg, "READ")) 569 io_test.opc = NVME_OPC_READ; 570 else if (!strcmp(optarg, "write") || 571 !strcmp(optarg, "WRITE")) 572 io_test.opc = NVME_OPC_WRITE; 573 else { 574 fprintf(stderr, "\"%s\" not valid opcode.\n", 575 optarg); 576 perftest_usage(); 577 } 578 break; 579 case 'p': 580 perthread = 1; 581 break; 582 case 's': 583 sflag = true; 584 io_test.size = strtoul(optarg, &p, 0); 585 if (p == NULL || *p == '\0' || toupper(*p) == 'B') { 586 // do nothing 587 } else if (toupper(*p) == 'K') { 588 io_test.size *= 1024; 589 } else if (toupper(*p) == 'M') { 590 io_test.size *= 1024 * 1024; 591 } else { 592 fprintf(stderr, "\"%s\" not valid size.\n", 593 optarg); 594 perftest_usage(); 595 } 596 break; 597 case 't': 598 tflag = true; 599 io_test.time = strtoul(optarg, &p, 0); 600 if (p != NULL && *p != '\0') { 601 fprintf(stderr, 602 "\"%s\" not valid time duration.\n", 603 optarg); 604 perftest_usage(); 605 } 606 break; 607 } 608 } 609 610 if (!nflag || !oflag || !sflag || !tflag || optind >= argc) 611 perftest_usage(); 612 613 open_dev(argv[optind], &fd, 1, 1); 614 if (ioctl(fd, ioctl_cmd, &io_test) < 0) { 615 fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno, 616 strerror(errno)); 617 close(fd); 618 exit(EX_IOERR); 619 } 620 621 close(fd); 622 print_perftest(&io_test, perthread); 623 exit(EX_OK); 624} 625 626static void 627reset_ctrlr(int argc, char *argv[]) 628{ 629 int ch, fd; 630 631 while ((ch = getopt(argc, argv, "")) != -1) { 632 switch ((char)ch) { 633 default: 634 usage(); 635 } 636 } 637 638 open_dev(argv[optind], &fd, 1, 1); 639 if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) { 640 printf("Reset request to %s failed. errno=%d (%s)\n", 641 argv[optind], errno, strerror(errno)); 642 exit(EX_IOERR); 643 } 644 645 exit(EX_OK); 646} 647 648int 649main(int argc, char *argv[]) 650{ 651 652 if (argc < 2) 653 usage(); 654 655 if (strcmp(argv[1], "devlist") == 0) 656 devlist(argc-1, &argv[1]); 657 else if (strcmp(argv[1], "identify") == 0) 658 identify(argc-1, &argv[1]); 659 else if (strcmp(argv[1], "perftest") == 0) 660 perftest(argc-1, &argv[1]); 661 else if (strcmp(argv[1], "reset") == 0) 662 reset_ctrlr(argc-1, &argv[1]); 663 664 usage(); 665 666 return (0); 667} 668 669