The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=38e1083940a274783cc9e8ebd845e35df6d0a1ff

commit 38e1083940a274783cc9e8ebd845e35df6d0a1ff
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2025-01-31 20:47:58 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2025-01-31 20:47:58 +0000

    nvmf: Add NVMF_CONNECTION_STATUS ioctl
    
    This returns an nvlist indicating if a Fabrics host is connected and
    the time of the most recent disconnection.
    
    Reviewed by:    imp
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D48219
---
 lib/libnvmf/libnvmf.h        |  5 +++++
 lib/libnvmf/nvmf_host.c      |  7 +++++++
 sys/dev/nvmf/host/nvmf.c     | 25 +++++++++++++++++++++++++
 sys/dev/nvmf/host/nvmf_var.h |  2 ++
 sys/dev/nvmf/nvmf.h          | 10 ++++++++++
 5 files changed, 49 insertions(+)

diff --git a/lib/libnvmf/libnvmf.h b/lib/libnvmf/libnvmf.h
index f34ccdb177e7..9840e190a24f 100644
--- a/lib/libnvmf/libnvmf.h
+++ b/lib/libnvmf/libnvmf.h
@@ -372,4 +372,9 @@ int nvmf_reconnect_host(int fd, const struct 
nvme_discovery_log_entry *dle,
     const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues,
     struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata);
 
+/*
+ * Fetch connection status from an existing kernel host.
+ */
+int    nvmf_connection_status(int fd, nvlist_t **nvlp);
+
 #endif /* !__LIBNVMF_H__ */
diff --git a/lib/libnvmf/nvmf_host.c b/lib/libnvmf/nvmf_host.c
index e194522870d1..89cdd5c6bb70 100644
--- a/lib/libnvmf/nvmf_host.c
+++ b/lib/libnvmf/nvmf_host.c
@@ -5,6 +5,7 @@
  * Written by: John Baldwin <j...@freebsd.org>
  */
 
+#include <sys/nv.h>
 #include <sys/sysctl.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -1001,3 +1002,9 @@ out:
        (void)nvmf_free_qpair(admin_qp);
        return (error);
 }
+
+int
+nvmf_connection_status(int fd, nvlist_t **nvlp)
+{
+       return (nvmf_read_ioc_nv(fd, NVMF_CONNECTION_STATUS, nvlp));
+}
diff --git a/sys/dev/nvmf/host/nvmf.c b/sys/dev/nvmf/host/nvmf.c
index befe93dbbbc0..dbdd4568bdf1 100644
--- a/sys/dev/nvmf/host/nvmf.c
+++ b/sys/dev/nvmf/host/nvmf.c
@@ -654,6 +654,7 @@ nvmf_disconnect_task(void *arg, int pending __unused)
                return;
        }
 
+       nanotime(&sc->last_disconnect);
        callout_drain(&sc->ka_tx_timer);
        callout_drain(&sc->ka_rx_timer);
        sc->ka_traffic = false;
@@ -1085,6 +1086,27 @@ nvmf_reconnect_params(struct nvmf_softc *sc, struct 
nvmf_ioc_nv *nv)
        return (error);
 }
 
+static int
+nvmf_connection_status(struct nvmf_softc *sc, struct nvmf_ioc_nv *nv)
+{
+       nvlist_t *nvl, *nvl_ts;
+       int error;
+
+       nvl = nvlist_create(0);
+       nvl_ts = nvlist_create(0);
+
+       sx_slock(&sc->connection_lock);
+       nvlist_add_bool(nvl, "connected", sc->admin != NULL);
+       nvlist_add_number(nvl_ts, "tv_sec", sc->last_disconnect.tv_sec);
+       nvlist_add_number(nvl_ts, "tv_nsec", sc->last_disconnect.tv_nsec);
+       sx_sunlock(&sc->connection_lock);
+       nvlist_move_nvlist(nvl, "last_disconnect", nvl_ts);
+
+       error = nvmf_pack_ioc_nvlist(nvl, nv);
+       nvlist_destroy(nvl);
+       return (error);
+}
+
 static int
 nvmf_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
     struct thread *td)
@@ -1116,6 +1138,9 @@ nvmf_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, 
int flag,
        case NVMF_RECONNECT_HOST:
                nv = (struct nvmf_ioc_nv *)arg;
                return (nvmf_reconnect_host(sc, nv));
+       case NVMF_CONNECTION_STATUS:
+               nv = (struct nvmf_ioc_nv *)arg;
+               return (nvmf_connection_status(sc, nv));
        default:
                return (ENOTTY);
        }
diff --git a/sys/dev/nvmf/host/nvmf_var.h b/sys/dev/nvmf/host/nvmf_var.h
index 470f76527e46..e45a31f413a4 100644
--- a/sys/dev/nvmf/host/nvmf_var.h
+++ b/sys/dev/nvmf/host/nvmf_var.h
@@ -86,6 +86,8 @@ struct nvmf_softc {
 
        nvlist_t *rparams;
 
+       struct timespec last_disconnect;
+
        eventhandler_tag shutdown_pre_sync_eh;
        eventhandler_tag shutdown_post_sync_eh;
 };
diff --git a/sys/dev/nvmf/nvmf.h b/sys/dev/nvmf/nvmf.h
index 79facfd4ede2..d4e7b1511e9d 100644
--- a/sys/dev/nvmf/nvmf.h
+++ b/sys/dev/nvmf/nvmf.h
@@ -90,6 +90,15 @@ struct nvmf_ioc_nv {
  * bool                                data_digests
  */
 
+/*
+ * The fields in the nvlist for NVMF_CONNECTION_STATUS are:
+ *
+ * bool                                connected
+ * timespec nvlist             last_disconnect
+ *  number                     tv_sec
+ *  number                     tv_nsec
+ */
+
 /*
  * The fields in the nvlist for handing off a controller qpair are:
  *
@@ -107,5 +116,6 @@ struct nvmf_ioc_nv {
 /* Operations on /dev/nvmeX */
 #define        NVMF_RECONNECT_PARAMS   _IOWR('n', 203, struct nvmf_ioc_nv)
 #define        NVMF_RECONNECT_HOST     _IOW('n', 204, struct nvmf_ioc_nv)
+#define        NVMF_CONNECTION_STATUS  _IOWR('n', 205, struct nvmf_ioc_nv)
 
 #endif /* !__NVMF_H__ */

Reply via email to