static void register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns) { struct ns_entry *entry; const struct spdk_nvme_ctrlr_data *cdata; entry = malloc(sizeof(struct ns_entry)); if (entry == NULL) { perror("ns_entry malloc"); exit(1); } cdata = spdk_nvme_ctrlr_get_data(ctrlr); entry->ns = ns; entry->size_in_ios = spdk_nvme_ns_get_size(ns) / g_io_size_bytes; entry->io_size_blocks = g_io_size_bytes / spdk_nvme_ns_get_sector_size(ns); snprintf(entry->name, 44, "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); g_num_namespaces++; entry->next = g_namespaces; g_namespaces = entry; }
static void register_ctrlr(struct spdk_nvme_ctrlr *ctrlr) { int num_ns; struct ctrlr_entry *entry = malloc(sizeof(struct ctrlr_entry)); const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr); if (entry == NULL) { perror("ctrlr_entry malloc"); exit(1); } snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); entry->ctrlr = ctrlr; g_ctrlr = entry; num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr); /* Only register the first namespace. */ if (num_ns < 1) { fprintf(stderr, "controller found with no namespaces\n"); exit(1); } register_ns(ctrlr, spdk_nvme_ctrlr_get_ns(ctrlr, 1)); }
static void reserve_controller(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, struct spdk_pci_device *pci_dev) { const struct spdk_nvme_ctrlr_data *cdata; cdata = spdk_nvme_ctrlr_get_data(ctrlr); printf("=====================================================\n"); printf("NVMe Controller at PCI bus %d, device %d, function %d\n", spdk_pci_device_get_bus(pci_dev), spdk_pci_device_get_dev(pci_dev), spdk_pci_device_get_func(pci_dev)); printf("=====================================================\n"); printf("Reservations: %s\n", cdata->oncs.reservations ? "Supported" : "Not Supported"); if (!cdata->oncs.reservations) return; set_host_identifier(ctrlr); get_host_identifier(ctrlr); /* tested 1 namespace */ reservation_ns_register(ctrlr, qpair, 1); reservation_ns_acquire(ctrlr, qpair, 1); reservation_ns_report(ctrlr, qpair, 1); reservation_ns_release(ctrlr, qpair, 1); }
static void register_ctrlr(struct spdk_nvme_ctrlr *ctrlr) { int nsid, num_ns; struct ctrlr_entry *entry = malloc(sizeof(struct ctrlr_entry)); const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr); if (entry == NULL) { perror("ctrlr_entry malloc"); exit(1); } entry->latency_page = rte_zmalloc("nvme latency", sizeof(struct spdk_nvme_intel_rw_latency_page), 4096); if (entry->latency_page == NULL) { printf("Allocation error (latency page)\n"); exit(1); } snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); entry->ctrlr = ctrlr; entry->next = g_controllers; g_controllers = entry; if (g_latency_tracking_enable && spdk_nvme_ctrlr_is_feature_supported(ctrlr, SPDK_NVME_INTEL_FEAT_LATENCY_TRACKING)) set_latency_tracking_feature(ctrlr, true); num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr); for (nsid = 1; nsid <= num_ns; nsid++) { register_ns(ctrlr, spdk_nvme_ctrlr_get_ns(ctrlr, nsid)); } }
static struct dev * get_controller(void) { unsigned int domain; unsigned int bus; unsigned int devid; unsigned int function; uint64_t pci_addr; char address[64]; char *p; int ch; struct dev *iter; const struct spdk_nvme_ctrlr_data *cdata; memset(address, 0, sizeof(address)); foreach_dev(iter) { display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC); } printf("Please Input PCI Address(domain:bus:dev.func): \n"); while ((ch = getchar()) != '\n' && ch != EOF); p = fgets(address, 64, stdin); if (p == NULL) { return NULL; } while (isspace(*p)) { p++; } if (sscanf(p, "%x:%x:%x.%x", &domain, &bus, &devid, &function) == 4) { /* Matched a full address - all variables are initialized */ } else if (sscanf(p, "%x:%x:%x", &domain, &bus, &devid) == 3) { function = 0; } else if (sscanf(p, "%x:%x.%x", &bus, &devid, &function) == 3) { domain = 0; } else if (sscanf(p, "%x:%x", &bus, &devid) == 2) { domain = 0; function = 0; } else { return NULL; } pci_addr = (uint64_t)domain << 24; pci_addr |= (uint64_t)bus << 16; pci_addr |= (uint64_t)devid << 8; pci_addr |= (uint64_t)function; foreach_dev(iter) { if (pci_addr == get_pci_addr(iter->pci_dev)) { cdata = spdk_nvme_ctrlr_get_data(iter->ctrlr); iter->cdata = cdata; return iter; } } return NULL; }
static void nvmf_direct_ctrlr_get_data(struct spdk_nvmf_session *session) { const struct spdk_nvme_ctrlr_data *cdata; cdata = spdk_nvme_ctrlr_get_data(session->subsys->dev.direct.ctrlr); memcpy(&session->vcdata, cdata, sizeof(struct spdk_nvme_ctrlr_data)); }
static void display_controller(struct dev *dev, int model) { const struct spdk_nvme_ctrlr_data *cdata; uint8_t str[128]; uint32_t i; cdata = spdk_nvme_ctrlr_get_data(dev->ctrlr); if (model == CONTROLLER_DISPLAY_SIMPLISTIC) { printf("%04x:%02x:%02x.%02x ", spdk_pci_device_get_domain(dev->pci_dev), spdk_pci_device_get_bus(dev->pci_dev), spdk_pci_device_get_dev(dev->pci_dev), spdk_pci_device_get_func(dev->pci_dev)); printf("%-40.40s %-20.20s ", cdata->mn, cdata->sn); printf("%5d ", cdata->cntlid); printf("\n"); return; } printf("=====================================================\n"); printf("NVMe Controller: %04x:%02x:%02x.%02x\n", spdk_pci_device_get_domain(dev->pci_dev), spdk_pci_device_get_bus(dev->pci_dev), spdk_pci_device_get_dev(dev->pci_dev), spdk_pci_device_get_func(dev->pci_dev)); printf("============================\n"); printf("Controller Capabilities/Features\n"); printf("Controller ID: %d\n", cdata->cntlid); snprintf(str, sizeof(cdata->sn) + 1, "%s", cdata->sn); printf("Serial Number: %s\n", str); printf("\n"); printf("Admin Command Set Attributes\n"); printf("============================\n"); printf("Namespace Manage And Attach: %s\n", cdata->oacs.ns_manage ? "Supported" : "Not Supported"); printf("Namespace Format: %s\n", cdata->oacs.format ? "Supported" : "Not Supported"); printf("\n"); printf("NVM Command Set Attributes\n"); printf("============================\n"); if (cdata->fna.format_all_ns) { printf("Namespace format operation applies to all namespaces\n"); } else { printf("Namespace format operation applies to per namespace\n"); } printf("\n"); printf("Namespace Attributes\n"); printf("============================\n"); for (i = 1; i <= spdk_nvme_ctrlr_get_num_ns(dev->ctrlr); i++) { display_namespace(spdk_nvme_ctrlr_get_ns(dev->ctrlr, i)); } }
static void register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns) { struct ns_entry *entry; const struct spdk_nvme_ctrlr_data *cdata; cdata = spdk_nvme_ctrlr_get_data(ctrlr); if (!spdk_nvme_ns_is_active(ns)) { printf("Controller %-20.20s (%-20.20s): Skipping inactive NS %u\n", cdata->mn, cdata->sn, spdk_nvme_ns_get_id(ns)); return; } if (spdk_nvme_ns_get_size(ns) < g_io_size_bytes || spdk_nvme_ns_get_sector_size(ns) > g_io_size_bytes) { printf("WARNING: controller %-20.20s (%-20.20s) ns %u has invalid " "ns size %" PRIu64 " / block size %u for I/O size %u\n", cdata->mn, cdata->sn, spdk_nvme_ns_get_id(ns), spdk_nvme_ns_get_size(ns), spdk_nvme_ns_get_sector_size(ns), g_io_size_bytes); return; } entry = malloc(sizeof(struct ns_entry)); if (entry == NULL) { perror("ns_entry malloc"); exit(1); } entry->type = ENTRY_TYPE_NVME_NS; entry->u.nvme.ctrlr = ctrlr; entry->u.nvme.ns = ns; entry->size_in_ios = spdk_nvme_ns_get_size(ns) / g_io_size_bytes; entry->io_size_blocks = g_io_size_bytes / spdk_nvme_ns_get_sector_size(ns); snprintf(entry->name, 44, "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); g_num_namespaces++; entry->next = g_namespaces; g_namespaces = entry; }
static void attach_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts) { int nsid, num_ns; struct ctrlr_entry *entry; const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr); entry = malloc(sizeof(struct ctrlr_entry)); if (entry == NULL) { perror("ctrlr_entry malloc"); exit(1); } printf("Attached to %04x:%02x:%02x.%02x\n", spdk_pci_device_get_domain(dev), spdk_pci_device_get_bus(dev), spdk_pci_device_get_dev(dev), spdk_pci_device_get_func(dev)); snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); entry->ctrlr = ctrlr; entry->next = g_controllers; g_controllers = entry; /* * Each controller has one of more namespaces. An NVMe namespace is basically * equivalent to a SCSI LUN. The controller's IDENTIFY data tells us how * many namespaces exist on the controller. For Intel(R) P3X00 controllers, * it will just be one namespace. * * Note that in NVMe, namespace IDs start at 1, not 0. */ num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr); printf("Using controller %s with %d namespaces.\n", entry->name, num_ns); for (nsid = 1; nsid <= num_ns; nsid++) { register_ns(ctrlr, spdk_nvme_ctrlr_get_ns(ctrlr, nsid)); } }
static void register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns) { struct ns_entry *entry; const struct spdk_nvme_ctrlr_data *cdata; /* * spdk_nvme_ctrlr is the logical abstraction in SPDK for an NVMe * controller. During initialization, the IDENTIFY data for the * controller is read using an NVMe admin command, and that data * can be retrieved using spdk_nvme_ctrlr_get_data() to get * detailed information on the controller. Refer to the NVMe * specification for more details on IDENTIFY for NVMe controllers. */ cdata = spdk_nvme_ctrlr_get_data(ctrlr); if (!spdk_nvme_ns_is_active(ns)) { printf("Controller %-20.20s (%-20.20s): Skipping inactive NS %u\n", cdata->mn, cdata->sn, spdk_nvme_ns_get_id(ns)); return; } entry = malloc(sizeof(struct ns_entry)); if (entry == NULL) { perror("ns_entry malloc"); exit(1); } entry->ctrlr = ctrlr; entry->ns = ns; entry->next = g_namespaces; g_namespaces = entry; printf(" Namespace ID: %d size: %juGB\n", spdk_nvme_ns_get_id(ns), spdk_nvme_ns_get_size(ns) / 1000000000); }