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);
> }