fuse_vfsops.c revision 1.1
1/* $OpenBSD: fuse_vfsops.c,v 1.1 2013/06/03 15:50:56 tedu 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/malloc.h> 20#include <sys/mount.h> 21#include <sys/pool.h> 22#include <sys/statvfs.h> 23#include <sys/sysctl.h> 24#include <sys/vnode.h> 25#include <sys/fusebuf.h> 26 27#include "fusefs_node.h" 28#include "fusefs.h" 29 30int fusefs_mount(struct mount *, const char *, void *, struct nameidata *, 31 struct proc *); 32int fusefs_start(struct mount *, int, struct proc *); 33int fusefs_unmount(struct mount *, int, struct proc *); 34int fusefs_root(struct mount *, struct vnode **); 35int fusefs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); 36int fusefs_statfs(struct mount *, struct statfs *, struct proc *); 37int fusefs_sync(struct mount *, int, struct ucred *, struct proc *); 38int fusefs_vget(struct mount *, ino_t, struct vnode **); 39int fusefs_fhtovp(struct mount *, struct fid *, struct vnode **); 40int fusefs_vptofh(struct vnode *, struct fid *); 41int fusefs_init(struct vfsconf *); 42int fusefs_sysctl(int *, u_int, void *, size_t *, void *, size_t, 43 struct proc *); 44int fusefs_checkexp(struct mount *, struct mbuf *, int *, 45 struct ucred **); 46 47const struct vfsops fusefs_vfsops = { 48 fusefs_mount, 49 fusefs_start, 50 fusefs_unmount, 51 fusefs_root, 52 fusefs_quotactl, 53 fusefs_statfs, 54 fusefs_sync, 55 fusefs_vget, 56 fusefs_fhtovp, 57 fusefs_vptofh, 58 fusefs_init, 59 fusefs_sysctl, 60 fusefs_checkexp 61}; 62 63struct pool fusefs_fbuf_pool; 64 65int 66fusefs_mount(struct mount *mp, const char *path, void *data, 67 struct nameidata *ndp, struct proc *p) 68{ 69 struct fusefs_mnt *fmp; 70 struct fusebuf *fbuf; 71 struct fusefs_args args; 72 int error; 73 74 if (mp->mnt_flag & MNT_UPDATE) 75 return (EOPNOTSUPP); 76 77 error = copyin(data, &args, sizeof(struct fusefs_args)); 78 if (error) 79 return (error); 80 81 fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO); 82 fmp->mp = mp; 83 fmp->sess_init = 0; 84 fmp->dev = args.dev; 85 printf("fusefs: mount dev %i\n", fmp->dev); 86 mp->mnt_data = fmp; 87 88 mp->mnt_flag |= MNT_LOCAL; 89 vfs_getnewfsid(mp); 90 91 bzero(mp->mnt_stat.f_mntonname, MNAMELEN); 92 strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); 93 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 94 bcopy("fusefs", mp->mnt_stat.f_mntfromname, sizeof("fusefs")); 95 96 fuse_device_set_fmp(fmp); 97 fbuf = fb_setup(0, 0, FBT_INIT, p); 98 99 /* cannot tsleep on mount */ 100 fuse_device_queue_fbuf(fmp->dev, fbuf); 101 102 return (0); 103} 104 105int 106fusefs_start(struct mount *mp, int flags, struct proc *p) 107{ 108 return (0); 109} 110 111int 112fusefs_unmount(struct mount *mp, int mntflags, struct proc *p) 113{ 114 struct fusefs_mnt *fmp; 115 struct fusebuf *fbuf; 116 extern int doforce; 117 int flags = 0; 118 int error; 119 120 fmp = VFSTOFUSEFS(mp); 121 122 if (fmp->sess_init) { 123 124 fmp->sess_init = 0; 125 fbuf = fb_setup(0, 0, FBT_DESTROY, p); 126 127 error = fb_queue(fmp->dev, fbuf); 128 pool_put(&fusefs_fbuf_pool, fbuf); 129 130 if (error) 131 printf("error from fuse\n"); 132 133 } else { 134 fuse_device_cleanup(fmp->dev, NULL); 135 } 136 137 if (mntflags & MNT_FORCE) { 138 /* fusefs can never be rootfs so don't check for it */ 139 if (!doforce) 140 return (EINVAL); 141 142 flags |= FORCECLOSE; 143 } 144 145 if ((error = vflush(mp, 0, flags))) 146 return (error); 147 148 free(fmp, M_FUSEFS); 149 150 return (error); 151} 152 153int 154fusefs_root(struct mount *mp, struct vnode **vpp) 155{ 156 struct vnode *nvp; 157 struct fusefs_node *ip; 158 int error; 159 160 if ((error = VFS_VGET(mp, (ino_t)FUSE_ROOTINO, &nvp)) != 0) 161 return (error); 162 163 ip = VTOI(nvp); 164 nvp->v_type = VDIR; 165 ip->vtype = VDIR; 166 167 *vpp = nvp; 168 return (0); 169} 170 171int fusefs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, 172 struct proc *p) 173{ 174 return (0); 175} 176 177int fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) 178{ 179 struct fusefs_mnt *fmp; 180 struct fusebuf *fbuf; 181 int error; 182 183 fmp = VFSTOFUSEFS(mp); 184 185 if (fmp->sess_init) { 186 fbuf = fb_setup(0, FUSE_ROOT_ID, FBT_STATFS, p); 187 188 error = fb_queue(fmp->dev, fbuf); 189 190 if (error) { 191 pool_put(&fusefs_fbuf_pool, fbuf); 192 return (error); 193 } 194 195 sbp->f_bavail = fbuf->fb_stat.f_bavail; 196 sbp->f_bfree = fbuf->fb_stat.f_bfree; 197 sbp->f_blocks = fbuf->fb_stat.f_blocks; 198 sbp->f_files = fbuf->fb_stat.f_files; 199 sbp->f_ffree = fbuf->fb_stat.f_ffree; 200 sbp->f_bsize = fbuf->fb_stat.f_frsize; 201 sbp->f_namemax = fbuf->fb_stat.f_namemax; 202 pool_put(&fusefs_fbuf_pool, fbuf); 203 } else { 204 sbp->f_bavail = 0; 205 sbp->f_bfree = 0; 206 sbp->f_blocks = 0; 207 sbp->f_ffree = 0; 208 sbp->f_files = 0; 209 sbp->f_bsize = 0; 210 sbp->f_namemax = 0; 211 } 212 213 return (0); 214} 215 216int fusefs_sync(struct mount *mp, int waitfor, struct ucred *cred, 217 struct proc *p) 218{ 219 return (0); 220} 221 222int fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) 223{ 224 struct fusefs_mnt *fmp; 225 struct fusefs_node *ip; 226 struct vnode *nvp; 227 int i; 228 int error; 229retry: 230 fmp = VFSTOFUSEFS(mp); 231 /* 232 * check if vnode is in hash. 233 */ 234 if ((*vpp = ufs_ihashget(fmp->dev, ino)) != NULLVP) 235 return (0); 236 237 /* 238 * if not create it 239 */ 240 if ((error = getnewvnode(VT_FUSEFS, mp, &fusefs_vops, &nvp)) != 0) { 241 printf("fuse: getnewvnode error\n"); 242 *vpp = NULLVP; 243 return (error); 244 } 245 246 ip = malloc(sizeof(*ip), M_FUSEFS, M_WAITOK | M_ZERO); 247 lockinit(&ip->ufs_ino.i_lock, PINOD, "fuseinode", 0, 0); 248 nvp->v_data = ip; 249 ip->ufs_ino.i_vnode = nvp; 250 ip->ufs_ino.i_dev = fmp->dev; 251 ip->ufs_ino.i_number = ino; 252 ip->parent = 0; 253 254 for (i = 0; i < FUFH_MAXTYPE; i++) 255 ip->fufh[i].fh_type = FUFH_INVALID; 256 257 error = ufs_ihashins(&ip->ufs_ino); 258 if (error) { 259 vrele(nvp); 260 261 if (error == EEXIST) 262 goto retry; 263 264 return (error); 265 } 266 267 ip->ufs_ino.i_ump = (struct ufsmount *)fmp; 268 269 if (ino == FUSE_ROOTINO) 270 nvp->v_flag |= VROOT; 271 272 *vpp = nvp; 273 274 return (0); 275} 276 277int fusefs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) 278{ 279 return (0); 280} 281 282int fusefs_vptofh(struct vnode *vp, struct fid *fhp) 283{ 284 return (0); 285} 286 287int fusefs_init(struct vfsconf *vfc) 288{ 289 pool_init(&fusefs_fbuf_pool, sizeof(struct fusebuf), 0, 0, 0, 290 "fmsg", &pool_allocator_nointr); 291 292 return (0); 293} 294 295int fusefs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 296 void *newp, size_t newlen, struct proc *p) 297{ 298 extern int stat_fbufs_in, stat_fbufs_wait, stat_opened_fusedev; 299 300 /* all sysctl names at this level are terminal */ 301 if (namelen != 1) 302 return (ENOTDIR); /* overloaded */ 303 304 switch (name[0]) { 305 case FUSEFS_NB_OPENDEVS: 306 return (sysctl_rdint(oldp, oldlenp, newp, 307 stat_opened_fusedev)); 308 case FUSEFS_INFBUFS: 309 return (sysctl_rdint(oldp, oldlenp, newp, stat_fbufs_in)); 310 case FUSEFS_WAITFBUFS: 311 return (sysctl_rdint(oldp, oldlenp, newp, stat_fbufs_wait)); 312 case FUSEFS_POOL_NBPAGES: 313 return (sysctl_rdint(oldp, oldlenp, newp, 314 fusefs_fbuf_pool.pr_npages)); 315 default: 316 return (EOPNOTSUPP); 317 } 318} 319 320int fusefs_checkexp(struct mount *mp, struct mbuf *nam, int *extflagsp, 321 struct ucred **credanonp) 322{ 323 return (0); 324} 325