Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Oct 2012 00:32:08 +0000 (UTC)
From:      Jim Harris <jimharris@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r241657 - in head/sys/dev: nvd nvme
Message-ID:  <201210180032.q9I0W80r099467@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jimharris
Date: Thu Oct 18 00:32:07 2012
New Revision: 241657
URL: http://svn.freebsd.org/changeset/base/241657

Log:
  Add return codes to all functions used for submitting commands to I/O
  queues.
  
  Sponsored by:	Intel

Modified:
  head/sys/dev/nvd/nvd.c
  head/sys/dev/nvme/nvme.c
  head/sys/dev/nvme/nvme.h
  head/sys/dev/nvme/nvme_ns.c
  head/sys/dev/nvme/nvme_ns_cmd.c
  head/sys/dev/nvme/nvme_qpair.c
  head/sys/dev/nvme/nvme_uio.c

Modified: head/sys/dev/nvd/nvd.c
==============================================================================
--- head/sys/dev/nvd/nvd.c	Thu Oct 18 00:20:02 2012	(r241656)
+++ head/sys/dev/nvd/nvd.c	Thu Oct 18 00:32:07 2012	(r241657)
@@ -214,9 +214,21 @@ nvd_bioq_process(void *arg, int pending)
 
 		err = nvme_ns_bio_process(ndisk->ns, bp, nvd_done);
 
+		/*
+		 * TODO: remove this loop and rely on GEOM's pacing once
+		 *  nvme(4) returns ENOMEM only for malloc() failures.
+		 *  Currently nvme(4) returns ENOMEM also for cases when
+		 *  the submission queue is completely full, and that case
+		 *  will be handled more elegantly in a future update.
+		 */
+		while (err == ENOMEM) {
+			pause("nvd enomem", 1);
+			err = nvme_ns_bio_process(ndisk->ns, bp, nvd_done);
+		}
+
 		if (err) {
 			atomic_add_acq_int(&ndisk->cur_depth, -1);
-			bp->bio_error = EIO;
+			bp->bio_error = err;
 			bp->bio_flags |= BIO_ERROR;
 			bp->bio_resid = bp->bio_bcount;
 			biodone(bp);

Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c	Thu Oct 18 00:20:02 2012	(r241656)
+++ head/sys/dev/nvme/nvme.c	Thu Oct 18 00:32:07 2012	(r241657)
@@ -275,6 +275,9 @@ nvme_allocate_tracker(struct nvme_contro
 
 	tr = nvme_qpair_allocate_tracker(qpair, alloc_prp_list);
 
+	if (tr == NULL)
+		return (NULL);
+
 	memset(&tr->cmd, 0, sizeof(tr->cmd));
 
 	tr->qpair = qpair;

Modified: head/sys/dev/nvme/nvme.h
==============================================================================
--- head/sys/dev/nvme/nvme.h	Thu Oct 18 00:20:02 2012	(r241656)
+++ head/sys/dev/nvme/nvme.h	Thu Oct 18 00:32:07 2012	(r241657)
@@ -704,16 +704,16 @@ enum nvme_namespace_flags {
 };
 
 /* NVM I/O functions */
-void	nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload,
+int	nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload,
 			  uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn,
 			  void *cb_arg);
-void	nvme_ns_cmd_read(struct nvme_namespace *ns, void *payload,
+int	nvme_ns_cmd_read(struct nvme_namespace *ns, void *payload,
 			 uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn,
 			 void *cb_arg);
-void	nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload,
+int	nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload,
 			       uint8_t num_ranges, nvme_cb_fn_t cb_fn,
 			       void *cb_arg);
-void	nvme_ns_cmd_flush(struct nvme_namespace *ns, nvme_cb_fn_t cb_fn,
+int	nvme_ns_cmd_flush(struct nvme_namespace *ns, nvme_cb_fn_t cb_fn,
 			  void *cb_arg);
 
 /* Registration functions */

Modified: head/sys/dev/nvme/nvme_ns.c
==============================================================================
--- head/sys/dev/nvme/nvme_ns.c	Thu Oct 18 00:20:02 2012	(r241656)
+++ head/sys/dev/nvme/nvme_ns.c	Thu Oct 18 00:32:07 2012	(r241657)
@@ -160,7 +160,7 @@ nvme_ns_strategy(struct bio *bp)
 	err = nvme_ns_bio_process(ns, bp, nvme_ns_strategy_done);
 
 	if (err) {
-		bp->bio_error = EIO;
+		bp->bio_error = err;
 		bp->bio_flags |= BIO_ERROR;
 		bp->bio_resid = bp->bio_bcount;
 		biodone(bp);
@@ -239,25 +239,26 @@ int
 nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp,
 	nvme_cb_fn_t cb_fn)
 {
-	struct nvme_dsm_range *dsm_range;
+	struct nvme_dsm_range	*dsm_range;
+	int			err;
 
 	bp->bio_driver1 = cb_fn;
 
 	switch (bp->bio_cmd) {
 	case BIO_READ:
-		nvme_ns_cmd_read(ns, bp->bio_data,
-		    bp->bio_offset/nvme_ns_get_sector_size(ns),
-		    bp->bio_bcount/nvme_ns_get_sector_size(ns),
-		    nvme_ns_bio_done, bp);
+		err = nvme_ns_cmd_read(ns, bp->bio_data,
+			bp->bio_offset/nvme_ns_get_sector_size(ns),
+			bp->bio_bcount/nvme_ns_get_sector_size(ns),
+			nvme_ns_bio_done, bp);
 		break;
 	case BIO_WRITE:
-		nvme_ns_cmd_write(ns, bp->bio_data,
-		    bp->bio_offset/nvme_ns_get_sector_size(ns),
-		    bp->bio_bcount/nvme_ns_get_sector_size(ns),
-		    nvme_ns_bio_done, bp);
+		err = nvme_ns_cmd_write(ns, bp->bio_data,
+			bp->bio_offset/nvme_ns_get_sector_size(ns),
+			bp->bio_bcount/nvme_ns_get_sector_size(ns),
+			nvme_ns_bio_done, bp);
 		break;
 	case BIO_FLUSH:
-		nvme_ns_cmd_flush(ns, nvme_ns_bio_done, bp);
+		err = nvme_ns_cmd_flush(ns, nvme_ns_bio_done, bp);
 		break;
 	case BIO_DELETE:
 		/*
@@ -272,13 +273,17 @@ nvme_ns_bio_process(struct nvme_namespac
 		dsm_range->starting_lba =
 		    bp->bio_offset/nvme_ns_get_sector_size(ns);
 		bp->bio_driver2 = dsm_range;
-		nvme_ns_cmd_deallocate(ns, dsm_range, 1, nvme_ns_bio_done, bp);
+		err = nvme_ns_cmd_deallocate(ns, dsm_range, 1,
+			nvme_ns_bio_done, bp);
+		if (err != 0)
+			free(dsm_range, M_NVME);
 		break;
 	default:
-		return (EIO);
+		err = EIO;
+		break;
 	}
 
-	return (0);
+	return (err);
 }
 
 #ifdef CHATHAM2

Modified: head/sys/dev/nvme/nvme_ns_cmd.c
==============================================================================
--- head/sys/dev/nvme/nvme_ns_cmd.c	Thu Oct 18 00:20:02 2012	(r241656)
+++ head/sys/dev/nvme/nvme_ns_cmd.c	Thu Oct 18 00:32:07 2012	(r241657)
@@ -29,7 +29,7 @@ __FBSDID("$FreeBSD$");
 
 #include "nvme_private.h"
 
-void
+int
 nvme_ns_cmd_read(struct nvme_namespace *ns, void *payload, uint64_t lba,
     uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg)
 {
@@ -40,6 +40,9 @@ nvme_ns_cmd_read(struct nvme_namespace *
 	tr = nvme_allocate_tracker(ns->ctrlr, FALSE, cb_fn, cb_arg,
 	    lba_count*512, payload);
 
+	if (tr == NULL)
+		return (ENOMEM);
+
 	cmd = &tr->cmd;
 	cmd->opc = NVME_OPC_READ;
 	cmd->nsid = ns->id;
@@ -52,9 +55,11 @@ nvme_ns_cmd_read(struct nvme_namespace *
 	    tr->payload_size, nvme_payload_map, tr, 0);
 
 	KASSERT(err == 0, ("bus_dmamap_load returned non-zero!\n"));
+
+	return (0);
 }
 
-void
+int
 nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload, uint64_t lba,
     uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg)
 {
@@ -65,6 +70,9 @@ nvme_ns_cmd_write(struct nvme_namespace 
 	tr = nvme_allocate_tracker(ns->ctrlr, FALSE, cb_fn, cb_arg,
 	    lba_count*512, payload);
 
+	if (tr == NULL)
+		return (ENOMEM);
+
 	cmd = &tr->cmd;
 	cmd->opc = NVME_OPC_WRITE;
 	cmd->nsid = ns->id;
@@ -77,9 +85,11 @@ nvme_ns_cmd_write(struct nvme_namespace 
 	    tr->payload_size, nvme_payload_map, tr, 0);
 
 	KASSERT(err == 0, ("bus_dmamap_load returned non-zero!\n"));
+
+	return (0);
 }
 
-void
+int
 nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload,
     uint8_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg)
 {
@@ -90,6 +100,9 @@ nvme_ns_cmd_deallocate(struct nvme_names
 	tr = nvme_allocate_tracker(ns->ctrlr, FALSE, cb_fn, cb_arg,
 	    num_ranges * sizeof(struct nvme_dsm_range), payload);
 
+	if (tr == NULL)
+		return (ENOMEM);
+
 	cmd = &tr->cmd;
 	cmd->opc = NVME_OPC_DATASET_MANAGEMENT;
 	cmd->nsid = ns->id;
@@ -102,9 +115,11 @@ nvme_ns_cmd_deallocate(struct nvme_names
 	    tr->payload_size, nvme_payload_map, tr, 0);
 
 	KASSERT(err == 0, ("bus_dmamap_load returned non-zero!\n"));
+
+	return (0);
 }
 
-void
+int
 nvme_ns_cmd_flush(struct nvme_namespace *ns, nvme_cb_fn_t cb_fn, void *cb_arg)
 {
 	struct nvme_tracker	*tr;
@@ -112,9 +127,14 @@ nvme_ns_cmd_flush(struct nvme_namespace 
 
 	tr = nvme_allocate_tracker(ns->ctrlr, FALSE, cb_fn, cb_arg, 0, NULL);
 
+	if (tr == NULL)
+		return (ENOMEM);
+
 	cmd = &tr->cmd;
 	cmd->opc = NVME_OPC_FLUSH;
 	cmd->nsid = ns->id;
 
 	nvme_qpair_submit_cmd(tr->qpair, tr);
+
+	return (0);
 }

Modified: head/sys/dev/nvme/nvme_qpair.c
==============================================================================
--- head/sys/dev/nvme/nvme_qpair.c	Thu Oct 18 00:20:02 2012	(r241656)
+++ head/sys/dev/nvme/nvme_qpair.c	Thu Oct 18 00:32:07 2012	(r241657)
@@ -84,10 +84,24 @@ nvme_qpair_allocate_tracker(struct nvme_
 
 	tr = SLIST_FIRST(&qpair->free_tr);
 	if (tr == NULL) {
-		/* TODO: fail if malloc returns NULL */
+		/* 
+		 * We can't support more trackers than we have entries in
+		 *  our queue, because it would generate invalid indices
+		 *  into the qpair's active tracker array.
+		 */
+		if (qpair->num_tr == qpair->num_entries) {
+			mtx_unlock(&qpair->lock);
+			return (NULL);
+		}
+
 		tr = malloc(sizeof(struct nvme_tracker), M_NVME,
 		    M_ZERO | M_NOWAIT);
 
+		if (tr == NULL) {
+			mtx_unlock(&qpair->lock);
+			return (NULL);
+		}
+
 		bus_dmamap_create(qpair->dma_tag, 0, &tr->dma_map);
 		callout_init_mtx(&tr->timer, &qpair->lock, 0);
 		tr->cid = qpair->num_tr++;

Modified: head/sys/dev/nvme/nvme_uio.c
==============================================================================
--- head/sys/dev/nvme/nvme_uio.c	Thu Oct 18 00:20:02 2012	(r241656)
+++ head/sys/dev/nvme/nvme_uio.c	Thu Oct 18 00:32:07 2012	(r241657)
@@ -64,6 +64,9 @@ nvme_allocate_tracker_uio(struct nvme_co
 	 */
 	tr = nvme_qpair_allocate_tracker(qpair, TRUE /* alloc_prp_list */);
 
+	if (tr == NULL)
+		return (NULL);
+
 	memset(&tr->cmd, 0, sizeof(tr->cmd));
 
 	tr->qpair = qpair;
@@ -80,7 +83,7 @@ nvme_payload_map_uio(void *arg, bus_dma_
 	nvme_payload_map(arg, seg, nseg, error);
 }
 
-static void
+static int
 nvme_read_uio(struct nvme_namespace *ns, struct uio *uio)
 {
 	struct nvme_tracker	*tr;
@@ -90,6 +93,9 @@ nvme_read_uio(struct nvme_namespace *ns,
 
 	tr = nvme_allocate_tracker_uio(ns->ctrlr, uio);
 
+	if (tr == NULL)
+		return (ENOMEM);
+
 	cmd = &tr->cmd;
 	cmd->opc = NVME_OPC_READ;
 	cmd->nsid = ns->id;
@@ -107,9 +113,11 @@ nvme_read_uio(struct nvme_namespace *ns,
 	    nvme_payload_map_uio, tr, 0);
 
 	KASSERT(err == 0, ("bus_dmamap_load_uio returned non-zero!\n"));
+
+	return (0);
 }
 
-static void
+static int
 nvme_write_uio(struct nvme_namespace *ns, struct uio *uio)
 {
 	struct nvme_tracker	*tr;
@@ -119,6 +127,9 @@ nvme_write_uio(struct nvme_namespace *ns
 
 	tr = nvme_allocate_tracker_uio(ns->ctrlr, uio);
 
+	if (tr == NULL)
+		return (ENOMEM);
+
 	cmd = &tr->cmd;
 	cmd->opc = NVME_OPC_WRITE;
 	cmd->nsid = ns->id;
@@ -136,6 +147,8 @@ nvme_write_uio(struct nvme_namespace *ns
 	    nvme_payload_map_uio, tr, 0);
 
 	KASSERT(err == 0, ("bus_dmamap_load_uio returned non-zero!\n"));
+
+	return (0);
 }
 
 int
@@ -143,6 +156,7 @@ nvme_ns_physio(struct cdev *dev, struct 
 {
 	struct nvme_namespace	*ns;
 	struct mtx		*mtx;
+	int			err;
 #if __FreeBSD_version > 900017
 	int			ref;
 #endif
@@ -160,11 +174,12 @@ nvme_ns_physio(struct cdev *dev, struct 
 
 	mtx_lock(mtx);
 	if (uio->uio_rw == UIO_READ)
-		nvme_read_uio(ns, uio);
+		err = nvme_read_uio(ns, uio);
 	else
-		nvme_write_uio(ns, uio);
+		err = nvme_write_uio(ns, uio);
 
-	msleep(uio, mtx, PRIBIO, "nvme_physio", 0);
+	if (err == 0)
+		msleep(uio, mtx, PRIBIO, "nvme_physio", 0);
 	mtx_unlock(mtx);
 
 #if __FreeBSD_version > 900017
@@ -173,7 +188,8 @@ nvme_ns_physio(struct cdev *dev, struct 
 	dev_relthread(dev);
 #endif
 
-	uio->uio_resid = 0;
+	if (err == 0)
+		uio->uio_resid = 0;
 
 	PRELE(curproc);
 	return (0);



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