On Mon, Sep 18, 2023 at 02:12:21PM +0300, Vitaliy Makkoveev wrote: > On Mon, Sep 18, 2023 at 02:03:08PM +0300, Vitaliy Makkoveev wrote: > > Also use this mutex to protect `evqueue_head', `evqueue_tail' and > > `evqueue_count'. > > > > Sorry, the right diff:
OK bluhm@ > Index: sys/dev/hotplug.c > =================================================================== > RCS file: /cvs/src/sys/dev/hotplug.c,v > retrieving revision 1.23 > diff -u -p -r1.23 hotplug.c > --- sys/dev/hotplug.c 8 Sep 2023 20:00:27 -0000 1.23 > +++ sys/dev/hotplug.c 18 Sep 2023 11:09:12 -0000 > @@ -22,27 +22,39 @@ > #include <sys/param.h> > #include <sys/systm.h> > #include <sys/device.h> > +#include <sys/event.h> > #include <sys/fcntl.h> > #include <sys/hotplug.h> > #include <sys/ioctl.h> > -#include <sys/selinfo.h> > +#include <sys/mutex.h> > #include <sys/vnode.h> > > #define HOTPLUG_MAXEVENTS 64 > > +/* > + * Locks used to protect struct members and global data > + * M hotplug_mtx > + */ > + > +static struct mutex hotplug_mtx = MUTEX_INITIALIZER(IPL_MPFLOOR); > + > static int opened; > static struct hotplug_event evqueue[HOTPLUG_MAXEVENTS]; > -static int evqueue_head, evqueue_tail, evqueue_count; > -static struct selinfo hotplug_sel; > +static int evqueue_head, evqueue_tail, evqueue_count; /* [M] */ > +static struct klist hotplug_klist; /* [M] */ > > void filt_hotplugrdetach(struct knote *); > int filt_hotplugread(struct knote *, long); > +int filt_hotplugmodify(struct kevent *, struct knote *); > +int filt_hotplugprocess(struct knote *, struct kevent *); > > const struct filterops hotplugread_filtops = { > - .f_flags = FILTEROP_ISFD, > + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, > .f_attach = NULL, > .f_detach = filt_hotplugrdetach, > .f_event = filt_hotplugread, > + .f_modify = filt_hotplugmodify, > + .f_process = filt_hotplugprocess, > }; > > #define EVQUEUE_NEXT(p) (p == HOTPLUG_MAXEVENTS - 1 ? 0 : p + 1) > @@ -60,6 +72,8 @@ hotplugattach(int count) > evqueue_head = 0; > evqueue_tail = 0; > evqueue_count = 0; > + > + klist_init_mutex(&hotplug_klist, &hotplug_mtx); > } > > void > @@ -87,7 +101,9 @@ hotplug_device_detach(enum devclass clas > int > hotplug_put_event(struct hotplug_event *he) > { > + mtx_enter(&hotplug_mtx); > if (evqueue_count == HOTPLUG_MAXEVENTS && opened) { > + mtx_leave(&hotplug_mtx); > printf("hotplug: event lost, queue full\n"); > return (1); > } > @@ -98,24 +114,21 @@ hotplug_put_event(struct hotplug_event * > evqueue_tail = EVQUEUE_NEXT(evqueue_tail); > else > evqueue_count++; > + knote_locked(&hotplug_klist, 0); > wakeup(&evqueue); > - selwakeup(&hotplug_sel); > + mtx_leave(&hotplug_mtx); > return (0); > } > > int > hotplug_get_event(struct hotplug_event *he) > { > - int s; > - > if (evqueue_count == 0) > return (1); > > - s = splbio(); > *he = evqueue[evqueue_tail]; > evqueue_tail = EVQUEUE_NEXT(evqueue_tail); > evqueue_count--; > - splx(s); > return (0); > } > > @@ -137,8 +150,11 @@ hotplugclose(dev_t dev, int flag, int mo > { > struct hotplug_event he; > > + mtx_enter(&hotplug_mtx); > while (hotplug_get_event(&he) == 0) > continue; > + mtx_leave(&hotplug_mtx); > + klist_invalidate(&hotplug_klist); > opened = 0; > return (0); > } > @@ -152,16 +168,23 @@ hotplugread(dev_t dev, struct uio *uio, > if (uio->uio_resid != sizeof(he)) > return (EINVAL); > > -again: > - if (hotplug_get_event(&he) == 0) > - return (uiomove(&he, sizeof(he), uio)); > - if (flags & IO_NDELAY) > - return (EAGAIN); > - > - error = tsleep_nsec(&evqueue, PRIBIO | PCATCH, "htplev", INFSLP); > - if (error) > - return (error); > - goto again; > + mtx_enter(&hotplug_mtx); > + while (hotplug_get_event(&he)) { > + if (flags & IO_NDELAY) { > + mtx_leave(&hotplug_mtx); > + return (EAGAIN); > + } > + > + error = msleep_nsec(&evqueue, &hotplug_mtx, PRIBIO | PCATCH, > + "htplev", INFSLP); > + if (error) { > + mtx_leave(&hotplug_mtx); > + return (error); > + } > + } > + mtx_leave(&hotplug_mtx); > + > + return (uiomove(&he, sizeof(he), uio)); > } > > int > @@ -183,32 +206,22 @@ hotplugioctl(dev_t dev, u_long cmd, cadd > int > hotplugkqfilter(dev_t dev, struct knote *kn) > { > - struct klist *klist; > - int s; > - > switch (kn->kn_filter) { > case EVFILT_READ: > - klist = &hotplug_sel.si_note; > kn->kn_fop = &hotplugread_filtops; > break; > default: > return (EINVAL); > } > > - s = splbio(); > - klist_insert_locked(klist, kn); > - splx(s); > + klist_insert(&hotplug_klist, kn); > return (0); > } > > void > filt_hotplugrdetach(struct knote *kn) > { > - int s; > - > - s = splbio(); > - klist_remove_locked(&hotplug_sel.si_note, kn); > - splx(s); > + klist_remove(&hotplug_klist, kn); > } > > int > @@ -217,4 +230,28 @@ filt_hotplugread(struct knote *kn, long > kn->kn_data = evqueue_count; > > return (evqueue_count > 0); > +} > + > +int > +filt_hotplugmodify(struct kevent *kev, struct knote *kn) > +{ > + int active; > + > + mtx_enter(&hotplug_mtx); > + active = knote_modify(kev, kn); > + mtx_leave(&hotplug_mtx); > + > + return (active); > +} > + > +int > +filt_hotplugprocess(struct knote *kn, struct kevent *kev) > +{ > + int active; > + > + mtx_enter(&hotplug_mtx); > + active = knote_process(kn, kev); > + mtx_leave(&hotplug_mtx); > + > + return (active); > }