From daef0c50cad4e064ac274d19ee6f786de9dd2a48 Mon Sep 17 00:00:00 2001 From: krw Date: Wed, 20 Dec 2023 13:37:25 +0000 Subject: [PATCH] Don't create an sd(4) larger than what the namespace will allow. A namespace must satisfy size (nsze) >= capacity (ncap) >= utilization (nuse) Use ncap for the sd(4) size when THINP is set and ncap < nsze. Tweak some variable names in passing to make code clearer. ok dlg@ --- sys/dev/ic/nvme.c | 37 +++++++++++++++++++++++++------------ sys/dev/ic/nvmereg.h | 3 ++- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/sys/dev/ic/nvme.c b/sys/dev/ic/nvme.c index f4018fb5d35..1909fa59bc3 100644 --- a/sys/dev/ic/nvme.c +++ b/sys/dev/ic/nvme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nvme.c,v 1.106 2022/11/25 03:20:09 dlg Exp $ */ +/* $OpenBSD: nvme.c,v 1.107 2023/12/20 13:37:25 krw Exp $ */ /* * Copyright (c) 2014 David Gwynne @@ -83,6 +83,7 @@ void nvme_scsi_cmd(struct scsi_xfer *); void nvme_minphys(struct buf *, struct scsi_link *); int nvme_scsi_probe(struct scsi_link *); void nvme_scsi_free(struct scsi_link *); +uint64_t nvme_scsi_size(struct nvm_identify_namespace *); #ifdef HIBERNATE #include @@ -470,7 +471,7 @@ nvme_scsi_probe(struct scsi_link *link) identify = NVME_DMA_KVA(mem); if (rv == 0) { - if (lemtoh64(&identify->nsze) > 0) { + if (nvme_scsi_size(identify) > 0) { /* Commit namespace if it has a size greater than zero. */ identify = malloc(sizeof(*identify), M_DEVBUF, M_WAITOK); memcpy(identify, NVME_DMA_KVA(mem), sizeof(*identify)); @@ -812,7 +813,7 @@ nvme_scsi_capacity16(struct scsi_xfer *xs) struct nvme_softc *sc = link->bus->sb_adapter_softc; struct nvm_identify_namespace *ns; struct nvm_namespace_format *f; - u_int64_t nsze; + u_int64_t addr; u_int16_t tpe = READ_CAP_16_TPE; ns = sc->sc_namespaces[link->target].ident; @@ -823,12 +824,11 @@ nvme_scsi_capacity16(struct scsi_xfer *xs) return; } - /* sd_read_cap_16() will add one */ - nsze = lemtoh64(&ns->nsze) - 1; + addr = nvme_scsi_size(ns) - 1; f = &ns->lbaf[NVME_ID_NS_FLBAS(ns->flbas)]; memset(&rcd, 0, sizeof(rcd)); - _lto8b(nsze, rcd.addr); + _lto8b(addr, rcd.addr); _lto4b(1 << f->lbads, rcd.length); _lto2b(tpe, rcd.lowest_aligned); @@ -846,7 +846,7 @@ nvme_scsi_capacity(struct scsi_xfer *xs) struct nvme_softc *sc = link->bus->sb_adapter_softc; struct nvm_identify_namespace *ns; struct nvm_namespace_format *f; - u_int64_t nsze; + u_int64_t addr; ns = sc->sc_namespaces[link->target].ident; @@ -856,15 +856,14 @@ nvme_scsi_capacity(struct scsi_xfer *xs) return; } - /* sd_read_cap_10() will add one */ - nsze = lemtoh64(&ns->nsze) - 1; - if (nsze > 0xffffffff) - nsze = 0xffffffff; + addr = nvme_scsi_size(ns) - 1; + if (addr > 0xffffffff) + addr = 0xffffffff; f = &ns->lbaf[NVME_ID_NS_FLBAS(ns->flbas)]; memset(&rcd, 0, sizeof(rcd)); - _lto4b(nsze, rcd.addr); + _lto4b(addr, rcd.addr); _lto4b(1 << f->lbads, rcd.length); memcpy(xs->data, &rcd, MIN(sizeof(rcd), xs->datalen)); @@ -885,6 +884,20 @@ nvme_scsi_free(struct scsi_link *link) free(identify, M_DEVBUF, sizeof(*identify)); } +uint64_t +nvme_scsi_size(struct nvm_identify_namespace *ns) +{ + uint64_t ncap, nsze; + + ncap = lemtoh64(&ns->ncap); /* Max allowed allocation. */ + nsze = lemtoh64(&ns->nsze); + + if ((ns->nsfeat & NVME_ID_NS_NSFEAT_THIN_PROV) && ncap < nsze) + return ncap; + else + return nsze; +} + uint32_t nvme_op_sq_enter(struct nvme_softc *sc, struct nvme_queue *q, struct nvme_ccb *ccb) diff --git a/sys/dev/ic/nvmereg.h b/sys/dev/ic/nvmereg.h index 4296b543930..59300bed27c 100644 --- a/sys/dev/ic/nvmereg.h +++ b/sys/dev/ic/nvmereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nvmereg.h,v 1.12 2023/12/11 14:27:09 krw Exp $ */ +/* $OpenBSD: nvmereg.h,v 1.13 2023/12/20 13:37:25 krw Exp $ */ /* * Copyright (c) 2014 David Gwynne @@ -363,6 +363,7 @@ struct nvm_identify_namespace { u_int64_t nuse; /* Namespace Utilization */ u_int8_t nsfeat; /* Namespace Features */ +#define NVME_ID_NS_NSFEAT_THIN_PROV (1 << 0) u_int8_t nlbaf; /* Number of LBA Formats */ u_int8_t flbas; /* Formatted LBA Size */ #define NVME_ID_NS_FLBAS(_f) ((_f) & 0x0f) -- 2.20.1