git: 5c2186b99254 - main - nda: Rescan the drive on open
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 03 Mar 2026 18:01:14 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=5c2186b992546bce212dfad3e49012f4c69c2d0c
commit 5c2186b992546bce212dfad3e49012f4c69c2d0c
Author: Warner Losh <imp@FreeBSD.org>
AuthorDate: 2026-03-03 17:59:31 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-03-03 17:59:31 +0000
nda: Rescan the drive on open
SCSI and ATA drives rescan the drive on opens to catch changes to the
disk. We do it here to so we catch if a drive has been FORMATed or
SANITIZEd with different parameters. We don't use xpt_rescan() since we
don't want to interfere with boot or keep all busses locked (this rescan
won't change the bus, so we don't need the CAM topo lock).
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D55520
---
sys/cam/nvme/nvme_da.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c
index 9646b792e9a9..2e8e376f985d 100644
--- a/sys/cam/nvme/nvme_da.c
+++ b/sys/cam/nvme/nvme_da.c
@@ -73,12 +73,14 @@ typedef enum {
NDA_FLAG_OPEN = 0x0001,
NDA_FLAG_DIRTY = 0x0002,
NDA_FLAG_SCTX_INIT = 0x0004,
+ NDA_FLAG_RESCAN = 0x0008,
} nda_flags;
#define NDA_FLAG_STRING \
"\020" \
"\001OPEN" \
"\002DIRTY" \
- "\003SCTX_INIT"
+ "\003SCTX_INIT" \
+ "\004RESCAN"
typedef enum {
NDA_Q_4K = 0x01,
@@ -318,11 +320,27 @@ ndasetgeom(struct nda_softc *softc, struct cam_periph *periph)
disk->d_flags |= flags;
}
+static void
+ndaopen_rescan_done(struct cam_periph *periph, union ccb *ccb)
+{
+ struct nda_softc *softc;
+
+ softc = (struct nda_softc *)periph->softc;
+
+ cam_periph_assert(periph, MA_OWNED);
+
+ softc->flags &= ~NDA_FLAG_RESCAN;
+ xpt_release_ccb(ccb);
+ wakeup(&softc->disk->d_mediasize);
+}
+
+
static int
ndaopen(struct disk *dp)
{
struct cam_periph *periph;
struct nda_softc *softc;
+ union ccb *ccb;
int error;
periph = (struct cam_periph *)dp->d_drv1;
@@ -337,10 +355,37 @@ ndaopen(struct disk *dp)
return (error);
}
+ softc = (struct nda_softc *)periph->softc;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
("ndaopen\n"));
- softc = (struct nda_softc *)periph->softc;
+ /*
+ * Rescan the lun in case the mediasize or sectorsize has changed since
+ * we probed the device. Format and secure erase operations can do this,
+ * but the nvme standard doesn't require a async notification of that
+ * happening. da/ada do this by restarting their probe, but since
+ * nvme_xpt gets the identify information we need, we just rescan here
+ * since it's the easiest way to notice size changes.
+ *
+ * Not acquiring / releasing for the geom probe -- it's inline
+ */
+ ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
+ ccb->ccb_h.func_code = XPT_SCAN_LUN;
+ ccb->ccb_h.cbfcnp = ndaopen_rescan_done;
+ ccb->ccb_h.ppriv_ptr0 = periph;
+ ccb->crcn.flags = 0;
+ xpt_action(ccb);
+
+ softc->flags |= NDA_FLAG_RESCAN;
+ error = 0;
+ while ((softc->flags & NDA_FLAG_RESCAN) != 0 && error == 0)
+ error = cam_periph_sleep(periph, &softc->disk->d_mediasize, PRIBIO,
+ "ndareprobe", 0);
+ if (error != 0)
+ xpt_print(periph->path, "Unable to retrieve capacity data\n");
+ else
+ ndasetgeom(softc, periph);
+
softc->flags |= NDA_FLAG_OPEN;
cam_periph_unhold(periph);