Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Jul 2020 00:42:34 +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: r363358 - stable/12/usr.sbin/bhyve
Message-ID:  <202007200042.06K0gY0s008566@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: chuck
Date: Mon Jul 20 00:42:34 2020
New Revision: 363358
URL: https://svnweb.freebsd.org/changeset/base/363358

Log:
  MFC r362765 bhyve: NVMe handle zero length DSM ranges

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	Mon Jul 20 00:39:54 2020	(r363357)
+++ stable/12/usr.sbin/bhyve/pci_nvme.c	Mon Jul 20 00:42:34 2020	(r363358)
@@ -2097,6 +2097,8 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc,
     struct pci_nvme_ioreq *req,
     uint16_t *status)
 {
+	struct nvme_dsm_range *range;
+	uint32_t nr, r, non_zero, dr;
 	int err;
 	bool pending = false;
 
@@ -2105,10 +2107,31 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc,
 		goto out;
 	}
 
+	nr = cmd->cdw10 & 0xff;
+
+	/* copy locally because a range entry could straddle PRPs */
+	range = calloc(1, NVME_MAX_DSM_TRIM);
+	if (range == NULL) {
+		pci_nvme_status_genc(status, NVME_SC_INTERNAL_DEVICE_ERROR);
+		goto out;
+	}
+	nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, cmd->prp1, cmd->prp2,
+	    (uint8_t *)range, NVME_MAX_DSM_TRIM, NVME_COPY_FROM_PRP);
+
+	/* Check for invalid ranges and the number of non-zero lengths */
+	non_zero = 0;
+	for (r = 0; r <= nr; r++) {
+		if (pci_nvme_out_of_range(nvstore,
+		    range[r].starting_lba, range[r].length)) {
+			pci_nvme_status_genc(status, NVME_SC_LBA_OUT_OF_RANGE);
+			goto out;
+		}
+		if (range[r].length != 0)
+			non_zero++;
+	}
+
 	if (cmd->cdw11 & NVME_DSM_ATTR_DEALLOCATE) {
-		struct nvme_dsm_range *range;
 		size_t offset, bytes;
-		uint32_t nr, r;
 		int sectsz_bits = sc->nvstore.sectsz_bits;
 
 		/*
@@ -2120,25 +2143,17 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc,
 			goto out;
 		}
 
-		if (req == NULL) {
-			pci_nvme_status_genc(status, NVME_SC_INTERNAL_DEVICE_ERROR);
+		/* If all ranges have a zero length, return Success */
+		if (non_zero == 0) {
+			pci_nvme_status_genc(status, NVME_SC_SUCCESS);
 			goto out;
 		}
 
-		/* copy locally because a range entry could straddle PRPs */
-		range = calloc(1, NVME_MAX_DSM_TRIM);
-		if (range == NULL) {
+		if (req == NULL) {
 			pci_nvme_status_genc(status, NVME_SC_INTERNAL_DEVICE_ERROR);
 			goto out;
 		}
-		nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, cmd->prp1, cmd->prp2,
-		    (uint8_t *)range, NVME_MAX_DSM_TRIM, NVME_COPY_FROM_PRP);
 
-		if (pci_nvme_out_of_range(nvstore, range[0].starting_lba,
-		    range[0].length)) {
-			pci_nvme_status_genc(status, NVME_SC_LBA_OUT_OF_RANGE);
-			goto out;
-		}
 		offset = range[0].starting_lba << sectsz_bits;
 		bytes = range[0].length << sectsz_bits;
 
@@ -2149,8 +2164,6 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc,
 		 *
 		 * Note that NVMe Number of Ranges is a zero based value
 		 */
-		nr = cmd->cdw10 & 0xff;
-
 		req->io_req.br_iovcnt = 0;
 		req->io_req.br_offset = offset;
 		req->io_req.br_resid = bytes;
@@ -2160,20 +2173,20 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc,
 		} else {
 			struct iovec *iov = req->io_req.br_iov;
 
-			for (r = 0; r <= nr; r++) {
-				if (pci_nvme_out_of_range(nvstore, range[r].starting_lba,
-				    range[r].length)) {
-					pci_nvme_status_genc(status, NVME_SC_LBA_OUT_OF_RANGE);
-					goto out;
-				}
+			for (r = 0, dr = 0; r <= nr; r++) {
 				offset = range[r].starting_lba << sectsz_bits;
 				bytes = range[r].length << sectsz_bits;
+				if (bytes == 0)
+					continue;
+
 				if ((nvstore->size - offset) < bytes) {
-					pci_nvme_status_genc(status, NVME_SC_LBA_OUT_OF_RANGE);
+					pci_nvme_status_genc(status,
+					    NVME_SC_LBA_OUT_OF_RANGE);
 					goto out;
 				}
-				iov[r].iov_base = (void *)offset;
-				iov[r].iov_len = bytes;
+				iov[dr].iov_base = (void *)offset;
+				iov[dr].iov_len = bytes;
+				dr++;
 			}
 			req->io_req.br_callback = pci_nvme_dealloc_sm;
 
@@ -2182,7 +2195,7 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc,
 			 * prev_size to track the number of entries
 			 */
 			req->prev_gpaddr = 0;
-			req->prev_size = r;
+			req->prev_size = dr;
 		}
 
 		err = blockif_delete(nvstore->ctx, &req->io_req);
@@ -2190,10 +2203,9 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc,
 			pci_nvme_status_genc(status, NVME_SC_INTERNAL_DEVICE_ERROR);
 		else
 			pending = true;
-
-		free(range);
 	}
 out:
+	free(range);
 	return (pending);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007200042.06K0gY0s008566>