Skip to content

Commit

Permalink
FreeBSD: add kqfilter support for zvol cdev
Browse files Browse the repository at this point in the history
The only event hooked up is NOTE_ATTRIB, which is triggered when the
device is resized.

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Rob Wing <rew@FreeBSD.org>
Closes #13773
  • Loading branch information
rob-wing authored and behlendorf committed Sep 6, 2022
1 parent 9d08874 commit 983096a
Showing 1 changed file with 64 additions and 0 deletions.
64 changes: 64 additions & 0 deletions module/os/freebsd/zfs/zvol_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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",
Expand All @@ -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;
Expand Down Expand Up @@ -601,6 +614,49 @@ zvol_geom_bio_getattr(struct bio *bp)
return (1);
}

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)
{
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 983096a

Please sign in to comment.