1*5812c3ccSTomohiro Kusumi /*- 2*5812c3ccSTomohiro Kusumi * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org> 3*5812c3ccSTomohiro Kusumi * Copyright (c) 2019 The DragonFly Project 4*5812c3ccSTomohiro Kusumi * All rights reserved. 5*5812c3ccSTomohiro Kusumi * 6*5812c3ccSTomohiro Kusumi * Redistribution and use in source and binary forms, with or without 7*5812c3ccSTomohiro Kusumi * modification, are permitted provided that the following conditions 8*5812c3ccSTomohiro Kusumi * are met: 9*5812c3ccSTomohiro Kusumi * 1. Redistributions of source code must retain the above copyright 10*5812c3ccSTomohiro Kusumi * notice, this list of conditions and the following disclaimer. 11*5812c3ccSTomohiro Kusumi * 2. Redistributions in binary form must reproduce the above copyright 12*5812c3ccSTomohiro Kusumi * notice, this list of conditions and the following disclaimer in the 13*5812c3ccSTomohiro Kusumi * documentation and/or other materials provided with the distribution. 14*5812c3ccSTomohiro Kusumi * 15*5812c3ccSTomohiro Kusumi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*5812c3ccSTomohiro Kusumi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*5812c3ccSTomohiro Kusumi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*5812c3ccSTomohiro Kusumi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*5812c3ccSTomohiro Kusumi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*5812c3ccSTomohiro Kusumi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*5812c3ccSTomohiro Kusumi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*5812c3ccSTomohiro Kusumi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*5812c3ccSTomohiro Kusumi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*5812c3ccSTomohiro Kusumi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*5812c3ccSTomohiro Kusumi * SUCH DAMAGE. 26*5812c3ccSTomohiro Kusumi */ 27*5812c3ccSTomohiro Kusumi 28*5812c3ccSTomohiro Kusumi #include "fuse.h" 29*5812c3ccSTomohiro Kusumi 30*5812c3ccSTomohiro Kusumi static MALLOC_DEFINE(M_FUSE_NODE, "fuse_node", "FUSE node"); 31*5812c3ccSTomohiro Kusumi 32*5812c3ccSTomohiro Kusumi static struct objcache *fuse_node_objcache = NULL; 33*5812c3ccSTomohiro Kusumi static struct objcache_malloc_args fuse_node_args = { 34*5812c3ccSTomohiro Kusumi sizeof(struct fuse_node), M_FUSE_NODE, 35*5812c3ccSTomohiro Kusumi }; 36*5812c3ccSTomohiro Kusumi 37*5812c3ccSTomohiro Kusumi static MALLOC_DEFINE(M_FUSE_DENT, "fuse_dent", "FUSE dent"); 38*5812c3ccSTomohiro Kusumi 39*5812c3ccSTomohiro Kusumi static struct objcache *fuse_dent_objcache = NULL; 40*5812c3ccSTomohiro Kusumi static struct objcache_malloc_args fuse_dent_args = { 41*5812c3ccSTomohiro Kusumi sizeof(struct fuse_dent), M_FUSE_DENT, 42*5812c3ccSTomohiro Kusumi }; 43*5812c3ccSTomohiro Kusumi 44*5812c3ccSTomohiro Kusumi static int 45*5812c3ccSTomohiro Kusumi fuse_dent_cmp(struct fuse_dent *p1, struct fuse_dent *p2) 46*5812c3ccSTomohiro Kusumi { 47*5812c3ccSTomohiro Kusumi return strcmp(p1->name, p2->name); 48*5812c3ccSTomohiro Kusumi } 49*5812c3ccSTomohiro Kusumi 50*5812c3ccSTomohiro Kusumi RB_PROTOTYPE_STATIC(fuse_dent_tree, fuse_dent, entry, fuse_dent_cmp); 51*5812c3ccSTomohiro Kusumi RB_GENERATE_STATIC(fuse_dent_tree, fuse_dent, dent_entry, fuse_dent_cmp); 52*5812c3ccSTomohiro Kusumi 53*5812c3ccSTomohiro Kusumi void 54*5812c3ccSTomohiro Kusumi fuse_node_new(struct fuse_mount *fmp, uint64_t ino, enum vtype vtyp, 55*5812c3ccSTomohiro Kusumi struct fuse_node **fnpp) 56*5812c3ccSTomohiro Kusumi { 57*5812c3ccSTomohiro Kusumi struct fuse_node *fnp; 58*5812c3ccSTomohiro Kusumi 59*5812c3ccSTomohiro Kusumi fnp = objcache_get(fuse_node_objcache, M_WAITOK); 60*5812c3ccSTomohiro Kusumi KKASSERT(fnp); 61*5812c3ccSTomohiro Kusumi 62*5812c3ccSTomohiro Kusumi memset(fnp, 0, sizeof(*fnp)); 63*5812c3ccSTomohiro Kusumi fnp->vp = NULL; 64*5812c3ccSTomohiro Kusumi fnp->fmp = fmp; 65*5812c3ccSTomohiro Kusumi fnp->pfnp = NULL; 66*5812c3ccSTomohiro Kusumi 67*5812c3ccSTomohiro Kusumi mtx_init(&fnp->node_lock, "fuse_node_lock"); 68*5812c3ccSTomohiro Kusumi RB_INIT(&fnp->dent_head); 69*5812c3ccSTomohiro Kusumi 70*5812c3ccSTomohiro Kusumi fnp->ino = ino; 71*5812c3ccSTomohiro Kusumi fnp->type = vtyp; 72*5812c3ccSTomohiro Kusumi fnp->nlink = 0; 73*5812c3ccSTomohiro Kusumi fnp->size = 0; 74*5812c3ccSTomohiro Kusumi fnp->nlookup = 0; 75*5812c3ccSTomohiro Kusumi fnp->fh = 0; 76*5812c3ccSTomohiro Kusumi fnp->closed = false; 77*5812c3ccSTomohiro Kusumi 78*5812c3ccSTomohiro Kusumi *fnpp = fnp; 79*5812c3ccSTomohiro Kusumi KKASSERT(*fnpp); 80*5812c3ccSTomohiro Kusumi } 81*5812c3ccSTomohiro Kusumi 82*5812c3ccSTomohiro Kusumi void 83*5812c3ccSTomohiro Kusumi fuse_node_free(struct fuse_node *fnp) 84*5812c3ccSTomohiro Kusumi { 85*5812c3ccSTomohiro Kusumi struct fuse_node *dfnp = fnp->pfnp; 86*5812c3ccSTomohiro Kusumi struct fuse_dent *fep; 87*5812c3ccSTomohiro Kusumi 88*5812c3ccSTomohiro Kusumi fuse_dbg("free ino=%ju\n", fnp->ino); 89*5812c3ccSTomohiro Kusumi 90*5812c3ccSTomohiro Kusumi if (dfnp) { 91*5812c3ccSTomohiro Kusumi mtx_lock(&dfnp->node_lock); 92*5812c3ccSTomohiro Kusumi RB_FOREACH(fep, fuse_dent_tree, &dfnp->dent_head) { 93*5812c3ccSTomohiro Kusumi if (fep->fnp == fnp) { 94*5812c3ccSTomohiro Kusumi fuse_dent_detach(dfnp, fep); 95*5812c3ccSTomohiro Kusumi fuse_dent_free(fep); 96*5812c3ccSTomohiro Kusumi break; 97*5812c3ccSTomohiro Kusumi } 98*5812c3ccSTomohiro Kusumi } 99*5812c3ccSTomohiro Kusumi mtx_unlock(&dfnp->node_lock); 100*5812c3ccSTomohiro Kusumi } 101*5812c3ccSTomohiro Kusumi 102*5812c3ccSTomohiro Kusumi mtx_lock(&fnp->node_lock); 103*5812c3ccSTomohiro Kusumi if (fnp->type == VDIR) { 104*5812c3ccSTomohiro Kusumi while ((fep = RB_ROOT(&fnp->dent_head))) { 105*5812c3ccSTomohiro Kusumi fuse_dent_detach(fnp, fep); 106*5812c3ccSTomohiro Kusumi fuse_dent_free(fep); 107*5812c3ccSTomohiro Kusumi } 108*5812c3ccSTomohiro Kusumi } 109*5812c3ccSTomohiro Kusumi fnp->vp->v_data = NULL; 110*5812c3ccSTomohiro Kusumi fnp->vp = NULL; 111*5812c3ccSTomohiro Kusumi fnp->nlink = -123; /* debug */ 112*5812c3ccSTomohiro Kusumi mtx_unlock(&fnp->node_lock); 113*5812c3ccSTomohiro Kusumi 114*5812c3ccSTomohiro Kusumi objcache_put(fuse_node_objcache, fnp); 115*5812c3ccSTomohiro Kusumi } 116*5812c3ccSTomohiro Kusumi 117*5812c3ccSTomohiro Kusumi void 118*5812c3ccSTomohiro Kusumi fuse_dent_new(struct fuse_node *fnp, const char *name, int namelen, 119*5812c3ccSTomohiro Kusumi struct fuse_dent **fepp) 120*5812c3ccSTomohiro Kusumi { 121*5812c3ccSTomohiro Kusumi struct fuse_dent *fep; 122*5812c3ccSTomohiro Kusumi 123*5812c3ccSTomohiro Kusumi fep = objcache_get(fuse_dent_objcache, M_WAITOK); 124*5812c3ccSTomohiro Kusumi KKASSERT(fep); 125*5812c3ccSTomohiro Kusumi 126*5812c3ccSTomohiro Kusumi if (namelen >= 0) 127*5812c3ccSTomohiro Kusumi fep->name = kstrndup(name, namelen, M_TEMP); 128*5812c3ccSTomohiro Kusumi else 129*5812c3ccSTomohiro Kusumi fep->name = kstrdup(name, M_TEMP); 130*5812c3ccSTomohiro Kusumi KKASSERT(fep->name); 131*5812c3ccSTomohiro Kusumi fep->fnp = fnp; 132*5812c3ccSTomohiro Kusumi 133*5812c3ccSTomohiro Kusumi KASSERT(fnp->nlink >= 0, ("new ino=%ju nlink=%d dent=\"%s\"", 134*5812c3ccSTomohiro Kusumi fnp->ino, fnp->nlink, fep->name)); 135*5812c3ccSTomohiro Kusumi KKASSERT(fnp->nlink < LINK_MAX); 136*5812c3ccSTomohiro Kusumi fnp->nlink++; 137*5812c3ccSTomohiro Kusumi 138*5812c3ccSTomohiro Kusumi *fepp = fep; 139*5812c3ccSTomohiro Kusumi KKASSERT(*fepp); 140*5812c3ccSTomohiro Kusumi } 141*5812c3ccSTomohiro Kusumi 142*5812c3ccSTomohiro Kusumi void 143*5812c3ccSTomohiro Kusumi fuse_dent_free(struct fuse_dent *fep) 144*5812c3ccSTomohiro Kusumi { 145*5812c3ccSTomohiro Kusumi struct fuse_node *fnp = fep->fnp; 146*5812c3ccSTomohiro Kusumi 147*5812c3ccSTomohiro Kusumi fuse_dbg("free dent=\"%s\"\n", fep->name); 148*5812c3ccSTomohiro Kusumi 149*5812c3ccSTomohiro Kusumi KASSERT(fnp->nlink > 0, ("free ino=%ju nlink=%d dent=\"%s\"", 150*5812c3ccSTomohiro Kusumi fnp->ino, fnp->nlink, fep->name)); 151*5812c3ccSTomohiro Kusumi 152*5812c3ccSTomohiro Kusumi if (fep->name) { 153*5812c3ccSTomohiro Kusumi kfree(fep->name, M_TEMP); 154*5812c3ccSTomohiro Kusumi fep->name = NULL; 155*5812c3ccSTomohiro Kusumi } 156*5812c3ccSTomohiro Kusumi 157*5812c3ccSTomohiro Kusumi KKASSERT(fnp->nlink <= LINK_MAX); 158*5812c3ccSTomohiro Kusumi fnp->nlink--; 159*5812c3ccSTomohiro Kusumi 160*5812c3ccSTomohiro Kusumi fep->fnp = NULL; 161*5812c3ccSTomohiro Kusumi objcache_put(fuse_dent_objcache, fep); 162*5812c3ccSTomohiro Kusumi } 163*5812c3ccSTomohiro Kusumi 164*5812c3ccSTomohiro Kusumi void 165*5812c3ccSTomohiro Kusumi fuse_dent_attach(struct fuse_node *dfnp, struct fuse_dent *fep) 166*5812c3ccSTomohiro Kusumi { 167*5812c3ccSTomohiro Kusumi KKASSERT(dfnp); 168*5812c3ccSTomohiro Kusumi KKASSERT(dfnp->type == VDIR); 169*5812c3ccSTomohiro Kusumi KKASSERT(mtx_islocked_ex(&dfnp->node_lock)); 170*5812c3ccSTomohiro Kusumi 171*5812c3ccSTomohiro Kusumi RB_INSERT(fuse_dent_tree, &dfnp->dent_head, fep); 172*5812c3ccSTomohiro Kusumi } 173*5812c3ccSTomohiro Kusumi 174*5812c3ccSTomohiro Kusumi void 175*5812c3ccSTomohiro Kusumi fuse_dent_detach(struct fuse_node *dfnp, struct fuse_dent *fep) 176*5812c3ccSTomohiro Kusumi { 177*5812c3ccSTomohiro Kusumi KKASSERT(dfnp); 178*5812c3ccSTomohiro Kusumi KKASSERT(dfnp->type == VDIR); 179*5812c3ccSTomohiro Kusumi KKASSERT(mtx_islocked_ex(&dfnp->node_lock)); 180*5812c3ccSTomohiro Kusumi 181*5812c3ccSTomohiro Kusumi RB_REMOVE(fuse_dent_tree, &dfnp->dent_head, fep); 182*5812c3ccSTomohiro Kusumi } 183*5812c3ccSTomohiro Kusumi 184*5812c3ccSTomohiro Kusumi int 185*5812c3ccSTomohiro Kusumi fuse_dent_find(struct fuse_node *dfnp, const char *name, int namelen, 186*5812c3ccSTomohiro Kusumi struct fuse_dent **fepp) 187*5812c3ccSTomohiro Kusumi { 188*5812c3ccSTomohiro Kusumi struct fuse_dent *fep, find; 189*5812c3ccSTomohiro Kusumi int error; 190*5812c3ccSTomohiro Kusumi 191*5812c3ccSTomohiro Kusumi if (namelen >= 0) 192*5812c3ccSTomohiro Kusumi find.name = kstrndup(name, namelen, M_TEMP); 193*5812c3ccSTomohiro Kusumi else 194*5812c3ccSTomohiro Kusumi find.name = kstrdup(name, M_TEMP); 195*5812c3ccSTomohiro Kusumi KKASSERT(find.name); 196*5812c3ccSTomohiro Kusumi 197*5812c3ccSTomohiro Kusumi fep = RB_FIND(fuse_dent_tree, &dfnp->dent_head, &find); 198*5812c3ccSTomohiro Kusumi if (fep) { 199*5812c3ccSTomohiro Kusumi error = 0; 200*5812c3ccSTomohiro Kusumi if (fepp) 201*5812c3ccSTomohiro Kusumi *fepp = fep; 202*5812c3ccSTomohiro Kusumi } else { 203*5812c3ccSTomohiro Kusumi error = ENOENT; 204*5812c3ccSTomohiro Kusumi fuse_dbg("dent=\"%s\" not found\n", find.name); 205*5812c3ccSTomohiro Kusumi } 206*5812c3ccSTomohiro Kusumi 207*5812c3ccSTomohiro Kusumi kfree(find.name, M_TEMP); 208*5812c3ccSTomohiro Kusumi 209*5812c3ccSTomohiro Kusumi return error; 210*5812c3ccSTomohiro Kusumi } 211*5812c3ccSTomohiro Kusumi 212*5812c3ccSTomohiro Kusumi int 213*5812c3ccSTomohiro Kusumi fuse_alloc_node(struct fuse_node *dfnp, uint64_t ino, const char *name, 214*5812c3ccSTomohiro Kusumi int namelen, enum vtype vtyp, struct vnode **vpp) 215*5812c3ccSTomohiro Kusumi { 216*5812c3ccSTomohiro Kusumi struct fuse_node *fnp = NULL; 217*5812c3ccSTomohiro Kusumi struct fuse_dent *fep = NULL; 218*5812c3ccSTomohiro Kusumi int error; 219*5812c3ccSTomohiro Kusumi 220*5812c3ccSTomohiro Kusumi if (vtyp == VBLK || vtyp == VCHR || vtyp == VFIFO) 221*5812c3ccSTomohiro Kusumi return EINVAL; 222*5812c3ccSTomohiro Kusumi 223*5812c3ccSTomohiro Kusumi mtx_lock(&dfnp->node_lock); 224*5812c3ccSTomohiro Kusumi error = fuse_dent_find(dfnp, name, namelen, &fep); 225*5812c3ccSTomohiro Kusumi if (!error) { 226*5812c3ccSTomohiro Kusumi mtx_unlock(&dfnp->node_lock); 227*5812c3ccSTomohiro Kusumi return EEXIST; 228*5812c3ccSTomohiro Kusumi } else if (error == ENOENT) { 229*5812c3ccSTomohiro Kusumi fuse_node_new(dfnp->fmp, ino, vtyp, &fnp); 230*5812c3ccSTomohiro Kusumi mtx_lock(&fnp->node_lock); 231*5812c3ccSTomohiro Kusumi fnp->pfnp = dfnp; 232*5812c3ccSTomohiro Kusumi fuse_dent_new(fnp, name, namelen, &fep); 233*5812c3ccSTomohiro Kusumi fuse_dent_attach(dfnp, fep); 234*5812c3ccSTomohiro Kusumi mtx_unlock(&fnp->node_lock); 235*5812c3ccSTomohiro Kusumi } else 236*5812c3ccSTomohiro Kusumi KKASSERT(0); 237*5812c3ccSTomohiro Kusumi mtx_unlock(&dfnp->node_lock); 238*5812c3ccSTomohiro Kusumi 239*5812c3ccSTomohiro Kusumi error = fuse_node_vn(fnp, LK_EXCLUSIVE, vpp); 240*5812c3ccSTomohiro Kusumi if (error) { 241*5812c3ccSTomohiro Kusumi mtx_lock(&dfnp->node_lock); 242*5812c3ccSTomohiro Kusumi fuse_dent_detach(dfnp, fep); 243*5812c3ccSTomohiro Kusumi fuse_dent_free(fep); 244*5812c3ccSTomohiro Kusumi mtx_unlock(&dfnp->node_lock); 245*5812c3ccSTomohiro Kusumi fuse_node_free(fnp); 246*5812c3ccSTomohiro Kusumi return error; 247*5812c3ccSTomohiro Kusumi } 248*5812c3ccSTomohiro Kusumi KKASSERT(*vpp); 249*5812c3ccSTomohiro Kusumi 250*5812c3ccSTomohiro Kusumi fuse_dbg("fnp=%p ino=%ju dent=\"%s\"\n", fnp, fnp->ino, fep->name); 251*5812c3ccSTomohiro Kusumi 252*5812c3ccSTomohiro Kusumi return 0; 253*5812c3ccSTomohiro Kusumi } 254*5812c3ccSTomohiro Kusumi 255*5812c3ccSTomohiro Kusumi int 256*5812c3ccSTomohiro Kusumi fuse_node_vn(struct fuse_node *fnp, int flags, struct vnode **vpp) 257*5812c3ccSTomohiro Kusumi { 258*5812c3ccSTomohiro Kusumi struct mount *mp = fnp->fmp->mp; 259*5812c3ccSTomohiro Kusumi struct vnode *vp; 260*5812c3ccSTomohiro Kusumi int error; 261*5812c3ccSTomohiro Kusumi retry: 262*5812c3ccSTomohiro Kusumi mtx_lock(&fnp->node_lock); 263*5812c3ccSTomohiro Kusumi vp = fnp->vp; 264*5812c3ccSTomohiro Kusumi if (vp) { 265*5812c3ccSTomohiro Kusumi vhold(vp); 266*5812c3ccSTomohiro Kusumi mtx_unlock(&fnp->node_lock); 267*5812c3ccSTomohiro Kusumi 268*5812c3ccSTomohiro Kusumi error = vget(vp, flags | LK_RETRY); 269*5812c3ccSTomohiro Kusumi if (error) { 270*5812c3ccSTomohiro Kusumi vdrop(vp); 271*5812c3ccSTomohiro Kusumi goto retry; 272*5812c3ccSTomohiro Kusumi } 273*5812c3ccSTomohiro Kusumi vdrop(vp); 274*5812c3ccSTomohiro Kusumi *vpp = vp; 275*5812c3ccSTomohiro Kusumi return 0; 276*5812c3ccSTomohiro Kusumi } 277*5812c3ccSTomohiro Kusumi mtx_unlock(&fnp->node_lock); 278*5812c3ccSTomohiro Kusumi 279*5812c3ccSTomohiro Kusumi error = getnewvnode(VT_FUSE, mp, &vp, VLKTIMEOUT, LK_CANRECURSE); 280*5812c3ccSTomohiro Kusumi if (error) 281*5812c3ccSTomohiro Kusumi return error; 282*5812c3ccSTomohiro Kusumi vp->v_type = fnp->type; 283*5812c3ccSTomohiro Kusumi vp->v_data = fnp; 284*5812c3ccSTomohiro Kusumi 285*5812c3ccSTomohiro Kusumi switch (vp->v_type) { 286*5812c3ccSTomohiro Kusumi case VREG: 287*5812c3ccSTomohiro Kusumi vinitvmio(vp, fnp->size, FUSE_BLKSIZE, -1); 288*5812c3ccSTomohiro Kusumi break; 289*5812c3ccSTomohiro Kusumi case VDIR: 290*5812c3ccSTomohiro Kusumi break; 291*5812c3ccSTomohiro Kusumi case VBLK: 292*5812c3ccSTomohiro Kusumi case VCHR: 293*5812c3ccSTomohiro Kusumi KKASSERT(0); 294*5812c3ccSTomohiro Kusumi vp->v_ops = &mp->mnt_vn_spec_ops; 295*5812c3ccSTomohiro Kusumi addaliasu(vp, umajor(0), uminor(0)); /* XXX CUSE */ 296*5812c3ccSTomohiro Kusumi break; 297*5812c3ccSTomohiro Kusumi case VLNK: 298*5812c3ccSTomohiro Kusumi break; 299*5812c3ccSTomohiro Kusumi case VSOCK: 300*5812c3ccSTomohiro Kusumi break; 301*5812c3ccSTomohiro Kusumi case VFIFO: 302*5812c3ccSTomohiro Kusumi KKASSERT(0); 303*5812c3ccSTomohiro Kusumi case VDATABASE: 304*5812c3ccSTomohiro Kusumi break; 305*5812c3ccSTomohiro Kusumi default: 306*5812c3ccSTomohiro Kusumi KKASSERT(0); 307*5812c3ccSTomohiro Kusumi } 308*5812c3ccSTomohiro Kusumi 309*5812c3ccSTomohiro Kusumi KKASSERT(vn_islocked(vp) == LK_EXCLUSIVE); 310*5812c3ccSTomohiro Kusumi KASSERT(!fnp->vp, ("lost race")); 311*5812c3ccSTomohiro Kusumi fnp->vp = vp; 312*5812c3ccSTomohiro Kusumi *vpp = vp; 313*5812c3ccSTomohiro Kusumi 314*5812c3ccSTomohiro Kusumi return 0; 315*5812c3ccSTomohiro Kusumi } 316*5812c3ccSTomohiro Kusumi 317*5812c3ccSTomohiro Kusumi int 318*5812c3ccSTomohiro Kusumi fuse_node_truncate(struct fuse_node *fnp, size_t oldsize, size_t newsize) 319*5812c3ccSTomohiro Kusumi { 320*5812c3ccSTomohiro Kusumi struct vnode *vp = fnp->vp; 321*5812c3ccSTomohiro Kusumi int error; 322*5812c3ccSTomohiro Kusumi 323*5812c3ccSTomohiro Kusumi fuse_dbg("ino=%ju update size %ju -> %ju\n", 324*5812c3ccSTomohiro Kusumi fnp->ino, oldsize, newsize); 325*5812c3ccSTomohiro Kusumi 326*5812c3ccSTomohiro Kusumi fnp->attr.va_size = fnp->size = newsize; 327*5812c3ccSTomohiro Kusumi 328*5812c3ccSTomohiro Kusumi if (newsize < oldsize) 329*5812c3ccSTomohiro Kusumi error = nvtruncbuf(vp, newsize, FUSE_BLKSIZE, -1, 0); 330*5812c3ccSTomohiro Kusumi else 331*5812c3ccSTomohiro Kusumi error = nvextendbuf(vp, oldsize, newsize, FUSE_BLKSIZE, 332*5812c3ccSTomohiro Kusumi FUSE_BLKSIZE, -1, -1, 0); 333*5812c3ccSTomohiro Kusumi return error; 334*5812c3ccSTomohiro Kusumi } 335*5812c3ccSTomohiro Kusumi 336*5812c3ccSTomohiro Kusumi void 337*5812c3ccSTomohiro Kusumi fuse_node_init(void) 338*5812c3ccSTomohiro Kusumi { 339*5812c3ccSTomohiro Kusumi fuse_node_objcache = objcache_create("fuse_node", 0, 0, 340*5812c3ccSTomohiro Kusumi NULL, NULL, NULL, 341*5812c3ccSTomohiro Kusumi objcache_malloc_alloc_zero, objcache_malloc_free, &fuse_node_args); 342*5812c3ccSTomohiro Kusumi 343*5812c3ccSTomohiro Kusumi fuse_dent_objcache = objcache_create("fuse_dent", 0, 0, 344*5812c3ccSTomohiro Kusumi NULL, NULL, NULL, 345*5812c3ccSTomohiro Kusumi objcache_malloc_alloc_zero, objcache_malloc_free, &fuse_dent_args); 346*5812c3ccSTomohiro Kusumi } 347*5812c3ccSTomohiro Kusumi 348*5812c3ccSTomohiro Kusumi void 349*5812c3ccSTomohiro Kusumi fuse_node_cleanup(void) 350*5812c3ccSTomohiro Kusumi { 351*5812c3ccSTomohiro Kusumi objcache_destroy(fuse_node_objcache); 352*5812c3ccSTomohiro Kusumi objcache_destroy(fuse_dent_objcache); 353*5812c3ccSTomohiro Kusumi } 354