git: afbb26b58b93 - main - devctl: allow to register a hook to receive the events

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Thu, 01 Jun 2023 21:02:27 UTC
The branch main has been updated by bapt:

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

commit afbb26b58b93bddf0e8720698cd712eac7f8c13d
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2023-06-01 21:01:40 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2023-06-01 21:01:40 +0000

    devctl: allow to register a hook to receive the events
    
    In preparation for netlink sysvent add a function that allow
    registering a function to hook the events and also send it via
    another kernel module (nlsysvent will be that module).
    
    Prepare a static list of known existing events in the kernel that
    will be used to prepopulate nlsysvent multicast group (one per event)
    
    Reviewed by:    imp
    Differential Revision:  https://reviews.freebsd.org/D37573
---
 sys/kern/kern_devctl.c | 38 ++++++++++++++++++++++++++++++++++++++
 sys/sys/devctl.h       | 28 ++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/sys/kern/kern_devctl.c b/sys/kern/kern_devctl.c
index d40559bba8f1..b51b135c38dc 100644
--- a/sys/kern/kern_devctl.c
+++ b/sys/kern/kern_devctl.c
@@ -134,6 +134,10 @@ static struct filterops devctl_rfiltops = {
 static struct cdev *devctl_dev;
 static void devaddq(const char *type, const char *what, device_t dev);
 
+static struct devctlbridge {
+	send_event_f *send_f;
+} devctl_notify_hook = { .send_f = NULL };
+
 static void
 devctl_init(void)
 {
@@ -435,6 +439,8 @@ devctl_notify(const char *system, const char *subsystem, const char *type,
 
 	if (system == NULL || subsystem == NULL || type == NULL)
 		return;
+	if (devctl_notify_hook.send_f != NULL)
+		devctl_notify_hook.send_f(system, subsystem, type, data);
 	dei = devctl_alloc_dei_sb(&sb);
 	if (dei == NULL)
 		return;
@@ -478,6 +484,7 @@ devaddq(const char *type, const char *what, device_t dev)
 	struct dev_event_info *dei;
 	const char *parstr;
 	struct sbuf sb;
+	size_t beginlen;
 
 	dei = devctl_alloc_dei_sb(&sb);
 	if (dei == NULL)
@@ -485,6 +492,7 @@ devaddq(const char *type, const char *what, device_t dev)
 	sbuf_cpy(&sb, type);
 	sbuf_cat(&sb, what);
 	sbuf_cat(&sb, " at ");
+	beginlen = sbuf_len(&sb);
 
 	/* Add in the location */
 	bus_child_location(dev, &sb);
@@ -503,6 +511,23 @@ devaddq(const char *type, const char *what, device_t dev)
 	sbuf_putc(&sb, '\n');
 	if (sbuf_finish(&sb) != 0)
 		goto bad;
+	if (devctl_notify_hook.send_f != NULL) {
+		const char *t;
+
+		switch (*type) {
+		case '+':
+			t = "ATTACH";
+			break;
+		case '-':
+			t = "DETACH";
+			break;
+		default:
+			t = "NOMATCH";
+			break;
+		}
+		devctl_notify_hook.send_f("device",
+		    what, t, sbuf_data(&sb) + beginlen);
+	}
 	devctl_queue(dei);
 	return;
 bad:
@@ -568,3 +593,16 @@ devctl_safe_quote_sb(struct sbuf *sb, const char *src)
 		sbuf_putc(sb, *src++);
 	}
 }
+
+void
+devctl_set_notify_hook(send_event_f *hook)
+{
+	devctl_notify_hook.send_f = hook;
+}
+
+void
+devctl_unset_notify_hook(void)
+{
+	devctl_notify_hook.send_f = NULL;
+}
+
diff --git a/sys/sys/devctl.h b/sys/sys/devctl.h
index b72cd28dfce8..5b613cf427df 100644
--- a/sys/sys/devctl.h
+++ b/sys/sys/devctl.h
@@ -12,11 +12,39 @@
  * devctl hooks.  Typically one should use the devctl_notify
  * hook to send the message.
  */
+
+static const char *devctl_systems[] = {
+	"ACPI",
+	"AEON",
+	"CAM",
+	"CARP",
+	"coretemp",
+	"DEVFS",
+	"device",
+	"ETHERNET",
+	"GEOM",
+	"HYPERV_NIC_VF",
+	"IFNET",
+	"INFINIBAND",
+	"KERNEL",
+	"nvme",
+	"PMU",
+	"RCTL",
+	"USB",
+	"VFS",
+	"VT",
+	"ZFS",
+};
+
 bool devctl_process_running(void);
 void devctl_notify(const char *__system, const char *__subsystem,
     const char *__type, const char *__data);
 struct sbuf;
 void devctl_safe_quote_sb(struct sbuf *__sb, const char *__src);
+typedef void send_event_f(const char *system, const char *subsystem,
+    const char *type, const char *data);
+void devctl_set_notify_hook(send_event_f *hook);
+void devctl_unset_notify_hook(void);
 #endif
 
 #endif /* _SYS_DEVCTL_H_ */