diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c --- a/sys/dev/null/null.c +++ b/sys/dev/null/null.c @@ -4,6 +4,7 @@ * Copyright (c) 2000 Mark R. V. Murray & Jeroen C. van Gelderen * Copyright (c) 2001-2004 Mark R. V. Murray * Copyright (c) 2014 Eitan Adler + * Copyright (c) 2025 Pietro Cerutti * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -48,18 +50,30 @@ static struct cdev *null_dev; static struct cdev *zero_dev; +#define FULL_NAME "full" +#define NULL_NAME "null" +#define ZERO_NAME "zero" + static d_write_t full_write; static d_write_t null_write; static d_ioctl_t null_ioctl; static d_ioctl_t zero_ioctl; static d_read_t zero_read; +static d_kqfilter_t null_kqfilter; +static int immediate_event(struct knote *kn, long hint); + +static const struct filterops immediate_filterops = { + .f_isfd = 1, + .f_event = immediate_event +}; static struct cdevsw full_cdevsw = { .d_version = D_VERSION, .d_read = zero_read, .d_write = full_write, .d_ioctl = zero_ioctl, - .d_name = "full", + .d_kqfilter = null_kqfilter, + .d_name = FULL_NAME, }; static struct cdevsw null_cdevsw = { @@ -67,7 +81,8 @@ .d_read = (d_read_t *)nullop, .d_write = null_write, .d_ioctl = null_ioctl, - .d_name = "null", + .d_kqfilter = null_kqfilter, + .d_name = NULL_NAME, }; static struct cdevsw zero_cdevsw = { @@ -75,7 +90,8 @@ .d_read = zero_read, .d_write = null_write, .d_ioctl = zero_ioctl, - .d_name = "zero", + .d_kqfilter = null_kqfilter, + .d_name = ZERO_NAME, .d_flags = D_MMAP_ANON, }; @@ -174,11 +190,11 @@ if (bootverbose) printf("null: \n"); full_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &full_cdevsw, 0, - NULL, UID_ROOT, GID_WHEEL, 0666, "full"); + NULL, UID_ROOT, GID_WHEEL, 0666, FULL_NAME); null_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &null_cdevsw, 0, - NULL, UID_ROOT, GID_WHEEL, 0666, "null"); + NULL, UID_ROOT, GID_WHEEL, 0666, NULL_NAME); zero_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &zero_cdevsw, 0, - NULL, UID_ROOT, GID_WHEEL, 0666, "zero"); + NULL, UID_ROOT, GID_WHEEL, 0666, ZERO_NAME); break; case MOD_UNLOAD: @@ -197,5 +213,25 @@ return (0); } +static int +immediate_event(struct knote *kn, long hint) +{ + return 1; +} + +static int +null_kqfilter(struct cdev *dev, struct knote *kn) +{ + switch (kn->kn_filter) + { + case EVFILT_READ: + case EVFILT_WRITE: + kn->kn_fop = &immediate_filterops; + return (0); + default: + return(EOPNOTSUPP); + } +} + DEV_MODULE(null, null_modevent, NULL); MODULE_VERSION(null, 1);