Date: Sun, 19 Jul 2020 23:45:49 +0000 (UTC) From: Chuck Tuffli <chuck@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r363349 - stable/12/usr.sbin/bhyve Message-ID: <202007192345.06JNjnau071268@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: chuck Date: Sun Jul 19 23:45:49 2020 New Revision: 363349 URL: https://svnweb.freebsd.org/changeset/base/363349 Log: MFC r362759 bhyve: implement NVMe SMART data I/O statistics Modified: stable/12/usr.sbin/bhyve/pci_nvme.c Directory Properties: stable/12/ (props changed) Modified: stable/12/usr.sbin/bhyve/pci_nvme.c ============================================================================== --- stable/12/usr.sbin/bhyve/pci_nvme.c Sun Jul 19 23:42:46 2020 (r363348) +++ stable/12/usr.sbin/bhyve/pci_nvme.c Sun Jul 19 23:45:49 2020 (r363349) @@ -218,6 +218,7 @@ struct pci_nvme_ioreq { uint64_t prev_gpaddr; size_t prev_size; + size_t bytes; struct blockif_req io_req; @@ -287,6 +288,14 @@ struct pci_nvme_softc { struct nvme_feature_obj feat[NVME_FID_MAX]; enum nvme_dsm_type dataset_management; + + /* Accounting for SMART data */ + __uint128_t read_data_units; + __uint128_t write_data_units; + __uint128_t read_commands; + __uint128_t write_commands; + uint32_t read_dunits_remainder; + uint32_t write_dunits_remainder; }; @@ -576,6 +585,10 @@ pci_nvme_init_logpages(struct pci_nvme_softc *sc) memset(&sc->err_log, 0, sizeof(sc->err_log)); memset(&sc->health_log, 0, sizeof(sc->health_log)); memset(&sc->fw_log, 0, sizeof(sc->fw_log)); + + /* Set read/write remainder to round up according to spec */ + sc->read_dunits_remainder = 999; + sc->write_dunits_remainder = 999; } static void @@ -961,7 +974,17 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struc NVME_COPY_TO_PRP); break; case NVME_LOG_HEALTH_INFORMATION: - /* TODO: present some smart info */ + pthread_mutex_lock(&sc->mtx); + memcpy(&sc->health_log.data_units_read, &sc->read_data_units, + sizeof(sc->health_log.data_units_read)); + memcpy(&sc->health_log.data_units_written, &sc->write_data_units, + sizeof(sc->health_log.data_units_written)); + memcpy(&sc->health_log.host_read_commands, &sc->read_commands, + sizeof(sc->health_log.host_read_commands)); + memcpy(&sc->health_log.host_write_commands, &sc->write_commands, + sizeof(sc->health_log.host_write_commands)); + pthread_mutex_unlock(&sc->mtx); + nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1, command->prp2, (uint8_t *)&sc->health_log, MIN(logsize, sizeof(sc->health_log)), @@ -1464,6 +1487,47 @@ pci_nvme_handle_admin_cmd(struct pci_nvme_softc* sc, u pthread_mutex_unlock(&sq->mtx); } +/* + * Update the Write and Read statistics reported in SMART data + * + * NVMe defines "data unit" as thousand's of 512 byte blocks and is rounded up. + * E.g. 1 data unit is 1 - 1,000 512 byte blocks. 3 data units are 2,001 - 3,000 + * 512 byte blocks. Rounding up is acheived by initializing the remainder to 999. + */ +static void +pci_nvme_stats_write_read_update(struct pci_nvme_softc *sc, uint8_t opc, + size_t bytes, uint16_t status) +{ + + pthread_mutex_lock(&sc->mtx); + switch (opc) { + case NVME_OPC_WRITE: + sc->write_commands++; + if (status != NVME_SC_SUCCESS) + break; + sc->write_dunits_remainder += (bytes / 512); + while (sc->write_dunits_remainder >= 1000) { + sc->write_data_units++; + sc->write_dunits_remainder -= 1000; + } + break; + case NVME_OPC_READ: + sc->read_commands++; + if (status != NVME_SC_SUCCESS) + break; + sc->read_dunits_remainder += (bytes / 512); + while (sc->read_dunits_remainder >= 1000) { + sc->read_data_units++; + sc->read_dunits_remainder -= 1000; + } + break; + default: + DPRINTF("%s: Invalid OPC 0x%02x for stats", __func__, opc); + break; + } + pthread_mutex_unlock(&sc->mtx); +} + static int pci_nvme_append_iov_req(struct pci_nvme_softc *sc, struct pci_nvme_ioreq *req, uint64_t gpaddr, size_t size, int do_write, uint64_t lba) @@ -1604,6 +1668,8 @@ pci_nvme_io_done(struct blockif_req *br, int err) pci_nvme_status_genc(&status, code); pci_nvme_set_completion(req->sc, sq, req->sqid, req->cid, 0, status); + pci_nvme_stats_write_read_update(req->sc, req->opc, + req->bytes, status); pci_nvme_release_ioreq(req->sc, req); } @@ -1778,6 +1844,7 @@ nvme_opc_write_read(struct pci_nvme_softc *sc, goto out; } + req->bytes = bytes; req->io_req.br_offset = lba; /* PRP bits 1:0 must be zero */ @@ -1795,6 +1862,9 @@ nvme_opc_write_read(struct pci_nvme_softc *sc, pending = true; } out: + if (!pending) + pci_nvme_stats_write_read_update(sc, cmd->opc, bytes, *status); + return (pending); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007192345.06JNjnau071268>