LCOV - code coverage report
Current view: top level - miscfs/fuse - fuse_device.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 232 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: fuse_device.c,v 1.29 2018/06/27 13:58:22 helg Exp $ */
       2             : /*
       3             :  * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
       4             :  *
       5             :  * Permission to use, copy, modify, and distribute this software for any
       6             :  * purpose with or without fee is hereby granted, provided that the above
       7             :  * copyright notice and this permission notice appear in all copies.
       8             :  *
       9             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16             :  */
      17             : 
      18             : #include <sys/param.h>
      19             : #include <sys/systm.h>
      20             : #include <sys/fcntl.h>
      21             : #include <sys/ioctl.h>
      22             : #include <sys/malloc.h>
      23             : #include <sys/mount.h>
      24             : #include <sys/poll.h>
      25             : #include <sys/stat.h>
      26             : #include <sys/statvfs.h>
      27             : #include <sys/vnode.h>
      28             : #include <sys/fusebuf.h>
      29             : 
      30             : #include "fusefs_node.h"
      31             : #include "fusefs.h"
      32             : 
      33             : #ifdef  FUSE_DEBUG
      34             : #define DPRINTF(fmt, arg...)    printf("%s: " fmt, "fuse", ##arg)
      35             : #else
      36             : #define DPRINTF(fmt, arg...)
      37             : #endif
      38             : 
      39             : SIMPLEQ_HEAD(fusebuf_head, fusebuf);
      40             : 
      41             : struct fuse_d {
      42             :         struct fusefs_mnt *fd_fmp;
      43             :         int fd_unit;
      44             : 
      45             :         /*fusebufs queues*/
      46             :         struct fusebuf_head fd_fbufs_in;
      47             :         struct fusebuf_head fd_fbufs_wait;
      48             : 
      49             :         /* kq fields */
      50             :         struct selinfo fd_rsel;
      51             :         LIST_ENTRY(fuse_d) fd_list;
      52             : };
      53             : 
      54             : int stat_fbufs_in = 0;
      55             : int stat_fbufs_wait = 0;
      56             : int stat_opened_fusedev = 0;
      57             : 
      58             : LIST_HEAD(, fuse_d) fuse_d_list;
      59             : struct fuse_d *fuse_lookup(int);
      60             : 
      61             : void    fuseattach(int);
      62             : int     fuseopen(dev_t, int, int, struct proc *);
      63             : int     fuseclose(dev_t, int, int, struct proc *);
      64             : int     fuseioctl(dev_t, u_long, caddr_t, int, struct proc *);
      65             : int     fuseread(dev_t, struct uio *, int);
      66             : int     fusewrite(dev_t, struct uio *, int);
      67             : int     fusepoll(dev_t, int, struct proc *);
      68             : int     fusekqfilter(dev_t dev, struct knote *kn);
      69             : int     filt_fuse_read(struct knote *, long);
      70             : void    filt_fuse_rdetach(struct knote *);
      71             : 
      72             : const static struct filterops fuse_rd_filtops = {
      73             :         1,
      74             :         NULL,
      75             :         filt_fuse_rdetach,
      76             :         filt_fuse_read
      77             : };
      78             : 
      79             : const static struct filterops fuse_seltrue_filtops = {
      80             :         1,
      81             :         NULL,
      82             :         filt_fuse_rdetach,
      83             :         filt_seltrue
      84             : };
      85             : 
      86             : #ifdef FUSE_DEBUG
      87             : static void
      88             : fuse_dump_buff(char *buff, int len)
      89             : {
      90             :         char text[17];
      91             :         int i;
      92             : 
      93             :         if (len < 0) {
      94             :                 printf("invalid len: %d", len);
      95             :                 return;
      96             :         }
      97             :         if (buff == NULL) {
      98             :                 printf("invalid buff");
      99             :                 return;
     100             :         }
     101             : 
     102             :         memset(text, 0, 17);
     103             :         for (i = 0; i < len; i++) {
     104             :                 if (i != 0 && (i % 16) == 0) {
     105             :                         printf(": %s\n", text);
     106             :                         memset(text, 0, 17);
     107             :                 }
     108             : 
     109             :                 printf("%.2x ", buff[i] & 0xff);
     110             : 
     111             :                 if (buff[i] > ' ' && buff[i] < '~')
     112             :                         text[i%16] = buff[i] & 0xff;
     113             :                 else
     114             :                         text[i%16] = '.';
     115             :         }
     116             : 
     117             :         if ((i % 16) != 0)
     118             :                 while ((i % 16) != 0) {
     119             :                         printf("   ");
     120             :                         i++;
     121             :                 }
     122             : 
     123             :         printf(": %s\n", text);
     124             : }
     125             : #endif
     126             : 
     127             : struct fuse_d *
     128           0 : fuse_lookup(int unit)
     129             : {
     130             :         struct fuse_d *fd;
     131             : 
     132           0 :         LIST_FOREACH(fd, &fuse_d_list, fd_list)
     133           0 :                 if (fd->fd_unit == unit)
     134           0 :                         return (fd);
     135           0 :         return (NULL);
     136           0 : }
     137             : 
     138             : /*
     139             :  * Cleanup all msgs from sc_fbufs_in and sc_fbufs_wait.
     140             :  */
     141             : void
     142           0 : fuse_device_cleanup(dev_t dev)
     143             : {
     144             :         struct fuse_d *fd;
     145             :         struct fusebuf *f, *ftmp, *lprev;
     146             : 
     147           0 :         fd = fuse_lookup(minor(dev));
     148           0 :         if (fd == NULL)
     149           0 :                 return;
     150             : 
     151             :         /* clear FIFO IN */
     152             :         lprev = NULL;
     153           0 :         SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_in, fb_next, ftmp) {
     154             :                 DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n");
     155           0 :                 if (lprev == NULL)
     156           0 :                         SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next);
     157             :                 else
     158           0 :                         SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lprev,
     159             :                             fb_next);
     160             : 
     161           0 :                 stat_fbufs_in--;
     162           0 :                 f->fb_err = ENXIO;
     163           0 :                 wakeup(f);
     164             :                 lprev = f;
     165             :         }
     166             : 
     167             :         /* clear FIFO WAIT*/
     168             :         lprev = NULL;
     169           0 :         SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_wait, fb_next, ftmp) {
     170             :                 DPRINTF("umount unprocessed msg in sc_fbufs_wait\n");
     171           0 :                 if (lprev == NULL)
     172           0 :                         SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next);
     173             :                 else
     174           0 :                         SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lprev,
     175             :                             fb_next);
     176             : 
     177           0 :                 stat_fbufs_wait--;
     178           0 :                 f->fb_err = ENXIO;
     179           0 :                 wakeup(f);
     180             :                 lprev = f;
     181             :         }
     182           0 : }
     183             : 
     184             : void
     185           0 : fuse_device_queue_fbuf(dev_t dev, struct fusebuf *fbuf)
     186             : {
     187             :         struct fuse_d *fd;
     188             : 
     189           0 :         fd = fuse_lookup(minor(dev));
     190           0 :         if (fd == NULL)
     191           0 :                 return;
     192             : 
     193           0 :         SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_in, fbuf, fb_next);
     194           0 :         stat_fbufs_in++;
     195           0 :         selwakeup(&fd->fd_rsel);
     196           0 : }
     197             : 
     198             : void
     199           0 : fuse_device_set_fmp(struct fusefs_mnt *fmp, int set)
     200             : {
     201             :         struct fuse_d *fd;
     202             : 
     203           0 :         fd = fuse_lookup(minor(fmp->dev));
     204           0 :         if (fd == NULL)
     205           0 :                 return;
     206             : 
     207           0 :         fd->fd_fmp = set ? fmp : NULL;
     208           0 : }
     209             : 
     210             : void
     211           0 : fuseattach(int num)
     212             : {
     213           0 :         LIST_INIT(&fuse_d_list);
     214           0 : }
     215             : 
     216             : int
     217           0 : fuseopen(dev_t dev, int flags, int fmt, struct proc * p)
     218             : {
     219             :         struct fuse_d *fd;
     220           0 :         int unit = minor(dev);
     221             : 
     222           0 :         if (flags & O_EXCL)
     223           0 :                 return (EBUSY); /* No exclusive opens */
     224             : 
     225           0 :         if ((fd = fuse_lookup(unit)) != NULL)
     226           0 :                 return (EBUSY);
     227             : 
     228           0 :         fd = malloc(sizeof(*fd), M_DEVBUF, M_WAITOK | M_ZERO);
     229           0 :         fd->fd_unit = unit;
     230           0 :         SIMPLEQ_INIT(&fd->fd_fbufs_in);
     231           0 :         SIMPLEQ_INIT(&fd->fd_fbufs_wait);
     232           0 :         LIST_INSERT_HEAD(&fuse_d_list, fd, fd_list);
     233             : 
     234           0 :         stat_opened_fusedev++;
     235           0 :         return (0);
     236           0 : }
     237             : 
     238             : int
     239           0 : fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
     240             : {
     241             :         struct fuse_d *fd;
     242             :         int error;
     243             : 
     244           0 :         fd = fuse_lookup(minor(dev));
     245           0 :         if (fd == NULL)
     246           0 :                 return (EINVAL);
     247             : 
     248           0 :         if (fd->fd_fmp) {
     249           0 :                 printf("fuse: device close without umount\n");
     250           0 :                 fd->fd_fmp->sess_init = 0;
     251           0 :                 fuse_device_cleanup(dev);
     252           0 :                 if ((vfs_busy(fd->fd_fmp->mp, VB_WRITE | VB_NOWAIT)) != 0)
     253             :                         goto end;
     254           0 :                 error = dounmount(fd->fd_fmp->mp, MNT_FORCE, p);
     255           0 :                 if (error)
     256           0 :                         printf("fuse: unmount failed with error %d\n", error);
     257           0 :                 fd->fd_fmp = NULL;
     258           0 :         }
     259             : 
     260             : end:
     261           0 :         LIST_REMOVE(fd, fd_list);
     262           0 :         free(fd, M_DEVBUF, sizeof(*fd));
     263           0 :         stat_opened_fusedev--;
     264           0 :         return (0);
     265           0 : }
     266             : 
     267             : /*
     268             :  * FIOCGETFBDAT         Get fusebuf datas from kernel to user
     269             :  * FIOCSETFBDAT         Set fusebuf datas from user to kernel
     270             :  */
     271             : int
     272           0 : fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
     273             : {
     274             :         struct fb_ioctl_xch *ioexch;
     275             :         struct fusebuf *lastfbuf;
     276             :         struct fusebuf *fbuf;
     277             :         struct fuse_d *fd;
     278             :         int error = 0;
     279             : 
     280           0 :         fd = fuse_lookup(minor(dev));
     281           0 :         if (fd == NULL)
     282           0 :                 return (ENXIO);
     283             : 
     284           0 :         switch (cmd) {
     285             :         case FIOCGETFBDAT:
     286           0 :                 ioexch = (struct fb_ioctl_xch *)addr;
     287             : 
     288             :                 /* Looking for uuid in fd_fbufs_in */
     289           0 :                 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_in, fb_next) {
     290           0 :                         if (fbuf->fb_uuid == ioexch->fbxch_uuid)
     291             :                                 break;
     292             : 
     293             :                         lastfbuf = fbuf;
     294             :                 }
     295           0 :                 if (fbuf == NULL) {
     296           0 :                         printf("fuse: Cannot find fusebuf\n");
     297           0 :                         return (EINVAL);
     298             :                 }
     299             : 
     300             :                 /* Remove the fbuf from fd_fbufs_in */
     301           0 :                 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_in))
     302           0 :                         SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next);
     303             :                 else
     304           0 :                         SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lastfbuf,
     305             :                             fb_next);
     306           0 :                 stat_fbufs_in--;
     307             : 
     308             :                 /* Do not handle fbufs with bad len */
     309           0 :                 if (fbuf->fb_len != ioexch->fbxch_len) {
     310           0 :                         printf("fuse: Bad fusebuf len\n");
     311           0 :                         return (EINVAL);
     312             :                 }
     313             : 
     314             :                 /* Update the userland fbuf */
     315           0 :                 error = copyout(fbuf->fb_dat, ioexch->fbxch_data,
     316             :                     ioexch->fbxch_len);
     317           0 :                 if (error) {
     318           0 :                         printf("fuse: cannot copyout\n");
     319           0 :                         return (error);
     320             :                 }
     321             : 
     322             : #ifdef FUSE_DEBUG
     323             :                 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_len);
     324             : #endif
     325             : 
     326             :                 /* Adding fbuf in fd_fbufs_wait */
     327           0 :                 free(fbuf->fb_dat, M_FUSEFS, fbuf->fb_len);
     328           0 :                 fbuf->fb_dat = NULL;
     329           0 :                 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next);
     330           0 :                 stat_fbufs_wait++;
     331           0 :                 break;
     332             : 
     333             :         case FIOCSETFBDAT:
     334             :                 DPRINTF("SET BUFFER\n");
     335           0 :                 ioexch = (struct fb_ioctl_xch *)addr;
     336             : 
     337             :                 /* looking for uuid in fd_fbufs_wait */
     338           0 :                 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) {
     339           0 :                         if (fbuf->fb_uuid == ioexch->fbxch_uuid)
     340             :                                 break;
     341             : 
     342             :                         lastfbuf = fbuf;
     343             :                 }
     344           0 :                 if (fbuf == NULL) {
     345           0 :                         printf("fuse: Cannot find fusebuf\n");
     346           0 :                         return (EINVAL);
     347             :                 }
     348             : 
     349             :                 /* Do not handle fbufs with bad len */
     350           0 :                 if (fbuf->fb_len != ioexch->fbxch_len) {
     351           0 :                         printf("fuse: Bad fusebuf size\n");
     352           0 :                         return (EINVAL);
     353             :                 }
     354             : 
     355             :                 /* fetching data from userland */
     356           0 :                 fbuf->fb_dat = malloc(ioexch->fbxch_len, M_FUSEFS,
     357             :                     M_WAITOK | M_ZERO);
     358           0 :                 error = copyin(ioexch->fbxch_data, fbuf->fb_dat,
     359           0 :                     ioexch->fbxch_len);
     360           0 :                 if (error) {
     361           0 :                         printf("fuse: Cannot copyin\n");
     362           0 :                         free(fbuf->fb_dat, M_FUSEFS, fbuf->fb_len);
     363           0 :                         fbuf->fb_dat = NULL;
     364           0 :                         return (error);
     365             :                 }
     366             : 
     367             : #ifdef FUSE_DEBUG
     368             :                 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_len);
     369             : #endif
     370             : 
     371             :                 /* Remove fbuf from fd_fbufs_wait */
     372           0 :                 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait))
     373           0 :                         SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next);
     374             :                 else
     375           0 :                         SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf,
     376             :                             fb_next);
     377           0 :                 stat_fbufs_wait--;
     378           0 :                 wakeup(fbuf);
     379           0 :                 break;
     380             :         default:
     381             :                 error = EINVAL;
     382           0 :         }
     383             : 
     384           0 :         return (error);
     385           0 : }
     386             : 
     387             : int
     388           0 : fuseread(dev_t dev, struct uio *uio, int ioflag)
     389             : {
     390             :         struct fuse_d *fd;
     391             :         struct fusebuf *fbuf;
     392           0 :         struct fb_hdr hdr;
     393             :         void *tmpaddr;
     394             :         int error = 0;
     395             : 
     396           0 :         fd = fuse_lookup(minor(dev));
     397           0 :         if (fd == NULL)
     398           0 :                 return (ENXIO);
     399             : 
     400           0 :         if (SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) {
     401           0 :                 if (ioflag & O_NONBLOCK)
     402           0 :                         return (EAGAIN);
     403             : 
     404             :                 goto end;
     405             :         }
     406             :         fbuf = SIMPLEQ_FIRST(&fd->fd_fbufs_in);
     407             : 
     408             :         /* We get the whole fusebuf or nothing */
     409           0 :         if (uio->uio_resid != FUSEBUFSIZE)
     410           0 :                 return (EINVAL);
     411             : 
     412             :         /* Do not send kernel pointers */
     413           0 :         memcpy(&hdr.fh_next, &fbuf->fb_next, sizeof(fbuf->fb_next));
     414           0 :         memset(&fbuf->fb_next, 0, sizeof(fbuf->fb_next));
     415           0 :         tmpaddr = fbuf->fb_dat;
     416           0 :         fbuf->fb_dat = NULL;
     417           0 :         error = uiomove(fbuf, FUSEBUFSIZE, uio);
     418           0 :         if (error)
     419             :                 goto end;
     420             : 
     421             : #ifdef FUSE_DEBUG
     422             :         fuse_dump_buff((char *)fbuf, FUSEBUFSIZE);
     423             : #endif
     424             :         /* Restore kernel pointers */
     425           0 :         memcpy(&fbuf->fb_next, &hdr.fh_next, sizeof(fbuf->fb_next));
     426           0 :         fbuf->fb_dat = tmpaddr;
     427             : 
     428             :         /* Remove the fbuf if it does not contains data */
     429           0 :         if (fbuf->fb_len == 0) {
     430           0 :                 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next);
     431           0 :                 stat_fbufs_in--;
     432           0 :                 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next);
     433           0 :                 stat_fbufs_wait++;
     434           0 :         }
     435             : 
     436             : end:
     437           0 :         return (error);
     438           0 : }
     439             : 
     440             : int
     441           0 : fusewrite(dev_t dev, struct uio *uio, int ioflag)
     442             : {
     443             :         struct fusebuf *lastfbuf;
     444             :         struct fuse_d *fd;
     445             :         struct fusebuf *fbuf;
     446           0 :         struct fb_hdr hdr;
     447             :         int error = 0;
     448             : 
     449           0 :         fd = fuse_lookup(minor(dev));
     450           0 :         if (fd == NULL)
     451           0 :                 return (ENXIO);
     452             : 
     453             :         /* We get the whole fusebuf or nothing */
     454           0 :         if (uio->uio_resid != FUSEBUFSIZE)
     455           0 :                 return (EINVAL);
     456             : 
     457           0 :         if ((error = uiomove(&hdr, sizeof(hdr), uio)) != 0)
     458           0 :                 return (error);
     459             : 
     460             :         /* looking for uuid in fd_fbufs_wait */
     461           0 :         SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) {
     462           0 :                 if (fbuf->fb_uuid == hdr.fh_uuid)
     463             :                         break;
     464             : 
     465             :                 lastfbuf = fbuf;
     466             :         }
     467           0 :         if (fbuf == NULL)
     468           0 :                 return (EINVAL);
     469             : 
     470             :         /* Update fb_hdr */
     471           0 :         fbuf->fb_len = hdr.fh_len;
     472           0 :         fbuf->fb_err = hdr.fh_err;
     473           0 :         fbuf->fb_ino = hdr.fh_ino;
     474             : 
     475             :         /* Check for corrupted fbufs */
     476           0 :         if ((fbuf->fb_len && fbuf->fb_err) ||
     477           0 :             SIMPLEQ_EMPTY(&fd->fd_fbufs_wait)) {
     478           0 :                 printf("fuse: dropping corrupted fusebuf\n");
     479             :                 error = EINVAL;
     480           0 :                 goto end;
     481             :         }
     482             : 
     483             :         /* Get the missing datas from the fbuf */
     484           0 :         error = uiomove(&fbuf->FD, uio->uio_resid, uio);
     485           0 :         if (error)
     486           0 :                 return error;
     487           0 :         fbuf->fb_dat = NULL;
     488             : #ifdef FUSE_DEBUG
     489             :         fuse_dump_buff((char *)fbuf, FUSEBUFSIZE);
     490             : #endif
     491             : 
     492           0 :         switch (fbuf->fb_type) {
     493             :         case FBT_INIT:
     494           0 :                 fd->fd_fmp->sess_init = 1;
     495           0 :                 break ;
     496             :         case FBT_DESTROY:
     497           0 :                 fd->fd_fmp = NULL;
     498           0 :                 break ;
     499             :         }
     500             : end:
     501             :         /* Remove the fbuf if it does not contains data */
     502           0 :         if (fbuf->fb_len == 0) {
     503           0 :                 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait))
     504           0 :                         SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next);
     505             :                 else
     506           0 :                         SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf,
     507             :                             fb_next);
     508           0 :                 stat_fbufs_wait--;
     509           0 :                 if (fbuf->fb_type == FBT_INIT)
     510           0 :                         fb_delete(fbuf);
     511             :                 else
     512           0 :                         wakeup(fbuf);
     513             :         }
     514             : 
     515           0 :         return (error);
     516           0 : }
     517             : 
     518             : int
     519           0 : fusepoll(dev_t dev, int events, struct proc *p)
     520             : {
     521             :         struct fuse_d *fd;
     522             :         int revents = 0;
     523             : 
     524           0 :         fd = fuse_lookup(minor(dev));
     525           0 :         if (fd == NULL)
     526           0 :                 return (EINVAL);
     527             : 
     528           0 :         if (events & (POLLIN | POLLRDNORM))
     529           0 :                 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in))
     530           0 :                         revents |= events & (POLLIN | POLLRDNORM);
     531             : 
     532           0 :         if (events & (POLLOUT | POLLWRNORM))
     533           0 :                 revents |= events & (POLLOUT | POLLWRNORM);
     534             : 
     535           0 :         if (revents == 0)
     536           0 :                 if (events & (POLLIN | POLLRDNORM))
     537           0 :                         selrecord(p, &fd->fd_rsel);
     538             : 
     539           0 :         return (revents);
     540           0 : }
     541             : 
     542             : int
     543           0 : fusekqfilter(dev_t dev, struct knote *kn)
     544             : {
     545             :         struct fuse_d *fd;
     546             :         struct klist *klist;
     547             : 
     548           0 :         fd = fuse_lookup(minor(dev));
     549           0 :         if (fd == NULL)
     550           0 :                 return (EINVAL);
     551             : 
     552           0 :         switch (kn->kn_filter) {
     553             :         case EVFILT_READ:
     554           0 :                 klist = &fd->fd_rsel.si_note;
     555           0 :                 kn->kn_fop = &fuse_rd_filtops;
     556           0 :                 break;
     557             :         case EVFILT_WRITE:
     558           0 :                 klist = &fd->fd_rsel.si_note;
     559           0 :                 kn->kn_fop = &fuse_seltrue_filtops;
     560           0 :                 break;
     561             :         default:
     562           0 :                 return (EINVAL);
     563             :         }
     564             : 
     565           0 :         kn->kn_hook = fd;
     566             : 
     567           0 :         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
     568             : 
     569           0 :         return (0);
     570           0 : }
     571             : 
     572             : void
     573           0 : filt_fuse_rdetach(struct knote *kn)
     574             : {
     575           0 :         struct fuse_d *fd = kn->kn_hook;
     576           0 :         struct klist *klist = &fd->fd_rsel.si_note;
     577             : 
     578           0 :         SLIST_REMOVE(klist, kn, knote, kn_selnext);
     579           0 : }
     580             : 
     581             : int
     582           0 : filt_fuse_read(struct knote *kn, long hint)
     583             : {
     584           0 :         struct fuse_d *fd = kn->kn_hook;
     585             :         int event = 0;
     586             : 
     587           0 :         if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in))
     588             :                 event = 1;
     589             : 
     590           0 :         return (event);
     591             : }

Generated by: LCOV version 1.13