Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177608774
D45462.1794831992.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None
D45462.1794831992.diff
View Options
diff --git a/sys/dev/nvmf/host/nvmf.c b/sys/dev/nvmf/host/nvmf.c
--- a/sys/dev/nvmf/host/nvmf.c
+++ b/sys/dev/nvmf/host/nvmf.c
@@ -8,12 +8,14 @@
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/eventhandler.h>
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/memdesc.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/reboot.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
@@ -31,6 +33,8 @@
MALLOC_DEFINE(M_NVMF, "nvmf", "NVMe over Fabrics host");
static void nvmf_disconnect_task(void *arg, int pending);
+static void nvmf_shutdown_pre_sync(void *arg, int howto);
+static void nvmf_shutdown_post_sync(void *arg, int howto);
void
nvmf_complete(void *arg, const struct nvme_completion *cqe)
@@ -528,6 +532,11 @@
goto out;
}
+ sc->shutdown_pre_sync_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync,
+ nvmf_shutdown_pre_sync, sc, SHUTDOWN_PRI_FIRST);
+ sc->shutdown_post_sync_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
+ nvmf_shutdown_post_sync, sc, SHUTDOWN_PRI_FIRST);
+
return (0);
out:
if (sc->ns != NULL) {
@@ -698,6 +707,62 @@
return (error);
}
+static void
+nvmf_shutdown_pre_sync(void *arg, int howto)
+{
+ struct nvmf_softc *sc = arg;
+
+ if ((howto & RB_NOSYNC) != 0 || SCHEDULER_STOPPED())
+ return;
+
+ /*
+ * If this association is disconnected, abort any pending
+ * requests with an error to permit filesystems to unmount
+ * without hanging.
+ */
+ sx_xlock(&sc->connection_lock);
+ if (sc->admin != NULL || sc->detaching) {
+ sx_xunlock(&sc->connection_lock);
+ return;
+ }
+
+ for (u_int i = 0; i < sc->cdata->nn; i++) {
+ if (sc->ns[i] != NULL)
+ nvmf_shutdown_ns(sc->ns[i]);
+ }
+ nvmf_shutdown_sim(sc);
+ sx_xunlock(&sc->connection_lock);
+}
+
+static void
+nvmf_shutdown_post_sync(void *arg, int howto)
+{
+ struct nvmf_softc *sc = arg;
+
+ if ((howto & RB_NOSYNC) != 0 || SCHEDULER_STOPPED())
+ return;
+
+ /*
+ * If this association is connected, disconnect gracefully.
+ */
+ sx_xlock(&sc->connection_lock);
+ if (sc->admin == NULL || sc->detaching) {
+ sx_xunlock(&sc->connection_lock);
+ return;
+ }
+
+ callout_drain(&sc->ka_tx_timer);
+ callout_drain(&sc->ka_rx_timer);
+
+ nvmf_shutdown_controller(sc);
+ for (u_int i = 0; i < sc->num_io_queues; i++) {
+ nvmf_destroy_qp(sc->io[i]);
+ }
+ nvmf_destroy_qp(sc->admin);
+ sc->admin = NULL;
+ sx_xunlock(&sc->connection_lock);
+}
+
static int
nvmf_detach(device_t dev)
{
@@ -710,6 +775,9 @@
sc->detaching = true;
sx_xunlock(&sc->connection_lock);
+ EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->shutdown_pre_sync_eh);
+ EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->shutdown_post_sync_eh);
+
nvmf_destroy_sim(sc);
for (i = 0; i < sc->cdata->nn; i++) {
if (sc->ns[i] != NULL)
@@ -1006,9 +1074,6 @@
DEVMETHOD(device_probe, nvmf_probe),
DEVMETHOD(device_attach, nvmf_attach),
DEVMETHOD(device_detach, nvmf_detach),
-#if 0
- DEVMETHOD(device_shutdown, nvmf_shutdown),
-#endif
DEVMETHOD_END
};
diff --git a/sys/dev/nvmf/host/nvmf_ns.c b/sys/dev/nvmf/host/nvmf_ns.c
--- a/sys/dev/nvmf/host/nvmf_ns.c
+++ b/sys/dev/nvmf/host/nvmf_ns.c
@@ -29,6 +29,7 @@
u_int flags;
uint32_t lba_size;
bool disconnected;
+ bool shutdown;
TAILQ_HEAD(, bio) pending_bios;
struct mtx lock;
@@ -89,7 +90,7 @@
bio->bio_driver2 = 0;
mtx_lock(&ns->lock);
if (ns->disconnected) {
- if (nvmf_fail_disconnect) {
+ if (nvmf_fail_disconnect || ns->shutdown) {
mtx_unlock(&ns->lock);
bio->bio_error = ECONNABORTED;
bio->bio_flags |= BIO_ERROR;
@@ -211,7 +212,7 @@
mtx_lock(&ns->lock);
if (ns->disconnected) {
- if (nvmf_fail_disconnect) {
+ if (nvmf_fail_disconnect || ns->shutdown) {
error = ECONNABORTED;
} else {
TAILQ_INSERT_TAIL(&ns->pending_bios, bio, bio_queue);
@@ -429,6 +430,28 @@
}
}
+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)
{
diff --git a/sys/dev/nvmf/host/nvmf_sim.c b/sys/dev/nvmf/host/nvmf_sim.c
--- a/sys/dev/nvmf/host/nvmf_sim.c
+++ b/sys/dev/nvmf/host/nvmf_sim.c
@@ -40,7 +40,10 @@
return;
if (nvmf_cqe_aborted(&ccb->nvmeio.cpl)) {
- if (nvmf_fail_disconnect)
+ struct cam_sim *sim = xpt_path_sim(ccb->ccb_h.path);
+ struct nvmf_softc *sc = cam_sim_softc(sim);
+
+ if (nvmf_fail_disconnect || sc->sim_shutdown)
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
else
ccb->ccb_h.status = CAM_REQUEUE_REQ;
@@ -109,7 +112,7 @@
mtx_lock(&sc->sim_mtx);
if (sc->sim_disconnected) {
mtx_unlock(&sc->sim_mtx);
- if (nvmf_fail_disconnect)
+ if (nvmf_fail_disconnect || sc->sim_shutdown)
nvmeio->ccb_h.status = CAM_DEV_NOT_THERE;
else
nvmeio->ccb_h.status = CAM_REQUEUE_REQ;
@@ -325,6 +328,15 @@
xpt_release_simq(sc->sim, 1);
}
+void
+nvmf_shutdown_sim(struct nvmf_softc *sc)
+{
+ mtx_lock(&sc->sim_mtx);
+ sc->sim_shutdown = true;
+ mtx_unlock(&sc->sim_mtx);
+ xpt_release_simq(sc->sim, 1);
+}
+
void
nvmf_destroy_sim(struct nvmf_softc *sc)
{
diff --git a/sys/dev/nvmf/host/nvmf_var.h b/sys/dev/nvmf/host/nvmf_var.h
--- a/sys/dev/nvmf/host/nvmf_var.h
+++ b/sys/dev/nvmf/host/nvmf_var.h
@@ -9,6 +9,7 @@
#define __NVMF_VAR_H__
#include <sys/_callout.h>
+#include <sys/_eventhandler.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/_sx.h>
@@ -42,6 +43,7 @@
struct cam_path *path;
struct mtx sim_mtx;
bool sim_disconnected;
+ bool sim_shutdown;
struct nvmf_namespace **ns;
@@ -82,6 +84,9 @@
u_int num_aer;
struct nvmf_aer *aer;
+
+ eventhandler_tag shutdown_pre_sync_eh;
+ eventhandler_tag shutdown_post_sync_eh;
};
struct nvmf_request {
@@ -187,6 +192,7 @@
const struct nvme_namespace_data *data);
void nvmf_disconnect_ns(struct nvmf_namespace *ns);
void nvmf_reconnect_ns(struct nvmf_namespace *ns);
+void nvmf_shutdown_ns(struct nvmf_namespace *ns);
void nvmf_destroy_ns(struct nvmf_namespace *ns);
bool nvmf_update_ns(struct nvmf_namespace *ns,
const struct nvme_namespace_data *data);
@@ -206,6 +212,7 @@
int nvmf_init_sim(struct nvmf_softc *sc);
void nvmf_disconnect_sim(struct nvmf_softc *sc);
void nvmf_reconnect_sim(struct nvmf_softc *sc);
+void nvmf_shutdown_sim(struct nvmf_softc *sc);
void nvmf_destroy_sim(struct nvmf_softc *sc);
void nvmf_sim_rescan_ns(struct nvmf_softc *sc, uint32_t id);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 16, 12:26 PM (19 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41776890
Default Alt Text
D45462.1794831992.diff (6 KB)
Attached To
Mode
D45462: nvmf: Handle shutdowns more gracefully
Attached
Detach File
Event Timeline