1 /*- 2 * Copyright (C) 2012 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$"); 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 62 static void perftest_usage(void); 63 64 static void 65 usage(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 75 static void 76 print_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 94 static void 95 print_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 161 static void 162 print_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 180 static void 181 print_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 206 static uint32_t 207 ns_get_sector_size(struct nvme_namespace_data *nsdata) 208 { 209 210 return (1 << nsdata->lbaf[0].lbads); 211 } 212 213 static void 214 read_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 237 static void 238 read_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 261 static void 262 devlist(int argc, char *argv[]) 263 { 264 struct nvme_controller_data cdata; 265 struct nvme_namespace_data nsdata; 266 struct stat devstat; 267 char name[64], path[64]; 268 uint32_t i; 269 int ch, ctrlr, exit_code, fd, found; 270 271 exit_code = EX_OK; 272 273 while ((ch = getopt(argc, argv, "")) != -1) { 274 switch ((char)ch) { 275 default: 276 usage(); 277 } 278 } 279 280 ctrlr = -1; 281 found = 0; 282 283 while (1) { 284 ctrlr++; 285 sprintf(name, "nvme%d", ctrlr); 286 sprintf(path, "/dev/%s", name); 287 288 if (stat(path, &devstat) != 0) 289 break; 290 291 found++; 292 293 fd = open(path, O_RDWR); 294 if (fd < 0) { 295 printf("Could not open %s. errno=%d (%s)\n", path, 296 errno, strerror(errno)); 297 exit_code = EX_NOPERM; 298 continue; 299 } 300 301 read_controller_data(fd, &cdata); 302 printf("%6s: %s\n", name, cdata.mn); 303 304 for (i = 0; i < cdata.nn; i++) { 305 sprintf(name, "nvme%dns%d", ctrlr, i+1); 306 read_namespace_data(fd, i+1, &nsdata); 307 printf(" %10s (%lldGB)\n", 308 name, 309 nsdata.nsze * 310 (long long)ns_get_sector_size(&nsdata) / 311 1024 / 1024 / 1024); 312 } 313 } 314 315 if (found == 0) 316 printf("No NVMe controllers found.\n"); 317 318 exit(exit_code); 319 } 320 321 static void 322 identify_ctrlr(int argc, char *argv[]) 323 { 324 struct nvme_controller_data cdata; 325 struct stat devstat; 326 char path[64]; 327 int ch, fd, hexflag = 0, hexlength; 328 int verboseflag = 0; 329 330 while ((ch = getopt(argc, argv, "vx")) != -1) { 331 switch ((char)ch) { 332 case 'v': 333 verboseflag = 1; 334 break; 335 case 'x': 336 hexflag = 1; 337 break; 338 default: 339 usage(); 340 } 341 } 342 343 sprintf(path, "/dev/%s", argv[optind]); 344 345 if (stat(path, &devstat) < 0) { 346 printf("Invalid device node %s. errno=%d (%s)\n", path, errno, 347 strerror(errno)); 348 exit(EX_IOERR); 349 } 350 351 fd = open(path, O_RDWR); 352 if (fd < 0) { 353 printf("Could not open %s. errno=%d (%s)\n", path, errno, 354 strerror(errno)); 355 exit(EX_NOPERM); 356 } 357 358 read_controller_data(fd, &cdata); 359 360 if (hexflag == 1) { 361 if (verboseflag == 1) 362 hexlength = sizeof(struct nvme_controller_data); 363 else 364 hexlength = offsetof(struct nvme_controller_data, 365 reserved5); 366 print_controller_hex(&cdata, hexlength); 367 exit(EX_OK); 368 } 369 370 if (verboseflag == 1) { 371 printf("-v not currently supported without -x.\n"); 372 usage(); 373 } 374 375 print_controller(&cdata); 376 exit(EX_OK); 377 } 378 379 static void 380 identify_ns(int argc, char *argv[]) 381 { 382 struct nvme_namespace_data nsdata; 383 struct stat devstat; 384 char path[64]; 385 char *nsloc; 386 int ch, fd, hexflag = 0, hexlength, nsid; 387 int verboseflag = 0; 388 389 while ((ch = getopt(argc, argv, "vx")) != -1) { 390 switch ((char)ch) { 391 case 'v': 392 verboseflag = 1; 393 break; 394 case 'x': 395 hexflag = 1; 396 break; 397 default: 398 usage(); 399 } 400 } 401 402 /* 403 * Check if the specified device node exists before continuing. 404 * This is a cleaner check for cases where the correct controller 405 * is specified, but an invalid namespace on that controller. 406 */ 407 sprintf(path, "/dev/%s", argv[optind]); 408 if (stat(path, &devstat) < 0) { 409 printf("Invalid device node %s. errno=%d (%s)\n", path, errno, 410 strerror(errno)); 411 exit(EX_IOERR); 412 } 413 414 nsloc = strstr(argv[optind], "ns"); 415 if (nsloc == NULL) { 416 printf("Invalid namepsace %s.\n", argv[optind]); 417 exit(EX_IOERR); 418 } 419 420 /* 421 * Pull the namespace id from the string. +2 skips past the "ns" part 422 * of the string. 423 */ 424 nsid = strtol(nsloc + 2, NULL, 10); 425 if (nsid == 0 && errno != 0) { 426 printf("Invalid namespace ID %s.\n", argv[optind]); 427 exit(EX_IOERR); 428 } 429 430 /* 431 * We send IDENTIFY commands to the controller, not the namespace, 432 * since it is an admin cmd. So the path should only include the 433 * nvmeX part of the nvmeXnsY string. 434 */ 435 sprintf(path, "/dev/"); 436 strncat(path, argv[optind], nsloc - argv[optind]); 437 if (stat(path, &devstat) < 0) { 438 printf("Invalid device node %s. errno=%d (%s)\n", path, errno, 439 strerror(errno)); 440 exit(EX_IOERR); 441 } 442 443 fd = open(path, O_RDWR); 444 if (fd < 0) { 445 printf("Could not open %s. errno=%d (%s)\n", path, errno, 446 strerror(errno)); 447 exit(EX_NOPERM); 448 } 449 450 read_namespace_data(fd, nsid, &nsdata); 451 452 if (hexflag == 1) { 453 if (verboseflag == 1) 454 hexlength = sizeof(struct nvme_namespace_data); 455 else 456 hexlength = offsetof(struct nvme_namespace_data, 457 reserved6); 458 print_namespace_hex(&nsdata, hexlength); 459 exit(EX_OK); 460 } 461 462 if (verboseflag == 1) { 463 printf("-v not currently supported without -x.\n"); 464 usage(); 465 } 466 467 print_namespace(&nsdata); 468 exit(EX_OK); 469 } 470 471 static void 472 identify(int argc, char *argv[]) 473 { 474 char *target; 475 476 if (argc < 2) 477 usage(); 478 479 while (getopt(argc, argv, "vx") != -1) ; 480 481 target = argv[optind]; 482 483 /* Specified device node must have "nvme" in it. */ 484 if (strstr(argv[optind], "nvme") == NULL) { 485 printf("Invalid device node '%s'.\n", argv[optind]); 486 exit(EX_IOERR); 487 } 488 489 optreset = 1; 490 optind = 1; 491 492 /* 493 * If device node contains "ns", we consider it a namespace, 494 * otherwise, consider it a controller. 495 */ 496 if (strstr(target, "ns") == NULL) 497 identify_ctrlr(argc, argv); 498 else 499 identify_ns(argc, argv); 500 } 501 502 static void 503 print_perftest(struct nvme_io_test *io_test, bool perthread) 504 { 505 uint32_t i, io_completed = 0, iops, mbps; 506 507 for (i = 0; i < io_test->num_threads; i++) 508 io_completed += io_test->io_completed[i]; 509 510 iops = io_completed/io_test->time; 511 mbps = iops * io_test->size / (1024*1024); 512 513 printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n", 514 io_test->num_threads, io_test->size, 515 io_test->opc == NVME_OPC_READ ? "READ" : "WRITE", 516 io_test->time, iops, mbps); 517 518 if (perthread) 519 for (i = 0; i < io_test->num_threads; i++) 520 printf("\t%3d: %8d IO/s\n", i, 521 io_test->io_completed[i]/io_test->time); 522 523 exit(1); 524 } 525 526 static void 527 perftest_usage(void) 528 { 529 fprintf(stderr, "usage:\n"); 530 fprintf(stderr, PERFTEST_USAGE); 531 exit(EX_USAGE); 532 } 533 534 static void 535 perftest(int argc, char *argv[]) 536 { 537 struct nvme_io_test io_test; 538 int fd; 539 char ch; 540 char *p; 541 const char *name; 542 char path[64]; 543 u_long ioctl_cmd = NVME_IO_TEST; 544 bool nflag, oflag, sflag, tflag; 545 int perthread = 0; 546 547 nflag = oflag = sflag = tflag = false; 548 name = NULL; 549 550 memset(&io_test, 0, sizeof(io_test)); 551 552 while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) { 553 switch (ch) { 554 case 'f': 555 if (!strcmp(optarg, "refthread")) 556 io_test.flags |= NVME_TEST_FLAG_REFTHREAD; 557 break; 558 case 'i': 559 if (!strcmp(optarg, "bio") || 560 !strcmp(optarg, "wait")) 561 ioctl_cmd = NVME_BIO_TEST; 562 else if (!strcmp(optarg, "io") || 563 !strcmp(optarg, "intr")) 564 ioctl_cmd = NVME_IO_TEST; 565 break; 566 case 'n': 567 nflag = true; 568 io_test.num_threads = strtoul(optarg, &p, 0); 569 if (p != NULL && *p != '\0') { 570 fprintf(stderr, 571 "\"%s\" not valid number of threads.\n", 572 optarg); 573 perftest_usage(); 574 } else if (io_test.num_threads == 0 || 575 io_test.num_threads > 128) { 576 fprintf(stderr, 577 "\"%s\" not valid number of threads.\n", 578 optarg); 579 perftest_usage(); 580 } 581 break; 582 case 'o': 583 oflag = true; 584 if (!strcmp(optarg, "read") || !strcmp(optarg, "READ")) 585 io_test.opc = NVME_OPC_READ; 586 else if (!strcmp(optarg, "write") || 587 !strcmp(optarg, "WRITE")) 588 io_test.opc = NVME_OPC_WRITE; 589 else { 590 fprintf(stderr, "\"%s\" not valid opcode.\n", 591 optarg); 592 perftest_usage(); 593 } 594 break; 595 case 'p': 596 perthread = 1; 597 break; 598 case 's': 599 sflag = true; 600 io_test.size = strtoul(optarg, &p, 0); 601 if (p == NULL || *p == '\0' || toupper(*p) == 'B') { 602 // do nothing 603 } else if (toupper(*p) == 'K') { 604 io_test.size *= 1024; 605 } else if (toupper(*p) == 'M') { 606 io_test.size *= 1024 * 1024; 607 } else { 608 fprintf(stderr, "\"%s\" not valid size.\n", 609 optarg); 610 perftest_usage(); 611 } 612 break; 613 case 't': 614 tflag = true; 615 io_test.time = strtoul(optarg, &p, 0); 616 if (p != NULL && *p != '\0') { 617 fprintf(stderr, 618 "\"%s\" not valid time duration.\n", 619 optarg); 620 perftest_usage(); 621 } 622 break; 623 } 624 } 625 626 name = argv[optind]; 627 628 if (!nflag || !oflag || !sflag || !tflag || name == NULL) 629 perftest_usage(); 630 631 sprintf(path, "/dev/%s", name); 632 633 fd = open(path, O_RDWR); 634 if (fd < 0) { 635 fprintf(stderr, "%s not valid device. errno=%d (%s)\n", path, 636 errno, strerror(errno)); 637 perftest_usage(); 638 } 639 640 if (ioctl(fd, ioctl_cmd, &io_test) < 0) { 641 fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno, 642 strerror(errno)); 643 exit(EX_IOERR); 644 } 645 646 print_perftest(&io_test, perthread); 647 exit(EX_OK); 648 } 649 650 static void 651 reset_ctrlr(int argc, char *argv[]) 652 { 653 struct stat devstat; 654 char path[64]; 655 int ch, fd; 656 657 while ((ch = getopt(argc, argv, "")) != -1) { 658 switch ((char)ch) { 659 default: 660 usage(); 661 } 662 } 663 664 sprintf(path, "/dev/%s", argv[optind]); 665 666 if (stat(path, &devstat) < 0) { 667 printf("Invalid device node %s. errno=%d (%s)\n", path, errno, 668 strerror(errno)); 669 exit(EX_IOERR); 670 } 671 672 fd = open(path, O_RDWR); 673 if (fd < 0) { 674 printf("Could not open %s. errno=%d (%s)\n", path, errno, 675 strerror(errno)); 676 exit(EX_NOPERM); 677 } 678 679 if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) { 680 printf("Reset request to %s failed. errno=%d (%s)\n", path, 681 errno, strerror(errno)); 682 exit(EX_IOERR); 683 } 684 685 exit(EX_OK); 686 } 687 688 int 689 main(int argc, char *argv[]) 690 { 691 692 if (argc < 2) 693 usage(); 694 695 if (strcmp(argv[1], "devlist") == 0) 696 devlist(argc-1, &argv[1]); 697 else if (strcmp(argv[1], "identify") == 0) 698 identify(argc-1, &argv[1]); 699 else if (strcmp(argv[1], "perftest") == 0) 700 perftest(argc-1, &argv[1]); 701 else if (strcmp(argv[1], "reset") == 0) 702 reset_ctrlr(argc-1, &argv[1]); 703 704 usage(); 705 706 return (0); 707 } 708