diff options
Diffstat (limited to 'sys/dev/nvmf/host/nvmf_ns.c')
-rw-r--r-- | sys/dev/nvmf/host/nvmf_ns.c | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/sys/dev/nvmf/host/nvmf_ns.c b/sys/dev/nvmf/host/nvmf_ns.c index 3ce434bf7c50..4215c8295d2e 100644 --- a/sys/dev/nvmf/host/nvmf_ns.c +++ b/sys/dev/nvmf/host/nvmf_ns.c @@ -18,7 +18,7 @@ #include <sys/proc.h> #include <sys/refcount.h> #include <sys/sbuf.h> -#include <machine/stdarg.h> +#include <sys/stdarg.h> #include <dev/nvme/nvme.h> #include <dev/nvmf/host/nvmf_var.h> @@ -29,6 +29,7 @@ struct nvmf_namespace { u_int flags; uint32_t lba_size; bool disconnected; + bool shutdown; TAILQ_HEAD(, bio) pending_bios; struct mtx lock; @@ -49,7 +50,7 @@ ns_printf(struct nvmf_namespace *ns, const char *fmt, ...) sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); sbuf_set_drain(&sb, sbuf_printf_drain, NULL); - sbuf_printf(&sb, "%sns%u: ", device_get_nameunit(ns->sc->dev), + sbuf_printf(&sb, "%sn%u: ", device_get_nameunit(ns->sc->dev), ns->id); va_start(ap, fmt); @@ -84,13 +85,22 @@ nvmf_ns_biodone(struct bio *bio) ns = bio->bio_dev->si_drv1; /* If a request is aborted, resubmit or queue it for resubmission. */ - if (bio->bio_error == ECONNABORTED) { + if (bio->bio_error == ECONNABORTED && !nvmf_fail_disconnect) { bio->bio_error = 0; bio->bio_driver2 = 0; mtx_lock(&ns->lock); if (ns->disconnected) { - TAILQ_INSERT_TAIL(&ns->pending_bios, bio, bio_queue); - mtx_unlock(&ns->lock); + if (nvmf_fail_disconnect || ns->shutdown) { + mtx_unlock(&ns->lock); + bio->bio_error = ECONNABORTED; + bio->bio_flags |= BIO_ERROR; + bio->bio_resid = bio->bio_bcount; + biodone(bio); + } else { + TAILQ_INSERT_TAIL(&ns->pending_bios, bio, + bio_queue); + mtx_unlock(&ns->lock); + } } else { mtx_unlock(&ns->lock); nvmf_ns_strategy(bio); @@ -163,6 +173,7 @@ nvmf_ns_submit_bio(struct nvmf_namespace *ns, struct bio *bio) struct nvme_dsm_range *dsm_range; struct memdesc mem; uint64_t lba, lba_count; + int error; dsm_range = NULL; memset(&cmd, 0, sizeof(cmd)); @@ -201,10 +212,15 @@ nvmf_ns_submit_bio(struct nvmf_namespace *ns, struct bio *bio) mtx_lock(&ns->lock); if (ns->disconnected) { - TAILQ_INSERT_TAIL(&ns->pending_bios, bio, bio_queue); + if (nvmf_fail_disconnect || ns->shutdown) { + error = ECONNABORTED; + } else { + TAILQ_INSERT_TAIL(&ns->pending_bios, bio, bio_queue); + error = 0; + } mtx_unlock(&ns->lock); free(dsm_range, M_NVMF); - return (0); + return (error); } req = nvmf_allocate_request(nvmf_select_io_queue(ns->sc), &cmd, @@ -258,9 +274,8 @@ nvmf_ns_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, return (nvmf_passthrough_cmd(ns->sc, pt, false)); case NVME_GET_NSID: gnsid = (struct nvme_get_nsid *)arg; - strncpy(gnsid->cdev, device_get_nameunit(ns->sc->dev), + strlcpy(gnsid->cdev, device_get_nameunit(ns->sc->dev), sizeof(gnsid->cdev)); - gnsid->cdev[sizeof(gnsid->cdev) - 1] = '\0'; gnsid->nsid = ns->id; return (0); case DIOCGMEDIASIZE: @@ -314,7 +329,7 @@ static struct cdevsw nvmf_ns_cdevsw = { struct nvmf_namespace * nvmf_init_ns(struct nvmf_softc *sc, uint32_t id, - struct nvme_namespace_data *data) + const struct nvme_namespace_data *data) { struct make_dev_args mda; struct nvmf_namespace *ns; @@ -372,10 +387,12 @@ nvmf_init_ns(struct nvmf_softc *sc, uint32_t id, mda.mda_gid = GID_WHEEL; mda.mda_mode = 0600; mda.mda_si_drv1 = ns; - error = make_dev_s(&mda, &ns->cdev, "%sns%u", + error = make_dev_s(&mda, &ns->cdev, "%sn%u", device_get_nameunit(sc->dev), id); if (error != 0) goto fail; + ns->cdev->si_drv2 = make_dev_alias(ns->cdev, "%sns%u", + device_get_nameunit(sc->dev), id); ns->cdev->si_flags |= SI_UNMAPPED; @@ -414,11 +431,35 @@ nvmf_reconnect_ns(struct nvmf_namespace *ns) } void +nvmf_shutdown_ns(struct nvmf_namespace *ns) +{ + TAILQ_HEAD(, bio) bios; + struct bio *bio; + + mtx_lock(&ns->lock); + ns->shutdown = true; + TAILQ_INIT(&bios); + TAILQ_CONCAT(&bios, &ns->pending_bios, bio_queue); + mtx_unlock(&ns->lock); + + while (!TAILQ_EMPTY(&bios)) { + bio = TAILQ_FIRST(&bios); + TAILQ_REMOVE(&bios, bio, bio_queue); + bio->bio_error = ECONNABORTED; + bio->bio_flags |= BIO_ERROR; + bio->bio_resid = bio->bio_bcount; + biodone(bio); + } +} + +void nvmf_destroy_ns(struct nvmf_namespace *ns) { TAILQ_HEAD(, bio) bios; struct bio *bio; + if (ns->cdev->si_drv2 != NULL) + destroy_dev(ns->cdev->si_drv2); destroy_dev(ns->cdev); /* @@ -451,7 +492,8 @@ nvmf_destroy_ns(struct nvmf_namespace *ns) } bool -nvmf_update_ns(struct nvmf_namespace *ns, struct nvme_namespace_data *data) +nvmf_update_ns(struct nvmf_namespace *ns, + const struct nvme_namespace_data *data) { uint8_t lbads, lbaf; |