xref: /dflybsd-src/sys/vfs/fuse/fuse_node.c (revision 5812c3cc7f8e910251a2cf4e78242f0b11a5fb4d)
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