svn commit: r241657 - in head/sys/dev: nvd nvme
Jim Harris
jimharris at FreeBSD.org
Thu Oct 18 00:32:08 UTC 2012
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);
More information about the svn-src-all
mailing list