aboutsummaryrefslogtreecommitdiffstats
path: root/module/os/freebsd
diff options
context:
space:
mode:
authorRob Wing <[email protected]>2022-02-01 20:00:57 -0900
committerBrian Behlendorf <[email protected]>2022-09-06 09:49:33 -0700
commit983096a1b46982a86d25fda2ccdf08079c3e51b9 (patch)
treebce032deb02a5a3664e840cfbc1ab411382ee27d /module/os/freebsd
parent9d0887402ba505fa7f82ffeb1e22c34fb07c83ed (diff)
FreeBSD: add kqfilter support for zvol cdev
The only event hooked up is NOTE_ATTRIB, which is triggered when the device is resized. Reviewed-by: Ryan Moeller <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Rob Wing <[email protected]> Closes #13773
Diffstat (limited to 'module/os/freebsd')
-rw-r--r--module/os/freebsd/zfs/zvol_os.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/module/os/freebsd/zfs/zvol_os.c b/module/os/freebsd/zfs/zvol_os.c
index ac030f753..8d2a6d776 100644
--- a/module/os/freebsd/zfs/zvol_os.c
+++ b/module/os/freebsd/zfs/zvol_os.c
@@ -92,6 +92,7 @@
#include <sys/zio_checksum.h>
#include <sys/zil_impl.h>
#include <sys/filio.h>
+#include <sys/freebsd_event.h>
#include <geom/geom.h>
#include <sys/zvol.h>
@@ -123,6 +124,7 @@ struct zvol_state_os {
struct zvol_state_dev {
struct cdev *zsd_cdev;
uint64_t zsd_sync_cnt;
+ struct selinfo zsd_selinfo;
} _zso_dev;
/* volmode=geom */
@@ -167,6 +169,7 @@ static d_ioctl_t zvol_cdev_ioctl;
static d_read_t zvol_cdev_read;
static d_write_t zvol_cdev_write;
static d_strategy_t zvol_geom_bio_strategy;
+static d_kqfilter_t zvol_cdev_kqfilter;
static struct cdevsw zvol_cdevsw = {
.d_name = "zvol",
@@ -178,6 +181,16 @@ static struct cdevsw zvol_cdevsw = {
.d_read = zvol_cdev_read,
.d_write = zvol_cdev_write,
.d_strategy = zvol_geom_bio_strategy,
+ .d_kqfilter = zvol_cdev_kqfilter,
+};
+
+static void zvol_filter_detach(struct knote *kn);
+static int zvol_filter_vnode(struct knote *kn, long hint);
+
+static struct filterops zvol_filterops_vnode = {
+ .f_isfd = 1,
+ .f_detach = zvol_filter_detach,
+ .f_event = zvol_filter_vnode,
};
extern uint_t zfs_geom_probe_vdev_key;
@@ -602,6 +615,49 @@ zvol_geom_bio_getattr(struct bio *bp)
}
static void
+zvol_filter_detach(struct knote *kn)
+{
+ zvol_state_t *zv;
+ struct zvol_state_dev *zsd;
+
+ zv = kn->kn_hook;
+ zsd = &zv->zv_zso->zso_dev;
+
+ knlist_remove(&zsd->zsd_selinfo.si_note, kn, 0);
+}
+
+static int
+zvol_filter_vnode(struct knote *kn, long hint)
+{
+ kn->kn_fflags |= kn->kn_sfflags & hint;
+
+ return (kn->kn_fflags != 0);
+}
+
+static int
+zvol_cdev_kqfilter(struct cdev *dev, struct knote *kn)
+{
+ zvol_state_t *zv;
+ struct zvol_state_dev *zsd;
+
+ zv = dev->si_drv2;
+ zsd = &zv->zv_zso->zso_dev;
+
+ 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 = &zvol_filterops_vnode;
+ kn->kn_hook = zv;
+ knlist_add(&zsd->zsd_selinfo.si_note, kn, 0);
+
+ return (0);
+}
+
+static void
zvol_geom_bio_strategy(struct bio *bp)
{
zvol_state_t *zv;
@@ -1306,6 +1362,8 @@ zvol_os_free(zvol_state_t *zv)
if (dev != NULL) {
ASSERT3P(dev->si_drv2, ==, NULL);
destroy_dev(dev);
+ knlist_clear(&zsd->zsd_selinfo.si_note, 0);
+ knlist_destroy(&zsd->zsd_selinfo.si_note);
}
}
@@ -1409,6 +1467,8 @@ zvol_os_create_minor(const char *name)
dev->si_iosize_max = MAXPHYS;
#endif
zsd->zsd_cdev = dev;
+ knlist_init_sx(&zsd->zsd_selinfo.si_note,
+ &zv->zv_state_lock);
}
}
(void) strlcpy(zv->zv_name, name, MAXPATHLEN);
@@ -1515,6 +1575,10 @@ zvol_os_update_volsize(zvol_state_t *zv, uint64_t volsize)
g_resize_provider(pp, zv->zv_volsize);
g_topology_unlock();
+ } else if (zv->zv_volmode == ZFS_VOLMODE_DEV) {
+ struct zvol_state_dev *zsd = &zv->zv_zso->zso_dev;
+
+ KNOTE_UNLOCKED(&zsd->zsd_selinfo.si_note, NOTE_ATTRIB);
}
return (0);
}