1241519Sattilio/* 2241519Sattilio * Copyright (c) 2007-2009 Google Inc. and Amit Singh 3241519Sattilio * All rights reserved. 4241519Sattilio * 5241519Sattilio * Redistribution and use in source and binary forms, with or without 6241519Sattilio * modification, are permitted provided that the following conditions are 7241519Sattilio * met: 8241519Sattilio * 9241519Sattilio * * Redistributions of source code must retain the above copyright 10241519Sattilio * notice, this list of conditions and the following disclaimer. 11241519Sattilio * * Redistributions in binary form must reproduce the above 12241519Sattilio * copyright notice, this list of conditions and the following disclaimer 13241519Sattilio * in the documentation and/or other materials provided with the 14241519Sattilio * distribution. 15241519Sattilio * * Neither the name of Google Inc. nor the names of its 16241519Sattilio * contributors may be used to endorse or promote products derived from 17241519Sattilio * this software without specific prior written permission. 18241519Sattilio * 19241519Sattilio * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20241519Sattilio * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21241519Sattilio * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22241519Sattilio * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23241519Sattilio * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24241519Sattilio * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25241519Sattilio * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26241519Sattilio * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27241519Sattilio * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28241519Sattilio * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29241519Sattilio * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30241519Sattilio * 31241519Sattilio * Copyright (C) 2005 Csaba Henk. 32241519Sattilio * All rights reserved. 33241519Sattilio * 34241519Sattilio * Redistribution and use in source and binary forms, with or without 35241519Sattilio * modification, are permitted provided that the following conditions 36241519Sattilio * are met: 37241519Sattilio * 1. Redistributions of source code must retain the above copyright 38241519Sattilio * notice, this list of conditions and the following disclaimer. 39241519Sattilio * 2. Redistributions in binary form must reproduce the above copyright 40241519Sattilio * notice, this list of conditions and the following disclaimer in the 41241519Sattilio * documentation and/or other materials provided with the distribution. 42241519Sattilio * 43241519Sattilio * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 44241519Sattilio * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45241519Sattilio * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46241519Sattilio * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 47241519Sattilio * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48241519Sattilio * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49241519Sattilio * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50241519Sattilio * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51241519Sattilio * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52241519Sattilio * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53241519Sattilio * SUCH DAMAGE. 54241519Sattilio */ 55241519Sattilio 56241519Sattilio#include <sys/cdefs.h> 57241519Sattilio__FBSDID("$FreeBSD: stable/10/sys/fs/fuse/fuse_internal.c 332023 2018-04-04 13:16:00Z emaste $"); 58241519Sattilio 59241519Sattilio#include <sys/types.h> 60241519Sattilio#include <sys/module.h> 61241519Sattilio#include <sys/systm.h> 62241519Sattilio#include <sys/errno.h> 63241519Sattilio#include <sys/param.h> 64241519Sattilio#include <sys/kernel.h> 65241519Sattilio#include <sys/conf.h> 66241519Sattilio#include <sys/uio.h> 67241519Sattilio#include <sys/malloc.h> 68241519Sattilio#include <sys/queue.h> 69241519Sattilio#include <sys/lock.h> 70241519Sattilio#include <sys/mutex.h> 71241519Sattilio#include <sys/sx.h> 72241519Sattilio#include <sys/proc.h> 73241519Sattilio#include <sys/mount.h> 74241519Sattilio#include <sys/vnode.h> 75241519Sattilio#include <sys/namei.h> 76241519Sattilio#include <sys/stat.h> 77241519Sattilio#include <sys/unistd.h> 78241519Sattilio#include <sys/filedesc.h> 79241519Sattilio#include <sys/file.h> 80241519Sattilio#include <sys/fcntl.h> 81241519Sattilio#include <sys/dirent.h> 82241519Sattilio#include <sys/bio.h> 83241519Sattilio#include <sys/buf.h> 84241519Sattilio#include <sys/sysctl.h> 85241519Sattilio#include <sys/priv.h> 86241519Sattilio 87241519Sattilio#include "fuse.h" 88241519Sattilio#include "fuse_file.h" 89241519Sattilio#include "fuse_internal.h" 90241519Sattilio#include "fuse_ipc.h" 91241519Sattilio#include "fuse_node.h" 92241519Sattilio#include "fuse_file.h" 93241519Sattilio#include "fuse_param.h" 94241519Sattilio 95241519Sattilio#define FUSE_DEBUG_MODULE INTERNAL 96241519Sattilio#include "fuse_debug.h" 97241519Sattilio 98241519Sattilio#ifdef ZERO_PAD_INCOMPLETE_BUFS 99241519Sattiliostatic int isbzero(void *buf, size_t len); 100241519Sattilio 101241519Sattilio#endif 102241519Sattilio 103241519Sattilio/* access */ 104241519Sattilio 105241519Sattilioint 106241519Sattiliofuse_internal_access(struct vnode *vp, 107241519Sattilio mode_t mode, 108241519Sattilio struct fuse_access_param *facp, 109241519Sattilio struct thread *td, 110241519Sattilio struct ucred *cred) 111241519Sattilio{ 112241519Sattilio int err = 0; 113241519Sattilio uint32_t mask = 0; 114241519Sattilio int dataflags; 115241519Sattilio int vtype; 116241519Sattilio struct mount *mp; 117241519Sattilio struct fuse_dispatcher fdi; 118241519Sattilio struct fuse_access_in *fai; 119241519Sattilio struct fuse_data *data; 120241519Sattilio 121241519Sattilio /* NOT YET DONE */ 122241519Sattilio /* 123241519Sattilio * If this vnop gives you trouble, just return 0 here for a lazy 124241519Sattilio * kludge. 125241519Sattilio */ 126241519Sattilio /* return 0;*/ 127241519Sattilio 128241519Sattilio fuse_trace_printf_func(); 129241519Sattilio 130241519Sattilio mp = vnode_mount(vp); 131241519Sattilio vtype = vnode_vtype(vp); 132241519Sattilio 133241519Sattilio data = fuse_get_mpdata(mp); 134241519Sattilio dataflags = data->dataflags; 135241519Sattilio 136241519Sattilio if ((mode & VWRITE) && vfs_isrdonly(mp)) { 137241519Sattilio return EACCES; 138241519Sattilio } 139241519Sattilio /* Unless explicitly permitted, deny everyone except the fs owner. */ 140241519Sattilio if (vnode_isvroot(vp) && !(facp->facc_flags & FACCESS_NOCHECKSPY)) { 141241519Sattilio if (!(dataflags & FSESS_DAEMON_CAN_SPY)) { 142241519Sattilio int denied = fuse_match_cred(data->daemoncred, 143241519Sattilio cred); 144241519Sattilio 145241519Sattilio if (denied) { 146241519Sattilio return EPERM; 147241519Sattilio } 148241519Sattilio } 149241519Sattilio facp->facc_flags |= FACCESS_NOCHECKSPY; 150241519Sattilio } 151241519Sattilio if (!(facp->facc_flags & FACCESS_DO_ACCESS)) { 152241519Sattilio return 0; 153241519Sattilio } 154241519Sattilio if (((vtype == VREG) && (mode & VEXEC))) { 155241519Sattilio#ifdef NEED_MOUNT_ARGUMENT_FOR_THIS 156241519Sattilio /* Let the kernel handle this through open / close heuristics.*/ 157241519Sattilio return ENOTSUP; 158241519Sattilio#else 159241519Sattilio /* Let the kernel handle this. */ 160241519Sattilio return 0; 161241519Sattilio#endif 162241519Sattilio } 163241519Sattilio if (!fsess_isimpl(mp, FUSE_ACCESS)) { 164241519Sattilio /* Let the kernel handle this. */ 165241519Sattilio return 0; 166241519Sattilio } 167241519Sattilio if (dataflags & FSESS_DEFAULT_PERMISSIONS) { 168241519Sattilio /* Let the kernel handle this. */ 169241519Sattilio return 0; 170241519Sattilio } 171241519Sattilio if ((mode & VADMIN) != 0) { 172241519Sattilio err = priv_check_cred(cred, PRIV_VFS_ADMIN, 0); 173241519Sattilio if (err) { 174241519Sattilio return err; 175241519Sattilio } 176241519Sattilio } 177241519Sattilio if ((mode & (VWRITE | VAPPEND | VADMIN)) != 0) { 178241519Sattilio mask |= W_OK; 179241519Sattilio } 180241519Sattilio if ((mode & VREAD) != 0) { 181241519Sattilio mask |= R_OK; 182241519Sattilio } 183241519Sattilio if ((mode & VEXEC) != 0) { 184241519Sattilio mask |= X_OK; 185241519Sattilio } 186241519Sattilio bzero(&fdi, sizeof(fdi)); 187241519Sattilio 188241519Sattilio fdisp_init(&fdi, sizeof(*fai)); 189241519Sattilio fdisp_make_vp(&fdi, FUSE_ACCESS, vp, td, cred); 190241519Sattilio 191241519Sattilio fai = fdi.indata; 192241519Sattilio fai->mask = F_OK; 193241519Sattilio fai->mask |= mask; 194241519Sattilio 195241519Sattilio err = fdisp_wait_answ(&fdi); 196241519Sattilio fdisp_destroy(&fdi); 197241519Sattilio 198241519Sattilio if (err == ENOSYS) { 199241519Sattilio fsess_set_notimpl(mp, FUSE_ACCESS); 200241519Sattilio err = 0; 201241519Sattilio } 202241519Sattilio return err; 203241519Sattilio} 204241519Sattilio 205241519Sattilio/* fsync */ 206241519Sattilio 207241519Sattilioint 208241519Sattiliofuse_internal_fsync_callback(struct fuse_ticket *tick, struct uio *uio) 209241519Sattilio{ 210241519Sattilio fuse_trace_printf_func(); 211241519Sattilio 212241519Sattilio if (tick->tk_aw_ohead.error == ENOSYS) { 213241519Sattilio fsess_set_notimpl(tick->tk_data->mp, fticket_opcode(tick)); 214241519Sattilio } 215241519Sattilio return 0; 216241519Sattilio} 217241519Sattilio 218241519Sattilioint 219241519Sattiliofuse_internal_fsync(struct vnode *vp, 220241519Sattilio struct thread *td, 221241519Sattilio struct ucred *cred, 222241519Sattilio struct fuse_filehandle *fufh) 223241519Sattilio{ 224241519Sattilio int op = FUSE_FSYNC; 225241519Sattilio struct fuse_fsync_in *ffsi; 226241519Sattilio struct fuse_dispatcher fdi; 227241519Sattilio 228241519Sattilio fuse_trace_printf_func(); 229241519Sattilio 230241519Sattilio if (vnode_isdir(vp)) { 231241519Sattilio op = FUSE_FSYNCDIR; 232241519Sattilio } 233241519Sattilio fdisp_init(&fdi, sizeof(*ffsi)); 234241519Sattilio fdisp_make_vp(&fdi, op, vp, td, cred); 235241519Sattilio ffsi = fdi.indata; 236241519Sattilio ffsi->fh = fufh->fh_id; 237241519Sattilio 238241519Sattilio ffsi->fsync_flags = 1; /* datasync */ 239241519Sattilio 240241519Sattilio fuse_insert_callback(fdi.tick, fuse_internal_fsync_callback); 241241519Sattilio fuse_insert_message(fdi.tick); 242241519Sattilio 243241519Sattilio fdisp_destroy(&fdi); 244241519Sattilio 245241519Sattilio return 0; 246241519Sattilio 247241519Sattilio} 248241519Sattilio 249241519Sattilio/* readdir */ 250241519Sattilio 251241519Sattilioint 252241519Sattiliofuse_internal_readdir(struct vnode *vp, 253241519Sattilio struct uio *uio, 254241519Sattilio struct fuse_filehandle *fufh, 255241519Sattilio struct fuse_iov *cookediov) 256241519Sattilio{ 257241519Sattilio int err = 0; 258241519Sattilio struct fuse_dispatcher fdi; 259241519Sattilio struct fuse_read_in *fri; 260241519Sattilio 261241519Sattilio if (uio_resid(uio) == 0) { 262241519Sattilio return 0; 263241519Sattilio } 264241519Sattilio fdisp_init(&fdi, 0); 265241519Sattilio 266241519Sattilio /* 267241519Sattilio * Note that we DO NOT have a UIO_SYSSPACE here (so no need for p2p 268241519Sattilio * I/O). 269241519Sattilio */ 270241519Sattilio 271241519Sattilio while (uio_resid(uio) > 0) { 272241519Sattilio 273241519Sattilio fdi.iosize = sizeof(*fri); 274241519Sattilio fdisp_make_vp(&fdi, FUSE_READDIR, vp, NULL, NULL); 275241519Sattilio 276241519Sattilio fri = fdi.indata; 277241519Sattilio fri->fh = fufh->fh_id; 278241519Sattilio fri->offset = uio_offset(uio); 279241519Sattilio fri->size = min(uio_resid(uio), FUSE_DEFAULT_IOSIZE); 280241519Sattilio /* mp->max_read */ 281241519Sattilio 282241519Sattilio if ((err = fdisp_wait_answ(&fdi))) { 283241519Sattilio break; 284241519Sattilio } 285241519Sattilio if ((err = fuse_internal_readdir_processdata(uio, fri->size, fdi.answ, 286241519Sattilio fdi.iosize, cookediov))) { 287241519Sattilio break; 288241519Sattilio } 289241519Sattilio } 290241519Sattilio 291241519Sattilio fdisp_destroy(&fdi); 292241519Sattilio return ((err == -1) ? 0 : err); 293241519Sattilio} 294241519Sattilio 295241519Sattilioint 296241519Sattiliofuse_internal_readdir_processdata(struct uio *uio, 297241519Sattilio size_t reqsize, 298241519Sattilio void *buf, 299241519Sattilio size_t bufsize, 300241519Sattilio void *param) 301241519Sattilio{ 302241519Sattilio int err = 0; 303241519Sattilio int cou = 0; 304241519Sattilio int bytesavail; 305241519Sattilio size_t freclen; 306241519Sattilio 307241519Sattilio struct dirent *de; 308241519Sattilio struct fuse_dirent *fudge; 309241519Sattilio struct fuse_iov *cookediov = param; 310241519Sattilio 311241519Sattilio if (bufsize < FUSE_NAME_OFFSET) { 312241519Sattilio return -1; 313241519Sattilio } 314241519Sattilio for (;;) { 315241519Sattilio 316241519Sattilio if (bufsize < FUSE_NAME_OFFSET) { 317241519Sattilio err = -1; 318241519Sattilio break; 319241519Sattilio } 320241519Sattilio fudge = (struct fuse_dirent *)buf; 321241519Sattilio freclen = FUSE_DIRENT_SIZE(fudge); 322241519Sattilio 323241519Sattilio cou++; 324241519Sattilio 325241519Sattilio if (bufsize < freclen) { 326241519Sattilio err = ((cou == 1) ? -1 : 0); 327241519Sattilio break; 328241519Sattilio } 329241519Sattilio#ifdef ZERO_PAD_INCOMPLETE_BUFS 330241519Sattilio if (isbzero(buf, FUSE_NAME_OFFSET)) { 331241519Sattilio err = -1; 332241519Sattilio break; 333241519Sattilio } 334241519Sattilio#endif 335241519Sattilio 336241519Sattilio if (!fudge->namelen || fudge->namelen > MAXNAMLEN) { 337241519Sattilio err = EINVAL; 338241519Sattilio break; 339241519Sattilio } 340241519Sattilio bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *) 341241519Sattilio &fudge->namelen); 342241519Sattilio 343241519Sattilio if (bytesavail > uio_resid(uio)) { 344241519Sattilio err = -1; 345241519Sattilio break; 346241519Sattilio } 347241519Sattilio fiov_refresh(cookediov); 348241519Sattilio fiov_adjust(cookediov, bytesavail); 349241519Sattilio 350241519Sattilio de = (struct dirent *)cookediov->base; 351241519Sattilio de->d_fileno = fudge->ino; /* XXX: truncation */ 352241519Sattilio de->d_reclen = bytesavail; 353241519Sattilio de->d_type = fudge->type; 354241519Sattilio de->d_namlen = fudge->namelen; 355241519Sattilio memcpy((char *)cookediov->base + sizeof(struct dirent) - 356241519Sattilio MAXNAMLEN - 1, 357241519Sattilio (char *)buf + FUSE_NAME_OFFSET, fudge->namelen); 358332023Semaste ((char *)cookediov->base)[bytesavail - 1] = '\0'; 359241519Sattilio 360241519Sattilio err = uiomove(cookediov->base, cookediov->len, uio); 361241519Sattilio if (err) { 362241519Sattilio break; 363241519Sattilio } 364241519Sattilio buf = (char *)buf + freclen; 365241519Sattilio bufsize -= freclen; 366241519Sattilio uio_setoffset(uio, fudge->off); 367241519Sattilio } 368241519Sattilio 369241519Sattilio return err; 370241519Sattilio} 371241519Sattilio 372241519Sattilio/* remove */ 373241519Sattilio 374241519Sattilio#define INVALIDATE_CACHED_VATTRS_UPON_UNLINK 1 375241519Sattilioint 376241519Sattiliofuse_internal_remove(struct vnode *dvp, 377241519Sattilio struct vnode *vp, 378241519Sattilio struct componentname *cnp, 379241519Sattilio enum fuse_opcode op) 380241519Sattilio{ 381241519Sattilio struct fuse_dispatcher fdi; 382241519Sattilio 383241519Sattilio struct vattr *vap = VTOVA(vp); 384241519Sattilio 385241519Sattilio#if INVALIDATE_CACHED_VATTRS_UPON_UNLINK 386241519Sattilio int need_invalidate = 0; 387241519Sattilio uint64_t target_nlink = 0; 388241519Sattilio 389241519Sattilio#endif 390241519Sattilio int err = 0; 391241519Sattilio 392241519Sattilio debug_printf("dvp=%p, cnp=%p, op=%d\n", vp, cnp, op); 393241519Sattilio 394241519Sattilio fdisp_init(&fdi, cnp->cn_namelen + 1); 395241519Sattilio fdisp_make_vp(&fdi, op, dvp, cnp->cn_thread, cnp->cn_cred); 396241519Sattilio 397241519Sattilio memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 398241519Sattilio ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 399241519Sattilio 400241519Sattilio#if INVALIDATE_CACHED_VATTRS_UPON_UNLINK 401241519Sattilio if (vap->va_nlink > 1) { 402241519Sattilio need_invalidate = 1; 403241519Sattilio target_nlink = vap->va_nlink; 404241519Sattilio } 405241519Sattilio#endif 406241519Sattilio 407241519Sattilio err = fdisp_wait_answ(&fdi); 408241519Sattilio fdisp_destroy(&fdi); 409241519Sattilio return err; 410241519Sattilio} 411241519Sattilio 412241519Sattilio/* rename */ 413241519Sattilio 414241519Sattilioint 415241519Sattiliofuse_internal_rename(struct vnode *fdvp, 416241519Sattilio struct componentname *fcnp, 417241519Sattilio struct vnode *tdvp, 418241519Sattilio struct componentname *tcnp) 419241519Sattilio{ 420241519Sattilio struct fuse_dispatcher fdi; 421241519Sattilio struct fuse_rename_in *fri; 422241519Sattilio int err = 0; 423241519Sattilio 424241519Sattilio fdisp_init(&fdi, sizeof(*fri) + fcnp->cn_namelen + tcnp->cn_namelen + 2); 425241519Sattilio fdisp_make_vp(&fdi, FUSE_RENAME, fdvp, tcnp->cn_thread, tcnp->cn_cred); 426241519Sattilio 427241519Sattilio fri = fdi.indata; 428241519Sattilio fri->newdir = VTOI(tdvp); 429241519Sattilio memcpy((char *)fdi.indata + sizeof(*fri), fcnp->cn_nameptr, 430241519Sattilio fcnp->cn_namelen); 431241519Sattilio ((char *)fdi.indata)[sizeof(*fri) + fcnp->cn_namelen] = '\0'; 432241519Sattilio memcpy((char *)fdi.indata + sizeof(*fri) + fcnp->cn_namelen + 1, 433241519Sattilio tcnp->cn_nameptr, tcnp->cn_namelen); 434241519Sattilio ((char *)fdi.indata)[sizeof(*fri) + fcnp->cn_namelen + 435241519Sattilio tcnp->cn_namelen + 1] = '\0'; 436241519Sattilio 437241519Sattilio err = fdisp_wait_answ(&fdi); 438241519Sattilio fdisp_destroy(&fdi); 439241519Sattilio return err; 440241519Sattilio} 441241519Sattilio 442241519Sattilio/* strategy */ 443241519Sattilio 444241519Sattilio/* entity creation */ 445241519Sattilio 446241519Sattiliovoid 447241519Sattiliofuse_internal_newentry_makerequest(struct mount *mp, 448241519Sattilio uint64_t dnid, 449241519Sattilio struct componentname *cnp, 450241519Sattilio enum fuse_opcode op, 451241519Sattilio void *buf, 452241519Sattilio size_t bufsize, 453241519Sattilio struct fuse_dispatcher *fdip) 454241519Sattilio{ 455241519Sattilio debug_printf("fdip=%p\n", fdip); 456241519Sattilio 457241519Sattilio fdip->iosize = bufsize + cnp->cn_namelen + 1; 458241519Sattilio 459241519Sattilio fdisp_make(fdip, op, mp, dnid, cnp->cn_thread, cnp->cn_cred); 460241519Sattilio memcpy(fdip->indata, buf, bufsize); 461241519Sattilio memcpy((char *)fdip->indata + bufsize, cnp->cn_nameptr, cnp->cn_namelen); 462241519Sattilio ((char *)fdip->indata)[bufsize + cnp->cn_namelen] = '\0'; 463241519Sattilio} 464241519Sattilio 465241519Sattilioint 466241519Sattiliofuse_internal_newentry_core(struct vnode *dvp, 467241519Sattilio struct vnode **vpp, 468241519Sattilio struct componentname *cnp, 469241519Sattilio enum vtype vtyp, 470241519Sattilio struct fuse_dispatcher *fdip) 471241519Sattilio{ 472241519Sattilio int err = 0; 473241519Sattilio struct fuse_entry_out *feo; 474241519Sattilio struct mount *mp = vnode_mount(dvp); 475241519Sattilio 476241519Sattilio if ((err = fdisp_wait_answ(fdip))) { 477241519Sattilio return err; 478241519Sattilio } 479241519Sattilio feo = fdip->answ; 480241519Sattilio 481241519Sattilio if ((err = fuse_internal_checkentry(feo, vtyp))) { 482241519Sattilio return err; 483241519Sattilio } 484241519Sattilio err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, vtyp); 485241519Sattilio if (err) { 486241519Sattilio fuse_internal_forget_send(mp, cnp->cn_thread, cnp->cn_cred, 487241519Sattilio feo->nodeid, 1); 488241519Sattilio return err; 489241519Sattilio } 490241519Sattilio cache_attrs(*vpp, feo); 491241519Sattilio 492241519Sattilio return err; 493241519Sattilio} 494241519Sattilio 495241519Sattilioint 496241519Sattiliofuse_internal_newentry(struct vnode *dvp, 497241519Sattilio struct vnode **vpp, 498241519Sattilio struct componentname *cnp, 499241519Sattilio enum fuse_opcode op, 500241519Sattilio void *buf, 501241519Sattilio size_t bufsize, 502241519Sattilio enum vtype vtype) 503241519Sattilio{ 504241519Sattilio int err; 505241519Sattilio struct fuse_dispatcher fdi; 506241519Sattilio struct mount *mp = vnode_mount(dvp); 507241519Sattilio 508241519Sattilio fdisp_init(&fdi, 0); 509241519Sattilio fuse_internal_newentry_makerequest(mp, VTOI(dvp), cnp, op, buf, 510241519Sattilio bufsize, &fdi); 511241519Sattilio err = fuse_internal_newentry_core(dvp, vpp, cnp, vtype, &fdi); 512241519Sattilio fdisp_destroy(&fdi); 513241519Sattilio 514241519Sattilio return err; 515241519Sattilio} 516241519Sattilio 517241519Sattilio/* entity destruction */ 518241519Sattilio 519241519Sattilioint 520241519Sattiliofuse_internal_forget_callback(struct fuse_ticket *ftick, struct uio *uio) 521241519Sattilio{ 522241519Sattilio fuse_internal_forget_send(ftick->tk_data->mp, curthread, NULL, 523241519Sattilio ((struct fuse_in_header *)ftick->tk_ms_fiov.base)->nodeid, 1); 524241519Sattilio 525241519Sattilio return 0; 526241519Sattilio} 527241519Sattilio 528241519Sattiliovoid 529241519Sattiliofuse_internal_forget_send(struct mount *mp, 530241519Sattilio struct thread *td, 531241519Sattilio struct ucred *cred, 532241519Sattilio uint64_t nodeid, 533241519Sattilio uint64_t nlookup) 534241519Sattilio{ 535241519Sattilio 536241519Sattilio struct fuse_dispatcher fdi; 537241519Sattilio struct fuse_forget_in *ffi; 538241519Sattilio 539241519Sattilio debug_printf("mp=%p, nodeid=%ju, nlookup=%ju\n", 540241519Sattilio mp, (uintmax_t)nodeid, (uintmax_t)nlookup); 541241519Sattilio 542241519Sattilio /* 543241519Sattilio * KASSERT(nlookup > 0, ("zero-times forget for vp #%llu", 544241519Sattilio * (long long unsigned) nodeid)); 545241519Sattilio */ 546241519Sattilio 547241519Sattilio fdisp_init(&fdi, sizeof(*ffi)); 548241519Sattilio fdisp_make(&fdi, FUSE_FORGET, mp, nodeid, td, cred); 549241519Sattilio 550241519Sattilio ffi = fdi.indata; 551241519Sattilio ffi->nlookup = nlookup; 552241519Sattilio 553241519Sattilio fuse_insert_message(fdi.tick); 554241519Sattilio fdisp_destroy(&fdi); 555241519Sattilio} 556241519Sattilio 557241519Sattiliovoid 558241519Sattiliofuse_internal_vnode_disappear(struct vnode *vp) 559241519Sattilio{ 560241519Sattilio struct fuse_vnode_data *fvdat = VTOFUD(vp); 561241519Sattilio 562241519Sattilio ASSERT_VOP_ELOCKED(vp, "fuse_internal_vnode_disappear"); 563241519Sattilio fvdat->flag |= FN_REVOKED; 564241519Sattilio cache_purge(vp); 565241519Sattilio} 566241519Sattilio 567241519Sattilio/* fuse start/stop */ 568241519Sattilio 569241519Sattilioint 570241519Sattiliofuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio) 571241519Sattilio{ 572241519Sattilio int err = 0; 573241519Sattilio struct fuse_data *data = tick->tk_data; 574241519Sattilio struct fuse_init_out *fiio; 575241519Sattilio 576241519Sattilio if ((err = tick->tk_aw_ohead.error)) { 577241519Sattilio goto out; 578241519Sattilio } 579241519Sattilio if ((err = fticket_pull(tick, uio))) { 580241519Sattilio goto out; 581241519Sattilio } 582241519Sattilio fiio = fticket_resp(tick)->base; 583241519Sattilio 584241519Sattilio /* XXX: Do we want to check anything further besides this? */ 585241519Sattilio if (fiio->major < 7) { 586241519Sattilio debug_printf("userpace version too low\n"); 587241519Sattilio err = EPROTONOSUPPORT; 588241519Sattilio goto out; 589241519Sattilio } 590241519Sattilio data->fuse_libabi_major = fiio->major; 591241519Sattilio data->fuse_libabi_minor = fiio->minor; 592241519Sattilio 593241519Sattilio if (fuse_libabi_geq(data, 7, 5)) { 594241519Sattilio if (fticket_resp(tick)->len == sizeof(struct fuse_init_out)) { 595241519Sattilio data->max_write = fiio->max_write; 596241519Sattilio } else { 597241519Sattilio err = EINVAL; 598241519Sattilio } 599241519Sattilio } else { 600241519Sattilio /* Old fix values */ 601241519Sattilio data->max_write = 4096; 602241519Sattilio } 603241519Sattilio 604241519Sattilioout: 605241519Sattilio if (err) { 606241519Sattilio fdata_set_dead(data); 607241519Sattilio } 608241519Sattilio FUSE_LOCK(); 609241519Sattilio data->dataflags |= FSESS_INITED; 610241519Sattilio wakeup(&data->ticketer); 611241519Sattilio FUSE_UNLOCK(); 612241519Sattilio 613241519Sattilio return 0; 614241519Sattilio} 615241519Sattilio 616241519Sattiliovoid 617241519Sattiliofuse_internal_send_init(struct fuse_data *data, struct thread *td) 618241519Sattilio{ 619241519Sattilio struct fuse_init_in *fiii; 620241519Sattilio struct fuse_dispatcher fdi; 621241519Sattilio 622241519Sattilio fdisp_init(&fdi, sizeof(*fiii)); 623241519Sattilio fdisp_make(&fdi, FUSE_INIT, data->mp, 0, td, NULL); 624241519Sattilio fiii = fdi.indata; 625241519Sattilio fiii->major = FUSE_KERNEL_VERSION; 626241519Sattilio fiii->minor = FUSE_KERNEL_MINOR_VERSION; 627241519Sattilio fiii->max_readahead = FUSE_DEFAULT_IOSIZE * 16; 628241519Sattilio fiii->flags = 0; 629241519Sattilio 630241519Sattilio fuse_insert_callback(fdi.tick, fuse_internal_init_callback); 631241519Sattilio fuse_insert_message(fdi.tick); 632241519Sattilio fdisp_destroy(&fdi); 633241519Sattilio} 634241519Sattilio 635241519Sattilio#ifdef ZERO_PAD_INCOMPLETE_BUFS 636241519Sattiliostatic int 637241519Sattilioisbzero(void *buf, size_t len) 638241519Sattilio{ 639241519Sattilio int i; 640241519Sattilio 641241519Sattilio for (i = 0; i < len; i++) { 642241519Sattilio if (((char *)buf)[i]) 643241519Sattilio return (0); 644241519Sattilio } 645241519Sattilio 646241519Sattilio return (1); 647241519Sattilio} 648241519Sattilio 649241519Sattilio#endif 650