1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk/nvme.h" 37 #include "spdk/vmd.h" 38 #include "spdk/nvme_zns.h" 39 #include "spdk/env.h" 40 41 struct ctrlr_entry { 42 struct spdk_nvme_ctrlr *ctrlr; 43 TAILQ_ENTRY(ctrlr_entry) link; 44 char name[1024]; 45 }; 46 47 struct ns_entry { 48 struct spdk_nvme_ctrlr *ctrlr; 49 struct spdk_nvme_ns *ns; 50 TAILQ_ENTRY(ns_entry) link; 51 struct spdk_nvme_qpair *qpair; 52 }; 53 54 static TAILQ_HEAD(, ctrlr_entry) g_controllers = TAILQ_HEAD_INITIALIZER(g_controllers); 55 static TAILQ_HEAD(, ns_entry) g_namespaces = TAILQ_HEAD_INITIALIZER(g_namespaces); 56 57 static bool g_vmd = false; 58 59 static void 60 register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns) 61 { 62 struct ns_entry *entry; 63 64 if (!spdk_nvme_ns_is_active(ns)) { 65 return; 66 } 67 68 entry = malloc(sizeof(struct ns_entry)); 69 if (entry == NULL) { 70 perror("ns_entry malloc"); 71 exit(1); 72 } 73 74 entry->ctrlr = ctrlr; 75 entry->ns = ns; 76 TAILQ_INSERT_TAIL(&g_namespaces, entry, link); 77 78 printf(" Namespace ID: %d size: %juGB\n", spdk_nvme_ns_get_id(ns), 79 spdk_nvme_ns_get_size(ns) / 1000000000); 80 } 81 82 struct hello_world_sequence { 83 struct ns_entry *ns_entry; 84 char *buf; 85 unsigned using_cmb_io; 86 int is_completed; 87 }; 88 89 static void 90 read_complete(void *arg, const struct spdk_nvme_cpl *completion) 91 { 92 struct hello_world_sequence *sequence = arg; 93 94 /* Assume the I/O was successful */ 95 sequence->is_completed = 1; 96 /* See if an error occurred. If so, display information 97 * about it, and set completion value so that I/O 98 * caller is aware that an error occurred. 99 */ 100 if (spdk_nvme_cpl_is_error(completion)) { 101 spdk_nvme_qpair_print_completion(sequence->ns_entry->qpair, (struct spdk_nvme_cpl *)completion); 102 fprintf(stderr, "I/O error status: %s\n", spdk_nvme_cpl_get_status_string(&completion->status)); 103 fprintf(stderr, "Read I/O failed, aborting run\n"); 104 sequence->is_completed = 2; 105 exit(1); 106 } 107 108 /* 109 * The read I/O has completed. Print the contents of the 110 * buffer, free the buffer, then mark the sequence as 111 * completed. This will trigger the hello_world() function 112 * to exit its polling loop. 113 */ 114 printf("%s", sequence->buf); 115 spdk_free(sequence->buf); 116 } 117 118 static void 119 write_complete(void *arg, const struct spdk_nvme_cpl *completion) 120 { 121 struct hello_world_sequence *sequence = arg; 122 struct ns_entry *ns_entry = sequence->ns_entry; 123 int rc; 124 125 /* See if an error occurred. If so, display information 126 * about it, and set completion value so that I/O 127 * caller is aware that an error occurred. 128 */ 129 if (spdk_nvme_cpl_is_error(completion)) { 130 spdk_nvme_qpair_print_completion(sequence->ns_entry->qpair, (struct spdk_nvme_cpl *)completion); 131 fprintf(stderr, "I/O error status: %s\n", spdk_nvme_cpl_get_status_string(&completion->status)); 132 fprintf(stderr, "Write I/O failed, aborting run\n"); 133 sequence->is_completed = 2; 134 exit(1); 135 } 136 /* 137 * The write I/O has completed. Free the buffer associated with 138 * the write I/O and allocate a new zeroed buffer for reading 139 * the data back from the NVMe namespace. 140 */ 141 if (sequence->using_cmb_io) { 142 spdk_nvme_ctrlr_unmap_cmb(ns_entry->ctrlr); 143 } else { 144 spdk_free(sequence->buf); 145 } 146 sequence->buf = spdk_zmalloc(0x1000, 0x1000, NULL, SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA); 147 148 rc = spdk_nvme_ns_cmd_read(ns_entry->ns, ns_entry->qpair, sequence->buf, 149 0, /* LBA start */ 150 1, /* number of LBAs */ 151 read_complete, (void *)sequence, 0); 152 if (rc != 0) { 153 fprintf(stderr, "starting read I/O failed\n"); 154 exit(1); 155 } 156 } 157 158 static void 159 reset_zone_complete(void *arg, const struct spdk_nvme_cpl *completion) 160 { 161 struct hello_world_sequence *sequence = arg; 162 163 /* Assume the I/O was successful */ 164 sequence->is_completed = 1; 165 /* See if an error occurred. If so, display information 166 * about it, and set completion value so that I/O 167 * caller is aware that an error occurred. 168 */ 169 if (spdk_nvme_cpl_is_error(completion)) { 170 spdk_nvme_qpair_print_completion(sequence->ns_entry->qpair, (struct spdk_nvme_cpl *)completion); 171 fprintf(stderr, "I/O error status: %s\n", spdk_nvme_cpl_get_status_string(&completion->status)); 172 fprintf(stderr, "Reset zone I/O failed, aborting run\n"); 173 sequence->is_completed = 2; 174 exit(1); 175 } 176 } 177 178 static void 179 reset_zone_and_wait_for_completion(struct hello_world_sequence *sequence) 180 { 181 if (spdk_nvme_zns_reset_zone(sequence->ns_entry->ns, sequence->ns_entry->qpair, 182 0, /* starting LBA of the zone to reset */ 183 false, /* don't reset all zones */ 184 reset_zone_complete, 185 sequence)) { 186 fprintf(stderr, "starting reset zone I/O failed\n"); 187 exit(1); 188 } 189 while (!sequence->is_completed) { 190 spdk_nvme_qpair_process_completions(sequence->ns_entry->qpair, 0); 191 } 192 sequence->is_completed = 0; 193 } 194 195 static void 196 hello_world(void) 197 { 198 struct ns_entry *ns_entry; 199 struct hello_world_sequence sequence; 200 int rc; 201 size_t sz; 202 203 TAILQ_FOREACH(ns_entry, &g_namespaces, link) { 204 /* 205 * Allocate an I/O qpair that we can use to submit read/write requests 206 * to namespaces on the controller. NVMe controllers typically support 207 * many qpairs per controller. Any I/O qpair allocated for a controller 208 * can submit I/O to any namespace on that controller. 209 * 210 * The SPDK NVMe driver provides no synchronization for qpair accesses - 211 * the application must ensure only a single thread submits I/O to a 212 * qpair, and that same thread must also check for completions on that 213 * qpair. This enables extremely efficient I/O processing by making all 214 * I/O operations completely lockless. 215 */ 216 ns_entry->qpair = spdk_nvme_ctrlr_alloc_io_qpair(ns_entry->ctrlr, NULL, 0); 217 if (ns_entry->qpair == NULL) { 218 printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n"); 219 return; 220 } 221 222 /* 223 * Use spdk_dma_zmalloc to allocate a 4KB zeroed buffer. This memory 224 * will be pinned, which is required for data buffers used for SPDK NVMe 225 * I/O operations. 226 */ 227 sequence.using_cmb_io = 1; 228 sequence.buf = spdk_nvme_ctrlr_map_cmb(ns_entry->ctrlr, &sz); 229 if (sequence.buf == NULL || sz < 0x1000) { 230 sequence.using_cmb_io = 0; 231 sequence.buf = spdk_zmalloc(0x1000, 0x1000, NULL, SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA); 232 } 233 if (sequence.buf == NULL) { 234 printf("ERROR: write buffer allocation failed\n"); 235 return; 236 } 237 if (sequence.using_cmb_io) { 238 printf("INFO: using controller memory buffer for IO\n"); 239 } else { 240 printf("INFO: using host memory buffer for IO\n"); 241 } 242 sequence.is_completed = 0; 243 sequence.ns_entry = ns_entry; 244 245 /* 246 * If the namespace is a Zoned Namespace, rather than a regular 247 * NVM namespace, we need to reset the first zone, before we 248 * write to it. This not needed for regular NVM namespaces. 249 */ 250 if (spdk_nvme_ns_get_csi(ns_entry->ns) == SPDK_NVME_CSI_ZNS) { 251 reset_zone_and_wait_for_completion(&sequence); 252 } 253 254 /* 255 * Print "Hello world!" to sequence.buf. We will write this data to LBA 256 * 0 on the namespace, and then later read it back into a separate buffer 257 * to demonstrate the full I/O path. 258 */ 259 snprintf(sequence.buf, 0x1000, "%s", "Hello world!\n"); 260 261 /* 262 * Write the data buffer to LBA 0 of this namespace. "write_complete" and 263 * "&sequence" are specified as the completion callback function and 264 * argument respectively. write_complete() will be called with the 265 * value of &sequence as a parameter when the write I/O is completed. 266 * This allows users to potentially specify different completion 267 * callback routines for each I/O, as well as pass a unique handle 268 * as an argument so the application knows which I/O has completed. 269 * 270 * Note that the SPDK NVMe driver will only check for completions 271 * when the application calls spdk_nvme_qpair_process_completions(). 272 * It is the responsibility of the application to trigger the polling 273 * process. 274 */ 275 rc = spdk_nvme_ns_cmd_write(ns_entry->ns, ns_entry->qpair, sequence.buf, 276 0, /* LBA start */ 277 1, /* number of LBAs */ 278 write_complete, &sequence, 0); 279 if (rc != 0) { 280 fprintf(stderr, "starting write I/O failed\n"); 281 exit(1); 282 } 283 284 /* 285 * Poll for completions. 0 here means process all available completions. 286 * In certain usage models, the caller may specify a positive integer 287 * instead of 0 to signify the maximum number of completions it should 288 * process. This function will never block - if there are no 289 * completions pending on the specified qpair, it will return immediately. 290 * 291 * When the write I/O completes, write_complete() will submit a new I/O 292 * to read LBA 0 into a separate buffer, specifying read_complete() as its 293 * completion routine. When the read I/O completes, read_complete() will 294 * print the buffer contents and set sequence.is_completed = 1. That will 295 * break this loop and then exit the program. 296 */ 297 while (!sequence.is_completed) { 298 spdk_nvme_qpair_process_completions(ns_entry->qpair, 0); 299 } 300 301 /* 302 * Free the I/O qpair. This typically is done when an application exits. 303 * But SPDK does support freeing and then reallocating qpairs during 304 * operation. It is the responsibility of the caller to ensure all 305 * pending I/O are completed before trying to free the qpair. 306 */ 307 spdk_nvme_ctrlr_free_io_qpair(ns_entry->qpair); 308 } 309 } 310 311 static bool 312 probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, 313 struct spdk_nvme_ctrlr_opts *opts) 314 { 315 printf("Attaching to %s\n", trid->traddr); 316 317 return true; 318 } 319 320 static void 321 attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, 322 struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts) 323 { 324 int nsid, num_ns; 325 struct ctrlr_entry *entry; 326 struct spdk_nvme_ns *ns; 327 const struct spdk_nvme_ctrlr_data *cdata; 328 329 entry = malloc(sizeof(struct ctrlr_entry)); 330 if (entry == NULL) { 331 perror("ctrlr_entry malloc"); 332 exit(1); 333 } 334 335 printf("Attached to %s\n", trid->traddr); 336 337 /* 338 * spdk_nvme_ctrlr is the logical abstraction in SPDK for an NVMe 339 * controller. During initialization, the IDENTIFY data for the 340 * controller is read using an NVMe admin command, and that data 341 * can be retrieved using spdk_nvme_ctrlr_get_data() to get 342 * detailed information on the controller. Refer to the NVMe 343 * specification for more details on IDENTIFY for NVMe controllers. 344 */ 345 cdata = spdk_nvme_ctrlr_get_data(ctrlr); 346 347 snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); 348 349 entry->ctrlr = ctrlr; 350 TAILQ_INSERT_TAIL(&g_controllers, entry, link); 351 352 /* 353 * Each controller has one or more namespaces. An NVMe namespace is basically 354 * equivalent to a SCSI LUN. The controller's IDENTIFY data tells us how 355 * many namespaces exist on the controller. For Intel(R) P3X00 controllers, 356 * it will just be one namespace. 357 * 358 * Note that in NVMe, namespace IDs start at 1, not 0. 359 */ 360 num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr); 361 printf("Using controller %s with %d namespaces.\n", entry->name, num_ns); 362 for (nsid = 1; nsid <= num_ns; nsid++) { 363 ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid); 364 if (ns == NULL) { 365 continue; 366 } 367 register_ns(ctrlr, ns); 368 } 369 } 370 371 static void 372 cleanup(void) 373 { 374 struct ns_entry *ns_entry, *tmp_ns_entry; 375 struct ctrlr_entry *ctrlr_entry, *tmp_ctrlr_entry; 376 struct spdk_nvme_detach_ctx *detach_ctx = NULL; 377 378 TAILQ_FOREACH_SAFE(ns_entry, &g_namespaces, link, tmp_ns_entry) { 379 TAILQ_REMOVE(&g_namespaces, ns_entry, link); 380 free(ns_entry); 381 } 382 383 TAILQ_FOREACH_SAFE(ctrlr_entry, &g_controllers, link, tmp_ctrlr_entry) { 384 TAILQ_REMOVE(&g_controllers, ctrlr_entry, link); 385 spdk_nvme_detach_async(ctrlr_entry->ctrlr, &detach_ctx); 386 free(ctrlr_entry); 387 } 388 389 while (detach_ctx && spdk_nvme_detach_poll_async(detach_ctx) == -EAGAIN) { 390 ; 391 } 392 } 393 394 static void 395 usage(const char *program_name) 396 { 397 printf("%s [options]", program_name); 398 printf("\n"); 399 printf("options:\n"); 400 printf(" -V enumerate VMD\n"); 401 } 402 403 static int 404 parse_args(int argc, char **argv) 405 { 406 int op; 407 408 while ((op = getopt(argc, argv, "V")) != -1) { 409 switch (op) { 410 case 'V': 411 g_vmd = true; 412 break; 413 default: 414 usage(argv[0]); 415 return 1; 416 } 417 } 418 419 return 0; 420 } 421 422 int main(int argc, char **argv) 423 { 424 int rc; 425 struct spdk_env_opts opts; 426 427 rc = parse_args(argc, argv); 428 if (rc != 0) { 429 return rc; 430 } 431 432 /* 433 * SPDK relies on an abstraction around the local environment 434 * named env that handles memory allocation and PCI device operations. 435 * This library must be initialized first. 436 * 437 */ 438 spdk_env_opts_init(&opts); 439 opts.name = "hello_world"; 440 opts.shm_id = 0; 441 if (spdk_env_init(&opts) < 0) { 442 fprintf(stderr, "Unable to initialize SPDK env\n"); 443 return 1; 444 } 445 446 printf("Initializing NVMe Controllers\n"); 447 448 if (g_vmd && spdk_vmd_init()) { 449 fprintf(stderr, "Failed to initialize VMD." 450 " Some NVMe devices can be unavailable.\n"); 451 } 452 453 /* 454 * Start the SPDK NVMe enumeration process. probe_cb will be called 455 * for each NVMe controller found, giving our application a choice on 456 * whether to attach to each controller. attach_cb will then be 457 * called for each controller after the SPDK NVMe driver has completed 458 * initializing the controller we chose to attach. 459 */ 460 rc = spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL); 461 if (rc != 0) { 462 fprintf(stderr, "spdk_nvme_probe() failed\n"); 463 cleanup(); 464 return 1; 465 } 466 467 if (TAILQ_EMPTY(&g_controllers)) { 468 fprintf(stderr, "no NVMe controllers found\n"); 469 cleanup(); 470 return 1; 471 } 472 473 printf("Initialization complete.\n"); 474 hello_world(); 475 cleanup(); 476 if (g_vmd) { 477 spdk_vmd_fini(); 478 } 479 480 return 0; 481 } 482