ping

> On 27 Sep 2023, at 16:07, Vitaliy Makkoveev <m...@openbsd.org> wrote:
> 
> Introduce `fd_mtx' mutex(9) and use it for `fd_fbufs_in' fuse buffers
> queue and `fd_rklist' knotes list protection.
> 
> Index: sys/miscfs/fuse/fuse_device.c
> ===================================================================
> RCS file: /cvs/src/sys/miscfs/fuse/fuse_device.c,v
> retrieving revision 1.39
> diff -u -p -r1.39 fuse_device.c
> --- sys/miscfs/fuse/fuse_device.c     8 Sep 2023 20:00:28 -0000       1.39
> +++ sys/miscfs/fuse/fuse_device.c     27 Sep 2023 13:05:55 -0000
> @@ -19,13 +19,14 @@
> #include <sys/systm.h>
> #include <sys/fcntl.h>
> #include <sys/ioctl.h>
> +#include <sys/event.h>
> #include <sys/malloc.h>
> #include <sys/mount.h>
> +#include <sys/mutex.h>
> #include <sys/stat.h>
> #include <sys/statvfs.h>
> #include <sys/vnode.h>
> #include <sys/fusebuf.h>
> -#include <sys/selinfo.h>
> 
> #include "fusefs_node.h"
> #include "fusefs.h"
> @@ -36,18 +37,24 @@
> #define       DPRINTF(fmt, arg...)
> #endif
> 
> +/*
> + * Locks used to protect struct members and global data
> + *   m       fd_mtx
> + */
> +
> SIMPLEQ_HEAD(fusebuf_head, fusebuf);
> 
> struct fuse_d {
> +     struct mutex fd_mtx;
>       struct fusefs_mnt *fd_fmp;
>       int fd_unit;
> 
>       /*fusebufs queues*/
> -     struct fusebuf_head fd_fbufs_in;
> +     struct fusebuf_head fd_fbufs_in;        /* [m] */
>       struct fusebuf_head fd_fbufs_wait;
> 
>       /* kq fields */
> -     struct selinfo fd_rsel;
> +     struct klist fd_rklist;                 /* [m] */
>       LIST_ENTRY(fuse_d) fd_list;
> };
> 
> @@ -67,12 +74,16 @@ int       fusewrite(dev_t, struct uio *, int);
> int   fusekqfilter(dev_t dev, struct knote *kn);
> int   filt_fuse_read(struct knote *, long);
> void  filt_fuse_rdetach(struct knote *);
> +int  filt_fuse_modify(struct kevent *, struct knote *);
> +int  filt_fuse_process(struct knote *, struct kevent *);
> 
> static const struct filterops fuse_rd_filtops = {
> -     .f_flags        = FILTEROP_ISFD,
> +     .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
>       .f_attach       = NULL,
>       .f_detach       = filt_fuse_rdetach,
>       .f_event        = filt_fuse_read,
> +     .f_modify       = filt_fuse_modify,
> +     .f_process      = filt_fuse_process,
> };
> 
> #ifdef FUSE_DEBUG
> @@ -142,6 +153,7 @@ fuse_device_cleanup(dev_t dev)
> 
>       /* clear FIFO IN */
>       lprev = NULL;
> +     mtx_enter(&fd->fd_mtx);
>       SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_in, fb_next, ftmp) {
>               DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n");
>               if (lprev == NULL)
> @@ -155,6 +167,7 @@ fuse_device_cleanup(dev_t dev)
>               wakeup(f);
>               lprev = f;
>       }
> +     mtx_leave(&fd->fd_mtx);
> 
>       /* clear FIFO WAIT*/
>       lprev = NULL;
> @@ -182,9 +195,11 @@ fuse_device_queue_fbuf(dev_t dev, struct
>       if (fd == NULL)
>               return;
> 
> +     mtx_enter(&fd->fd_mtx);
>       SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_in, fbuf, fb_next);
> +     knote_locked(&fd->fd_rklist, 0);
> +     mtx_leave(&fd->fd_mtx);
>       stat_fbufs_in++;
> -     selwakeup(&fd->fd_rsel);
> }
> 
> void
> @@ -221,6 +236,9 @@ fuseopen(dev_t dev, int flags, int fmt, 
>       fd->fd_unit = unit;
>       SIMPLEQ_INIT(&fd->fd_fbufs_in);
>       SIMPLEQ_INIT(&fd->fd_fbufs_wait);
> +     mtx_init(&fd->fd_mtx, IPL_MPFLOOR);
> +     klist_init_mutex(&fd->fd_rklist, &fd->fd_mtx);
> +
>       LIST_INSERT_HEAD(&fuse_d_list, fd, fd_list);
> 
>       stat_opened_fusedev++;
> @@ -278,6 +296,7 @@ fuseioctl(dev_t dev, u_long cmd, caddr_t
>               ioexch = (struct fb_ioctl_xch *)addr;
> 
>               /* Looking for uuid in fd_fbufs_in */
> +             mtx_enter(&fd->fd_mtx);
>               SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_in, fb_next) {
>                       if (fbuf->fb_uuid == ioexch->fbxch_uuid)
>                               break;
> @@ -285,6 +304,7 @@ fuseioctl(dev_t dev, u_long cmd, caddr_t
>                       lastfbuf = fbuf;
>               }
>               if (fbuf == NULL) {
> +                     mtx_leave(&fd->fd_mtx);
>                       printf("fuse: Cannot find fusebuf\n");
>                       return (EINVAL);
>               }
> @@ -295,6 +315,8 @@ fuseioctl(dev_t dev, u_long cmd, caddr_t
>               else
>                       SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lastfbuf,
>                           fb_next);
> +             mtx_leave(&fd->fd_mtx);
> +     
>               stat_fbufs_in--;
> 
>               /* Do not handle fbufs with bad len */
> @@ -389,13 +411,17 @@ fuseread(dev_t dev, struct uio *uio, int
>       if (fd == NULL)
>               return (ENXIO);
> 
> +     mtx_enter(&fd->fd_mtx);
>       if (SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) {
> +             mtx_leave(&fd->fd_mtx);
> +
>               if (ioflag & O_NONBLOCK)
>                       return (EAGAIN);
> 
>               goto end;
>       }
>       fbuf = SIMPLEQ_FIRST(&fd->fd_fbufs_in);
> +     mtx_leave(&fd->fd_mtx);
> 
>       /* We get the whole fusebuf or nothing */
>       if (uio->uio_resid != FUSEBUFSIZE)
> @@ -419,7 +445,9 @@ fuseread(dev_t dev, struct uio *uio, int
> 
>       /* Remove the fbuf if it does not contains data */
>       if (fbuf->fb_len == 0) {
> +             mtx_enter(&fd->fd_mtx);
>               SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next);
> +             mtx_leave(&fd->fd_mtx);
>               stat_fbufs_in--;
>               SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next);
>               stat_fbufs_wait++;
> @@ -519,7 +547,7 @@ fusekqfilter(dev_t dev, struct knote *kn
> 
>       switch (kn->kn_filter) {
>       case EVFILT_READ:
> -             klist = &fd->fd_rsel.si_note;
> +             klist = &fd->fd_rklist;
>               kn->kn_fop = &fuse_rd_filtops;
>               break;
>       case EVFILT_WRITE:
> @@ -530,7 +558,7 @@ fusekqfilter(dev_t dev, struct knote *kn
> 
>       kn->kn_hook = fd;
> 
> -     klist_insert_locked(klist, kn);
> +     klist_insert(klist, kn);
> 
>       return (0);
> }
> @@ -539,9 +567,9 @@ void
> filt_fuse_rdetach(struct knote *kn)
> {
>       struct fuse_d *fd = kn->kn_hook;
> -     struct klist *klist = &fd->fd_rsel.si_note;
> +     struct klist *klist = &fd->fd_rklist;
> 
> -     klist_remove_locked(klist, kn);
> +     klist_remove(klist, kn);
> }
> 
> int
> @@ -554,4 +582,30 @@ filt_fuse_read(struct knote *kn, long hi
>               event = 1;
> 
>       return (event);
> +}
> +
> +int
> +filt_fuse_modify(struct kevent *kev, struct knote *kn)
> +{
> +     struct fuse_d *fd = kn->kn_hook;
> +     int active;
> +
> +     mtx_enter(&fd->fd_mtx);
> +     active = knote_modify(kev, kn);
> +     mtx_leave(&fd->fd_mtx);
> +
> +     return (active);
> +}
> +
> +int
> +filt_fuse_process(struct knote *kn, struct kevent *kev)
> +{
> +     struct fuse_d *fd = kn->kn_hook;
> +     int active;
> +
> +     mtx_enter(&fd->fd_mtx);
> +     active = knote_process(kn, kev); 
> +     mtx_leave(&fd->fd_mtx);
> +
> +     return (active);
> }
> 

Reply via email to