git: a50e92cc203c - main - geom: add kqfilter support for geom dev

From: Robert Wing <rew_at_FreeBSD.org>
Date: Tue, 18 Jan 2022 20:03:13 UTC
The branch main has been updated by rew:

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

commit a50e92cc203c1e3dd2cca03410b568f76694895c
Author:     Robert Wing <rew@FreeBSD.org>
AuthorDate: 2022-01-18 19:54:59 +0000
Commit:     Robert Wing <rew@FreeBSD.org>
CommitDate: 2022-01-18 19:54:59 +0000

    geom: add kqfilter support for geom dev
    
    The only event hooked up is NOTE_ATTRIB, which is triggered when the
    device is resized. Support for other NOTE_* events to follow.
    
    Reviewed by:    kib, jhb
    Differential Revision:  https://reviews.freebsd.org/D33402
---
 sys/geom/geom_dev.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 9c33ab71e6c8..fedd9df96274 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/disk.h>
 #include <sys/fcntl.h>
 #include <sys/limits.h>
+#include <sys/selinfo.h>
 #include <sys/sysctl.h>
 #include <geom/geom.h>
 #include <geom/geom_int.h>
@@ -65,6 +66,7 @@ struct g_dev_softc {
 	struct cdev	*sc_alias;
 	int		 sc_open;
 	u_int		 sc_active;
+	struct selinfo	 sc_selinfo;
 #define	SC_A_DESTROY	(1 << 31)
 #define	SC_A_OPEN	(1 << 30)
 #define	SC_A_ACTIVE	(SC_A_OPEN - 1)
@@ -74,6 +76,16 @@ static d_open_t		g_dev_open;
 static d_close_t	g_dev_close;
 static d_strategy_t	g_dev_strategy;
 static d_ioctl_t	g_dev_ioctl;
+static d_kqfilter_t	g_dev_kqfilter;
+
+static void		gdev_filter_detach(struct knote *kn);
+static int		gdev_filter_vnode(struct knote *kn, long hint);
+
+static struct filterops gdev_filterops_vnode = {
+	.f_isfd = 1,
+	.f_detach = gdev_filter_detach,
+	.f_event = gdev_filter_vnode,
+};
 
 static struct cdevsw g_dev_cdevsw = {
 	.d_version =	D_VERSION,
@@ -85,6 +97,7 @@ static struct cdevsw g_dev_cdevsw = {
 	.d_strategy =	g_dev_strategy,
 	.d_name =	"g_dev",
 	.d_flags =	D_DISK | D_TRACKCLOSE,
+	.d_kqfilter =	g_dev_kqfilter,
 };
 
 static g_init_t g_dev_init;
@@ -214,6 +227,8 @@ g_dev_destroy(void *arg, int flags __unused)
 	g_trace(G_T_TOPOLOGY, "g_dev_destroy(%p(%s))", cp, gp->name);
 	snprintf(buf, sizeof(buf), "cdev=%s", gp->name);
 	devctl_notify("GEOM", "DEV", "DESTROY", buf);
+	knlist_clear(&sc->sc_selinfo.si_note, 0);
+	knlist_destroy(&sc->sc_selinfo.si_note);
 	if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
 		g_access(cp, -cp->acr, -cp->acw, -cp->ace);
 	g_detach(cp);
@@ -305,8 +320,12 @@ g_dev_attrchanged(struct g_consumer *cp, const char *attr)
 static void
 g_dev_resize(struct g_consumer *cp)
 {
+	struct g_dev_softc *sc;
 	char buf[SPECNAMELEN + 6];
 
+	sc = cp->private;
+	KNOTE_UNLOCKED(&sc->sc_selinfo.si_note, NOTE_ATTRIB);
+
 	snprintf(buf, sizeof(buf), "cdev=%s", cp->provider->name);
 	devctl_notify("GEOM", "DEV", "SIZECHANGE", buf);
 }
@@ -378,6 +397,7 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
 	dev = sc->sc_dev;
 	dev->si_flags |= SI_UNMAPPED;
 	dev->si_iosize_max = maxphys;
+	knlist_init_mtx(&sc->sc_selinfo.si_note, &sc->sc_mtx);
 	error = init_dumpdev(dev);
 	if (error != 0)
 		printf("%s: init_dumpdev() failed (gp->name=%s, error=%d)\n",
@@ -896,4 +916,43 @@ g_dev_orphan(struct g_consumer *cp)
 	destroy_dev_sched_cb(dev, g_dev_callback, cp);
 }
 
+static void
+gdev_filter_detach(struct knote *kn)
+{
+	struct g_dev_softc *sc;
+
+	sc = kn->kn_hook;
+
+	knlist_remove(&sc->sc_selinfo.si_note, kn, 0);
+}
+
+static int
+gdev_filter_vnode(struct knote *kn, long hint)
+{
+	kn->kn_fflags |= kn->kn_sfflags & hint;
+
+	return (kn->kn_fflags != 0);
+}
+
+static int
+g_dev_kqfilter(struct cdev *dev, struct knote *kn)
+{
+	struct g_dev_softc *sc;
+
+	sc = dev->si_drv1;
+
+	if (kn->kn_filter != EVFILT_VNODE)
+		return (EINVAL);
+
+	/* XXX: extend support for other NOTE_* events */
+	if (kn->kn_sfflags != NOTE_ATTRIB)
+		return (EINVAL);
+
+	kn->kn_fop = &gdev_filterops_vnode;
+	kn->kn_hook = sc;
+	knlist_add(&sc->sc_selinfo.si_note, kn, 0);
+
+	return (0);
+}
+
 DECLARE_GEOM_CLASS(g_dev_class, g_dev);