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

          Line data    Source code
       1             : /* $OpenBSD: fuse_vfsops.c,v 1.42 2018/07/17 13:12:08 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/file.h>
      21             : #include <sys/filedesc.h>
      22             : #include <sys/malloc.h>
      23             : #include <sys/mount.h>
      24             : #include <sys/pool.h>
      25             : #include <sys/proc.h>
      26             : #include <sys/specdev.h>
      27             : #include <sys/stat.h>
      28             : #include <sys/statvfs.h>
      29             : #include <sys/sysctl.h>
      30             : #include <sys/vnode.h>
      31             : #include <sys/fusebuf.h>
      32             : 
      33             : #include "fusefs_node.h"
      34             : #include "fusefs.h"
      35             : 
      36             : int     fusefs_mount(struct mount *, const char *, void *, struct nameidata *,
      37             :             struct proc *);
      38             : int     fusefs_start(struct mount *, int, struct proc *);
      39             : int     fusefs_unmount(struct mount *, int, struct proc *);
      40             : int     fusefs_root(struct mount *, struct vnode **);
      41             : int     fusefs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *);
      42             : int     fusefs_statfs(struct mount *, struct statfs *, struct proc *);
      43             : int     fusefs_sync(struct mount *, int, int, struct ucred *, struct proc *);
      44             : int     fusefs_vget(struct mount *, ino_t, struct vnode **);
      45             : int     fusefs_fhtovp(struct mount *, struct fid *, struct vnode **);
      46             : int     fusefs_vptofh(struct vnode *, struct fid *);
      47             : int     fusefs_init(struct vfsconf *);
      48             : int     fusefs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
      49             :             struct proc *);
      50             : int     fusefs_checkexp(struct mount *, struct mbuf *, int *,
      51             :             struct ucred **);
      52             : 
      53             : const struct vfsops fusefs_vfsops = {
      54             :         fusefs_mount,
      55             :         fusefs_start,
      56             :         fusefs_unmount,
      57             :         fusefs_root,
      58             :         fusefs_quotactl,
      59             :         fusefs_statfs,
      60             :         fusefs_sync,
      61             :         fusefs_vget,
      62             :         fusefs_fhtovp,
      63             :         fusefs_vptofh,
      64             :         fusefs_init,
      65             :         fusefs_sysctl,
      66             :         fusefs_checkexp
      67             : };
      68             : 
      69             : struct pool fusefs_fbuf_pool;
      70             : 
      71             : #define PENDING 2       /* FBT_INIT reply not yet received */
      72             : 
      73             : int
      74           0 : fusefs_mount(struct mount *mp, const char *path, void *data,
      75             :     struct nameidata *ndp, struct proc *p)
      76             : {
      77             :         struct fusefs_mnt *fmp;
      78             :         struct fusebuf *fbuf;
      79           0 :         struct fusefs_args *args = data;
      80             :         struct vnode *vp;
      81             :         struct file *fp;
      82             :         int error = 0;
      83             : 
      84           0 :         if (mp->mnt_flag & MNT_UPDATE)
      85           0 :                 return (EOPNOTSUPP);
      86             : 
      87           0 :         if ((fp = fd_getfile(p->p_fd, args->fd)) == NULL)
      88           0 :                 return (EBADF);
      89             : 
      90           0 :         if (fp->f_type != DTYPE_VNODE) {
      91             :                 error = EINVAL;
      92           0 :                 goto bad;
      93             :         }
      94             : 
      95           0 :         vp = fp->f_data;
      96           0 :         if (vp->v_type != VCHR) {
      97             :                 error = EBADF;
      98           0 :                 goto bad;
      99             :         }
     100             : 
     101             :         /* Only root may specify allow_other. */
     102           0 :         if (args->allow_other && (error = suser_ucred(p->p_ucred)))
     103             :                 goto bad;
     104             : 
     105           0 :         fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO);
     106           0 :         fmp->mp = mp;
     107           0 :         fmp->sess_init = PENDING;
     108           0 :         fmp->dev = vp->v_rdev;
     109           0 :         if (args->max_read > 0)
     110           0 :                 fmp->max_read = MIN(args->max_read, FUSEBUFMAXSIZE);
     111             :         else
     112           0 :                 fmp->max_read = FUSEBUFMAXSIZE;
     113             : 
     114           0 :         fmp->allow_other = args->allow_other;
     115             : 
     116           0 :         mp->mnt_data = fmp;
     117           0 :         mp->mnt_flag |= MNT_LOCAL;
     118           0 :         vfs_getnewfsid(mp);
     119             : 
     120           0 :         memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN);
     121           0 :         strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
     122           0 :         memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
     123           0 :         strlcpy(mp->mnt_stat.f_mntfromname, "fusefs", MNAMELEN);
     124           0 :         memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
     125           0 :         strlcpy(mp->mnt_stat.f_mntfromspec, "fusefs", MNAMELEN);
     126             : 
     127           0 :         fuse_device_set_fmp(fmp, 1);
     128           0 :         fbuf = fb_setup(0, 0, FBT_INIT, p);
     129             : 
     130             :         /* cannot tsleep on mount */
     131           0 :         fuse_device_queue_fbuf(fmp->dev, fbuf);
     132             : 
     133             : bad:
     134           0 :         FRELE(fp, p);
     135           0 :         return (error);
     136           0 : }
     137             : 
     138             : int
     139           0 : fusefs_start(struct mount *mp, int flags, struct proc *p)
     140             : {
     141           0 :         return (0);
     142             : }
     143             : 
     144             : int
     145           0 : fusefs_unmount(struct mount *mp, int mntflags, struct proc *p)
     146             : {
     147             :         struct fusefs_mnt *fmp;
     148             :         struct fusebuf *fbuf;
     149             :         int flags = 0;
     150             :         int error;
     151             : 
     152           0 :         fmp = VFSTOFUSEFS(mp);
     153             : 
     154           0 :         if (mntflags & MNT_FORCE)
     155           0 :                 flags |= FORCECLOSE;
     156             : 
     157           0 :         if ((error = vflush(mp, NULLVP, flags)))
     158           0 :                 return (error);
     159             : 
     160           0 :         if (fmp->sess_init && fmp->sess_init != PENDING) {
     161           0 :                 fbuf = fb_setup(0, 0, FBT_DESTROY, p);
     162             : 
     163           0 :                 error = fb_queue(fmp->dev, fbuf);
     164             : 
     165           0 :                 if (error)
     166           0 :                         printf("fusefs: error %d on destroy\n", error);
     167             : 
     168           0 :                 fb_delete(fbuf);
     169           0 :         }
     170           0 :         fmp->sess_init = 0;
     171             : 
     172           0 :         fuse_device_cleanup(fmp->dev);
     173           0 :         fuse_device_set_fmp(fmp, 0);
     174           0 :         free(fmp, M_FUSEFS, sizeof(*fmp));
     175           0 :         mp->mnt_data = NULL;
     176             : 
     177           0 :         return (0);
     178           0 : }
     179             : 
     180             : int
     181           0 : fusefs_root(struct mount *mp, struct vnode **vpp)
     182             : {
     183           0 :         struct vnode *nvp;
     184             :         int error;
     185             : 
     186           0 :         if ((error = VFS_VGET(mp, FUSE_ROOTINO, &nvp)) != 0)
     187           0 :                 return (error);
     188             : 
     189           0 :         nvp->v_type = VDIR;
     190             : 
     191           0 :         *vpp = nvp;
     192           0 :         return (0);
     193           0 : }
     194             : 
     195             : int
     196           0 : fusefs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
     197             :     struct proc *p)
     198             : {
     199           0 :         return (EOPNOTSUPP);
     200             : }
     201             : 
     202             : int
     203           0 : fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
     204             : {
     205             :         struct fusefs_mnt *fmp;
     206             :         struct fusebuf *fbuf;
     207             :         int error;
     208             : 
     209           0 :         fmp = VFSTOFUSEFS(mp);
     210             : 
     211             :         /* Deny other users unless allow_other mount option was specified. */
     212           0 :         if (!fmp->allow_other && p->p_ucred->cr_uid != mp->mnt_stat.f_owner)
     213           0 :                 return (EPERM);
     214             : 
     215           0 :         copy_statfs_info(sbp, mp);
     216             : 
     217             :         /*
     218             :          * Both FBT_INIT and FBT_STATFS are sent to the FUSE file system
     219             :          * daemon when it is mounted. However, the daemon is the process
     220             :          * that called mount(2) so to prevent a deadlock return dummy
     221             :          * values until the response to FBT_INIT init is received. All
     222             :          * other VFS syscalls are queued.
     223             :          */
     224           0 :         if (!fmp->sess_init || fmp->sess_init == PENDING) {
     225           0 :                 sbp->f_bavail = 0;
     226           0 :                 sbp->f_bfree = 0;
     227           0 :                 sbp->f_blocks = 0;
     228           0 :                 sbp->f_ffree = 0;
     229           0 :                 sbp->f_favail = 0;
     230           0 :                 sbp->f_files = 0;
     231           0 :                 sbp->f_bsize = 0;
     232           0 :                 sbp->f_iosize = 0;
     233           0 :                 sbp->f_namemax = 0;
     234           0 :         } else {
     235           0 :                 fbuf = fb_setup(0, FUSE_ROOTINO, FBT_STATFS, p);
     236             : 
     237           0 :                 error = fb_queue(fmp->dev, fbuf);
     238             : 
     239           0 :                 if (error) {
     240           0 :                         fb_delete(fbuf);
     241           0 :                         return (error);
     242             :                 }
     243             : 
     244           0 :                 sbp->f_bavail = fbuf->fb_stat.f_bavail;
     245           0 :                 sbp->f_bfree = fbuf->fb_stat.f_bfree;
     246           0 :                 sbp->f_blocks = fbuf->fb_stat.f_blocks;
     247           0 :                 sbp->f_files = fbuf->fb_stat.f_files;
     248           0 :                 sbp->f_ffree = fbuf->fb_stat.f_ffree;
     249           0 :                 sbp->f_favail = fbuf->fb_stat.f_favail;
     250           0 :                 sbp->f_bsize = fbuf->fb_stat.f_frsize;
     251           0 :                 sbp->f_iosize = fbuf->fb_stat.f_bsize;
     252           0 :                 sbp->f_namemax = fbuf->fb_stat.f_namemax;
     253           0 :                 fb_delete(fbuf);
     254             :         }
     255             : 
     256           0 :         return (0);
     257           0 : }
     258             : 
     259             : int
     260           0 : fusefs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred,
     261             :     struct proc *p)
     262             : {
     263           0 :         return (0);
     264             : }
     265             : 
     266             : int
     267           0 : fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
     268             : {
     269           0 :         struct vattr vattr;
     270             :         struct fusefs_mnt *fmp;
     271             :         struct fusefs_node *ip;
     272           0 :         struct vnode *nvp;
     273             :         int i;
     274           0 :         int error;
     275             : retry:
     276           0 :         fmp = VFSTOFUSEFS(mp);
     277             :         /*
     278             :          * check if vnode is in hash.
     279             :          */
     280           0 :         if ((*vpp = ufs_ihashget(fmp->dev, ino)) != NULLVP)
     281           0 :                 return (0);
     282             : 
     283             :         /*
     284             :          * if not create it
     285             :          */
     286           0 :         if ((error = getnewvnode(VT_FUSEFS, mp, &fusefs_vops, &nvp)) != 0) {
     287           0 :                 printf("fusefs: getnewvnode error\n");
     288           0 :                 *vpp = NULLVP;
     289           0 :                 return (error);
     290             :         }
     291             : 
     292           0 :         ip = malloc(sizeof(*ip), M_FUSEFS, M_WAITOK | M_ZERO);
     293           0 :         rrw_init_flags(&ip->ufs_ino.i_lock, "fuseinode",
     294             :             RWL_DUPOK | RWL_IS_VNODE);
     295           0 :         nvp->v_data = ip;
     296           0 :         ip->ufs_ino.i_vnode = nvp;
     297           0 :         ip->ufs_ino.i_dev = fmp->dev;
     298           0 :         ip->ufs_ino.i_number = ino;
     299             : 
     300           0 :         for (i = 0; i < FUFH_MAXTYPE; i++)
     301           0 :                 ip->fufh[i].fh_type = FUFH_INVALID;
     302             : 
     303           0 :         error = ufs_ihashins(&ip->ufs_ino);
     304           0 :         if (error) {
     305           0 :                 vrele(nvp);
     306             : 
     307           0 :                 if (error == EEXIST)
     308           0 :                         goto retry;
     309             : 
     310           0 :                 return (error);
     311             :         }
     312             : 
     313           0 :         ip->ufs_ino.i_ump = (struct ufsmount *)fmp;
     314             : 
     315           0 :         if (ino == FUSE_ROOTINO)
     316           0 :                 nvp->v_flag |= VROOT;
     317             :         else {
     318             :                 /*
     319             :                  * Initialise the file size so that file size changes can be
     320             :                  * detected during file operations.
     321             :                  */
     322           0 :                 error = VOP_GETATTR(nvp, &vattr, curproc->p_ucred, curproc);
     323           0 :                 if (error) {
     324           0 :                         vrele(nvp);
     325           0 :                         return (error);
     326             :                 }
     327           0 :                 ip->filesize = vattr.va_size;
     328             :         }
     329             : 
     330           0 :         *vpp = nvp;
     331             : 
     332           0 :         return (0);
     333           0 : }
     334             : 
     335             : int
     336           0 : fusefs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
     337             : {
     338           0 :         return (EINVAL);
     339             : }
     340             : 
     341             : int
     342           0 : fusefs_vptofh(struct vnode *vp, struct fid *fhp)
     343             : {
     344           0 :         return (EINVAL);
     345             : }
     346             : 
     347             : int
     348           0 : fusefs_init(struct vfsconf *vfc)
     349             : {
     350           0 :         pool_init(&fusefs_fbuf_pool, sizeof(struct fusebuf), 0, 0, PR_WAITOK,
     351             :             "fmsg", NULL);
     352             : 
     353           0 :         return (0);
     354             : }
     355             : 
     356             : int
     357           0 : fusefs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     358             :     void *newp, size_t newlen, struct proc *p)
     359             : {
     360             :         extern int stat_fbufs_in, stat_fbufs_wait, stat_opened_fusedev;
     361             : 
     362             :         /* all sysctl names at this level are terminal */
     363           0 :         if (namelen != 1)
     364           0 :                 return (ENOTDIR);               /* overloaded */
     365             : 
     366           0 :         switch (name[0]) {
     367             :         case FUSEFS_OPENDEVS:
     368           0 :                 return (sysctl_rdint(oldp, oldlenp, newp,
     369           0 :                     stat_opened_fusedev));
     370             :         case FUSEFS_INFBUFS:
     371           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_fbufs_in));
     372             :         case FUSEFS_WAITFBUFS:
     373           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_fbufs_wait));
     374             :         case FUSEFS_POOL_NBPAGES:
     375           0 :                 return (sysctl_rdint(oldp, oldlenp, newp,
     376           0 :                     fusefs_fbuf_pool.pr_npages));
     377             :         default:
     378           0 :                 return (EOPNOTSUPP);
     379             :         }
     380           0 : }
     381             : 
     382             : int
     383           0 : fusefs_checkexp(struct mount *mp, struct mbuf *nam, int *extflagsp,
     384             :     struct ucred **credanonp)
     385             : {
     386           0 :         return (EOPNOTSUPP);
     387             : }

Generated by: LCOV version 1.13