mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-25 02:49:32 +03:00
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 <ryan@iXsystems.com> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Signed-off-by: Rob Wing <rew@FreeBSD.org> Closes #13773
This commit is contained in:
parent
9d0887402b
commit
983096a1b4
@ -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;
|
||||
@ -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)
|
||||
{
|
||||
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user