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>