Index: usr.sbin/bhyve/bhyve.8 =================================================================== --- usr.sbin/bhyve/bhyve.8 +++ usr.sbin/bhyve/bhyve.8 @@ -532,8 +532,6 @@ Max elements in each queue. .It Li ioslots Max number of concurrent I/O requests. -.It Li sectsz -Sector size (defaults to blockif sector size). .It Li ser Serial number with maximum 20 characters. .El Index: usr.sbin/bhyve/pci_nvme.c =================================================================== --- usr.sbin/bhyve/pci_nvme.c +++ usr.sbin/bhyve/pci_nvme.c @@ -33,7 +33,7 @@ * bhyve PCIe-NVMe device emulation. * * options: - * -s ,nvme,devpath,maxq=#,qsz=#,ioslots=#,sectsz=#,ser=A-Z,eui64=# + * -s ,nvme,devpath,maxq=#,qsz=#,ioslots=#,ser=A-Z,eui64=# * * accepted devpath: * /dev/blockdev @@ -43,10 +43,11 @@ * maxq = max number of queues * qsz = max elements in each queue * ioslots = max number of concurrent io requests - * sectsz = sector size (defaults to blockif sector size) * ser = serial number (20-chars max) * eui64 = IEEE Extended Unique Identifier (8 byte value) * + * block device options can also be appended + * */ /* TODO: @@ -2019,9 +2020,10 @@ pci_nvme_parse_opts(struct pci_nvme_softc *sc, char *opts) { char bident[sizeof("XX:X:X")]; - char *uopt, *xopts, *config; - uint32_t sectsz; + char *bopt, *uopt, *xopts, *config; int optidx; + size_t block_len; + FILE* fp; sc->max_queues = NVME_QUEUES; sc->max_qentries = NVME_MAX_QENTRIES; @@ -2029,7 +2031,6 @@ sc->num_squeues = sc->max_queues; sc->num_cqueues = sc->max_queues; sc->dataset_management = NVME_DATASET_MANAGEMENT_AUTO; - sectsz = 0; uopt = strdup(opts); optidx = 0; @@ -2039,76 +2040,94 @@ xopts != NULL; xopts = strtok(NULL, ",")) { - if ((config = strchr(xopts, '=')) != NULL) + if ((config = strchr(xopts, '=')) != NULL) { *config++ = '\0'; - if (!strcmp("maxq", xopts)) { - sc->max_queues = atoi(config); - } else if (!strcmp("qsz", xopts)) { - sc->max_qentries = atoi(config); - } else if (!strcmp("ioslots", xopts)) { - sc->ioslots = atoi(config); - } else if (!strcmp("sectsz", xopts)) { - sectsz = atoi(config); - } else if (!strcmp("ser", xopts)) { - /* - * This field indicates the Product Serial Number in - * 7-bit ASCII, unused bytes should be space characters. - * Ref: NVMe v1.3c. - */ - cpywithpad((char *)sc->ctrldata.sn, - sizeof(sc->ctrldata.sn), config, ' '); - } else if (!strcmp("ram", xopts)) { - uint64_t sz = strtoull(&xopts[4], NULL, 10); - - sc->nvstore.type = NVME_STOR_RAM; - sc->nvstore.size = sz * 1024 * 1024; - sc->nvstore.ctx = calloc(1, sc->nvstore.size); - sc->nvstore.sectsz = 4096; - sc->nvstore.sectsz_bits = 12; - if (sc->nvstore.ctx == NULL) { - perror("Unable to allocate RAM"); - free(uopt); - return (-1); + if (!strcmp("maxq", xopts)) { + sc->max_queues = atoi(config); + } else if (!strcmp("qsz", xopts)) { + sc->max_qentries = atoi(config); + } else if (!strcmp("ioslots", xopts)) { + sc->ioslots = atoi(config); + } else if (!strcmp("ser", xopts)) { + /* + * This field indicates the Product Serial Number in + * 7-bit ASCII, unused bytes should be space characters. + * Ref: NVMe v1.3c. + */ + cpywithpad((char *)sc->ctrldata.sn, + sizeof(sc->ctrldata.sn), config, ' '); + } else if (!strcmp("ram", xopts)) { + uint64_t sz = strtoull(&xopts[4], NULL, 10); + + sc->nvstore.type = NVME_STOR_RAM; + sc->nvstore.size = sz * 1024 * 1024; + sc->nvstore.ctx = calloc(1, sc->nvstore.size); + if (sc->nvstore.ctx == NULL) { + perror("Unable to allocate RAM"); + free(uopt); + return (-1); + } + } else if (!strcmp("eui64", xopts)) { + sc->nvstore.eui64 = htobe64(strtoull(config, NULL, 0)); + } else if (!strcmp("dsm", xopts)) { + if (!strcmp("auto", config)) + sc->dataset_management = NVME_DATASET_MANAGEMENT_AUTO; + else if (!strcmp("enable", config)) + sc->dataset_management = NVME_DATASET_MANAGEMENT_ENABLE; + else if (!strcmp("disable", config)) + sc->dataset_management = NVME_DATASET_MANAGEMENT_DISABLE; + } else { + if (sc->nvstore.type == NVME_STOR_BLOCKIF) { + /* Pass other config to blockif_open. */ + *--config = '='; + fprintf(fp, ",%s", xopts); + } else { + EPRINTLN("Invalid option %s", xopts); + free(uopt); + return (-1); + } } - } else if (!strcmp("eui64", xopts)) { - sc->nvstore.eui64 = htobe64(strtoull(config, NULL, 0)); - } else if (!strcmp("dsm", xopts)) { - if (!strcmp("auto", config)) - sc->dataset_management = NVME_DATASET_MANAGEMENT_AUTO; - else if (!strcmp("enable", config)) - sc->dataset_management = NVME_DATASET_MANAGEMENT_ENABLE; - else if (!strcmp("disable", config)) - sc->dataset_management = NVME_DATASET_MANAGEMENT_DISABLE; - } else if (optidx == 0) { - snprintf(bident, sizeof(bident), "%d:%d", - sc->nsc_pi->pi_slot, sc->nsc_pi->pi_func); - sc->nvstore.ctx = blockif_open(xopts, bident); - if (sc->nvstore.ctx == NULL) { - perror("Could not open backing file"); + } else { + if (optidx == 0) { + /* Pass other config to blockif_open. */ + bopt = NULL; + fp = open_memstream(&bopt, &block_len); + fprintf(fp, "%s", xopts); + sc->nvstore.type = NVME_STOR_BLOCKIF; + } else if (sc->nvstore.type == NVME_STOR_BLOCKIF) { + /* Pass other options to blockif_open. */ + fprintf(fp, ",%s", xopts); + } else { + EPRINTLN("Invalid option %s", xopts); free(uopt); return (-1); } - sc->nvstore.type = NVME_STOR_BLOCKIF; - sc->nvstore.size = blockif_size(sc->nvstore.ctx); - } else { - EPRINTLN("Invalid option %s", xopts); - free(uopt); - return (-1); } optidx++; } free(uopt); - if (sc->nvstore.ctx == NULL || sc->nvstore.size == 0) { - EPRINTLN("backing store not specified"); - return (-1); + if (sc->nvstore.type == NVME_STOR_BLOCKIF) { + fclose(fp); + snprintf(bident, sizeof(bident), "%d:%d", + sc->nsc_pi->pi_slot, sc->nsc_pi->pi_func); + sc->nvstore.ctx = blockif_open(bopt, bident); + free(bopt); + if (sc->nvstore.ctx == NULL) { + EPRINTLN("backing store not specified"); + return (-1); + } + sc->nvstore.size = blockif_size(sc->nvstore.ctx); } - if (sectsz == 512 || sectsz == 4096 || sectsz == 8192) - sc->nvstore.sectsz = sectsz; - else if (sc->nvstore.type != NVME_STOR_RAM) + + if (sc->nvstore.type == NVME_STOR_RAM) { + sc->nvstore.sectsz = 4096; + } else { sc->nvstore.sectsz = blockif_sectsz(sc->nvstore.ctx); + } + for (sc->nvstore.sectsz_bits = 9; (1 << sc->nvstore.sectsz_bits) < sc->nvstore.sectsz; sc->nvstore.sectsz_bits++);