xref: /dragonfly/sys/vfs/fuse/fuse_vnops.c (revision 3d33658b)
1 /*-
2  * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org>
3  * Copyright (c) 2019 The DragonFly Project
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include "fuse.h"
29 
30 #include <sys/fcntl.h>
31 #include <sys/dirent.h>
32 #include <sys/namei.h>
33 #include <sys/uio.h>
34 #include <sys/mountctl.h>
35 #include <vm/vm_pager.h>
36 #include <vm/vnode_pager.h>
37 
38 static int
39 fuse_set_attr(struct fuse_node *fnp, struct fuse_attr *fat)
40 {
41 	struct vattr *vap = &fnp->attr;
42 	int error = 0;
43 
44 	vattr_null(vap);
45 
46 	vap->va_type = IFTOVT(fat->mode);
47 	vap->va_size = fat->size;
48 	vap->va_bytes = fat->blocks * S_BLKSIZE;
49 	vap->va_mode = fat->mode & ~S_IFMT;
50 	if (!fat->nlink) /* XXX .fuse_hidden* has 0 link */
51 		vap->va_nlink = 1;
52 	else
53 		vap->va_nlink = fat->nlink;
54 	vap->va_uid = fat->uid;
55 	vap->va_gid = fat->gid;
56 	vap->va_fsid = fnp->fmp->mp->mnt_stat.f_fsid.val[0];
57 	vap->va_fileid = fat->ino;
58 	vap->va_blocksize = FUSE_BLKSIZE;
59 	vap->va_rmajor = VNOVAL;
60 	vap->va_rminor = VNOVAL;
61 	vap->va_atime.tv_sec = fat->atime;
62 	vap->va_atime.tv_nsec = fat->atimensec;
63 	vap->va_mtime.tv_sec = fat->mtime;
64 	vap->va_mtime.tv_nsec = fat->mtimensec;
65 	vap->va_ctime.tv_sec = fat->ctime;
66 	vap->va_ctime.tv_nsec = fat->ctimensec;
67 	vap->va_flags = 0;
68 	vap->va_gen = VNOVAL;
69 	vap->va_vaflags = 0;
70 
71 	KKASSERT(vap->va_type == fnp->type);
72 
73 	if (fnp->nlink != vap->va_nlink) {
74 		fuse_dbg("ino=%ju update nlink %d -> %ju\n",
75 		    fnp->ino, fnp->nlink, vap->va_nlink);
76 		fnp->nlink = vap->va_nlink;
77 	}
78 
79 	if (fnp->vp->v_object && fnp->size != vap->va_size)
80 		error = fuse_node_truncate(fnp, fnp->size, vap->va_size);
81 
82 	return error;
83 }
84 
85 static int
86 fuse_vop_access(struct vop_access_args *ap)
87 {
88 	struct vnode *vp = ap->a_vp;
89 	mode_t mode = ap->a_mode;
90 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
91 	struct fuse_ipc *fip;
92 	struct fuse_access_in *fai;
93 	uint32_t mask;
94 	int error;
95 
96 	if (fuse_test_dead(fmp))
97 		return 0;
98 
99 	if (fuse_test_nosys(fmp, FUSE_ACCESS))
100 		return 0;
101 
102 	switch (vp->v_type) {
103 	case VDIR:
104 	case VLNK:
105 	case VREG:
106 		if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
107 			return EROFS;
108 		break;
109 	case VBLK:
110 	case VCHR:
111 	case VSOCK:
112 	case VFIFO:
113 		break;
114 	default:
115 		return EINVAL;
116 	}
117 
118 	mask = F_OK;
119 	if (mode & VEXEC)
120 		mask |= X_OK;
121 	if (mode & VWRITE)
122 		mask |= W_OK;
123 	if (mode & VREAD)
124 		mask |= R_OK;
125 
126 	fip = fuse_ipc_get(fmp, sizeof(*fai));
127 	fai = fuse_ipc_fill(fip, FUSE_ACCESS, VTOI(vp)->ino, ap->a_cred);
128 	fai->mask = mask;
129 
130 	error = fuse_ipc_tx(fip);
131 	if (error) {
132 		if (error == ENOSYS)
133 			error = 0;
134 		if (error == ENOTCONN && (vp->v_flag & VROOT))
135 			error = 0;
136 		return error;
137 	}
138 
139 	fuse_ipc_put(fip);
140 
141 	return 0;
142 }
143 
144 static int
145 fuse_vop_open(struct vop_open_args *ap)
146 {
147 	struct vnode *vp = ap->a_vp;
148 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
149 	struct fuse_node *fnp = VTOI(vp);
150 	struct fuse_ipc *fip;
151 	struct fuse_open_in *foi;
152 	struct fuse_open_out *foo;
153 	int error, op;
154 
155 	if (fuse_test_dead(fmp))
156 		return ENOTCONN;
157 
158 	if (fuse_test_nosys(fmp, FUSE_OPEN))
159 		return EOPNOTSUPP;
160 
161 	if (vp->v_type == VDIR)
162 		op = FUSE_OPENDIR;
163 	else
164 		op = FUSE_OPEN;
165 
166 	fip = fuse_ipc_get(fmp, sizeof(*foi));
167 	foi = fuse_ipc_fill(fip, op, fnp->ino, ap->a_cred);
168 	foi->flags = OFLAGS(ap->a_mode);
169 	fuse_dbg("flags=%X\n", foi->flags);
170 	if (foi->flags & O_CREAT) {
171 		fuse_dbg("drop O_CREAT\n");
172 		foi->flags &= ~O_CREAT;
173 	}
174 
175 	error = fuse_ipc_tx(fip);
176 	if (error)
177 		return error;
178 
179 	/* XXX unused */
180 	foo = fuse_out_data(fip);
181 	if (foo->open_flags & FOPEN_DIRECT_IO)
182 		;
183 	else if (foo->open_flags & FOPEN_KEEP_CACHE)
184 		;
185 	else if (foo->open_flags & FOPEN_NONSEEKABLE)
186 		;
187 	else if (foo->open_flags & FOPEN_CACHE_DIR)
188 		;
189 
190 	fnp->closed = false;
191 	fuse_get_nfh(VTOI(vp), foo->fh);
192 	if (ap->a_fp) {
193 #if 1
194 		fuse_get_fh(ap->a_fp, foo->fh);
195 #else
196 		/* see #if0'd code in fuse_vop_setattr() */
197 		if (!ap->a_fp->private_data)
198 			fuse_get_fh(ap->a_fp, foo->fh);
199 		else {
200 			uint64_t *fhp = ap->a_fp->private_data;
201 			*fhp = foo->fh;
202 		}
203 #endif
204 	}
205 
206 	fuse_ipc_put(fip);
207 
208 	return vop_stdopen(ap);
209 }
210 
211 static int
212 fuse_vop_close(struct vop_close_args *ap)
213 {
214 	struct vnode *vp = ap->a_vp;
215 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
216 	struct fuse_node *fnp = VTOI(vp);
217 	struct fuse_ipc *fip;
218 	struct fuse_release_in *fri;
219 	int error, op;
220 
221 	if (fuse_test_dead(fmp))
222 		return 0;
223 
224 	if (fuse_test_nosys(fmp, FUSE_RELEASE) ||
225 	    fuse_test_nosys(fmp, FUSE_RELEASEDIR))
226 		return EOPNOTSUPP;
227 
228 	if (vp->v_type == VDIR)
229 		op = FUSE_RELEASEDIR;
230 	else
231 		op = FUSE_RELEASE;
232 
233 	fip = fuse_ipc_get(fmp, sizeof(*fri));
234 	fri = fuse_ipc_fill(fip, op, fnp->ino, NULL);
235 	/* unused */
236 	//fri->flags = ...;
237 	//fri->release_flags = ...;
238 	//fri->lock_owner = ...;
239 	fri->fh = fuse_nfh(VTOI(vp));
240 	if (ap->a_fp)
241 		fri->fh = fuse_fh(ap->a_fp);
242 
243 	error = fuse_ipc_tx(fip);
244 	if (error)
245 		return error;
246 
247 	fuse_ipc_put(fip);
248 
249 	fnp->closed = true;
250 	fuse_put_nfh(VTOI(vp));
251 	if (ap->a_fp)
252 		fuse_put_fh(ap->a_fp);
253 
254 	return vop_stdclose(ap);
255 }
256 
257 static int
258 fuse_vop_fsync(struct vop_fsync_args *ap)
259 {
260 	struct vnode *vp = ap->a_vp;
261 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
262 	struct fuse_ipc *fip;
263 	struct fuse_fsync_in *fsi;
264 	int error, op;
265 
266 	if (fuse_test_dead(fmp))
267 		return 0;
268 
269 	if (fuse_test_nosys(fmp, FUSE_FSYNC))
270 		return 0;
271 
272 	if (vp->v_type == VDIR)
273 		op = FUSE_FSYNCDIR;
274 	else
275 		op = FUSE_FSYNC;
276 
277 	fip = fuse_ipc_get(fmp, sizeof(*fsi));
278 	fsi = fuse_ipc_fill(fip, op, VTOI(vp)->ino, NULL);
279 	fsi->fh = fuse_nfh(VTOI(vp));
280 	if (ap->a_fp)
281 		fsi->fh = fuse_fh(ap->a_fp);
282 	fsi->fsync_flags = 1; /* datasync */
283 
284 	error = fuse_ipc_tx(fip);
285 	if (error)
286 		return error;
287 	fuse_ipc_put(fip);
288 
289 	vn_syncer_remove(vp, 1);
290 	vfsync(ap->a_vp, ap->a_waitfor, 1, NULL, NULL);
291 	vclrisdirty(vp);
292 
293 	return 0;
294 }
295 
296 static int
297 fuse_vop_getattr(struct vop_getattr_args *ap)
298 {
299 	struct vnode *vp = ap->a_vp;
300 	struct vattr *vap = ap->a_vap;
301 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
302 	struct fuse_node *fnp = VTOI(vp);
303 	struct fuse_ipc *fip;
304 	struct fuse_getattr_in *fgi;
305 	struct fuse_attr_out *fao;
306 	int error;
307 
308 	if (fuse_test_dead(fmp))
309 		return 0;
310 
311 	if (fuse_test_nosys(fmp, FUSE_GETATTR))
312 		return 0;
313 
314 	fip = fuse_ipc_get(fmp, sizeof(*fgi));
315 	fgi = fuse_ipc_fill(fip, FUSE_GETATTR, fnp->ino, NULL);
316 #if 0
317 	/* this may be called before open when fh is 0 */
318 	fgi->getattr_flags |= FUSE_GETATTR_FH;
319 	fgi->fh = fuse_nfh(fnp);
320 	if (ap->a_fp)
321 		fgi->fh = fuse_fh(ap->a_fp);
322 #endif
323 	error = fuse_ipc_tx(fip);
324 	if (error) {
325 		if (error == ENOSYS)
326 			error = 0;
327 		if (error == ENOTCONN && (vp->v_flag & VROOT)) {
328 			memset(vap, 0, sizeof(*vap));
329 			vap->va_type = vp->v_type;
330 			error = 0;
331 		}
332 		return error;
333 	}
334 
335 	fao = fuse_out_data(fip);
336 	mtx_lock(&fnp->node_lock);
337 	fuse_set_attr(fnp, &fao->attr);
338 	memcpy(vap, &fnp->attr, sizeof(*vap));
339 	/* unused */
340 	//fao->attr_valid;
341 	//fao->attr_valid_nsec;
342 	mtx_unlock(&fnp->node_lock);
343 
344 	fuse_ipc_put(fip);
345 
346 	if (vap->va_type != vp->v_type)
347 		return EINVAL;
348 
349 	return 0;
350 }
351 
352 static int
353 fuse_vop_setattr(struct vop_setattr_args *ap)
354 {
355 	struct vnode *vp = ap->a_vp;
356 	struct vattr *vap = ap->a_vap;
357 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
358 	struct fuse_node *fnp = VTOI(vp);
359 	struct fuse_ipc *fip;
360 	struct fuse_setattr_in *fsi, arg;
361 	struct fuse_attr_out *fao;
362 	int kflags = 0;
363 	int error = 0;
364 
365 	if (fuse_test_dead(fmp))
366 		return 0;
367 
368 	if (fuse_test_nosys(fmp, FUSE_SETATTR))
369 		return 0;
370 
371 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
372 		return EROFS;
373 
374 	memset(&arg, 0, sizeof(arg));
375 	mtx_lock(&fnp->node_lock);
376 
377 	if (!error && (vap->va_flags != VNOVAL)) {
378 		mtx_unlock(&fnp->node_lock);
379 		kflags |= NOTE_ATTRIB;
380 		return EOPNOTSUPP; /* XXX */
381 	}
382 
383 	if (!error && (vap->va_size != VNOVAL)) {
384 		if (vp->v_type == VDIR) {
385 			mtx_unlock(&fnp->node_lock);
386 			return EISDIR;
387 		}
388 		if (vp->v_type == VREG &&
389 		    (vp->v_mount->mnt_flag & MNT_RDONLY)) {
390 			mtx_unlock(&fnp->node_lock);
391 			return EROFS;
392 		}
393 		arg.size = vap->va_size;
394 		arg.valid |= FATTR_SIZE;
395 		if (vap->va_size > fnp->size)
396 			kflags |= NOTE_WRITE | NOTE_EXTEND;
397 		else
398 			kflags |= NOTE_WRITE;
399 	}
400 
401 	if (!error && (vap->va_uid != (uid_t)VNOVAL ||
402 	    vap->va_gid != (gid_t)VNOVAL)) {
403 		mode_t mode;
404 		error = vop_helper_chown(vp, vap->va_uid, vap->va_gid,
405 		    ap->a_cred, &arg.uid, &arg.gid, &mode);
406 		arg.valid |= FATTR_UID;
407 		arg.valid |= FATTR_GID;
408 		kflags |= NOTE_ATTRIB;
409 	}
410 
411 	if (!error && (vap->va_mode != (mode_t)VNOVAL)) {
412 		error = vop_helper_chmod(vp, vap->va_mode, ap->a_cred,
413 		    vap->va_uid, vap->va_gid, (mode_t*)&arg.mode);
414 		arg.valid |= FATTR_MODE;
415 		kflags |= NOTE_ATTRIB;
416 	}
417 
418 	if (!error && (vap->va_atime.tv_sec != VNOVAL &&
419 	    vap->va_atime.tv_nsec != VNOVAL)) {
420 		arg.atime = vap->va_atime.tv_sec;
421 		arg.atimensec = vap->va_atime.tv_nsec;
422 		arg.valid |= FATTR_ATIME;
423 		kflags |= NOTE_ATTRIB;
424 	}
425 
426 	if (!error && (vap->va_mtime.tv_sec != VNOVAL &&
427 	    vap->va_mtime.tv_nsec != VNOVAL)) {
428 		arg.mtime = vap->va_mtime.tv_sec;
429 		arg.mtimensec = vap->va_mtime.tv_nsec;
430 		arg.valid |= FATTR_MTIME;
431 		kflags |= NOTE_ATTRIB;
432 	}
433 
434 	if (!error && (vap->va_ctime.tv_sec != VNOVAL &&
435 	    vap->va_ctime.tv_nsec != VNOVAL)) {
436 		arg.ctime = vap->va_ctime.tv_sec;
437 		arg.ctimensec = vap->va_ctime.tv_nsec;
438 		arg.valid |= FATTR_CTIME;
439 		kflags |= NOTE_ATTRIB;
440 	}
441 
442 	mtx_unlock(&fnp->node_lock);
443 
444 	if (error)
445 		return error;
446 	if (!arg.valid)
447 		return 0;
448 
449 	fip = fuse_ipc_get(fmp, sizeof(*fsi));
450 	fsi = fuse_ipc_fill(fip, FUSE_SETATTR, fnp->ino, ap->a_cred);
451 	memcpy(fsi, &arg, sizeof(arg));
452 #if 0
453 	fsi->valid |= FATTR_FH;
454 	fsi->fh = fuse_nfh(fnp);
455 	if (ap->a_fp) {
456 		/* vn_open() may call VOP_SETATTR_FP() prior to VOP_OPEN(). */
457 		if (!ap->a_fp->private_data)
458 			fuse_get_fh(ap->a_fp, 0); /* XXX */
459 		fsi->fh = fuse_fh(ap->a_fp);
460 	}
461 #endif
462 	error = fuse_ipc_tx(fip);
463 	if (error)
464 		return error;
465 
466 	fao = fuse_out_data(fip);
467 	if (IFTOVT(fao->attr.mode) != vp->v_type) {
468 		fuse_ipc_put(fip);
469 		return EINVAL;
470 	}
471 	mtx_lock(&fnp->node_lock);
472 	fuse_set_attr(fnp, &fao->attr);
473 	/* unused */
474 	//fao->attr_valid;
475 	//fao->attr_valid_nsec;
476 	mtx_unlock(&fnp->node_lock);
477 
478 	fuse_ipc_put(fip);
479 	fuse_knote(vp, kflags);
480 
481 	return 0;
482 }
483 
484 static int
485 fuse_vop_nresolve(struct vop_nresolve_args *ap)
486 {
487 	struct vnode *dvp = ap->a_dvp;
488 	struct vnode *vp;
489 	struct namecache *ncp = ap->a_nch->ncp;
490 	struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
491 	struct fuse_node *dfnp = VTOI(dvp);
492 	struct fuse_ipc *fip;
493 	struct fuse_entry_out *feo;
494 	char *p, tmp[1024];
495 	uint32_t mode;
496 	enum vtype vtyp;
497 	int error;
498 
499 	if (fuse_test_dead(fmp))
500 		return ENOTCONN;
501 
502 	if (fuse_test_nosys(fmp, FUSE_LOOKUP))
503 		return EOPNOTSUPP;
504 
505 	fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1);
506 	p = fuse_ipc_fill(fip, FUSE_LOOKUP, dfnp->ino, ap->a_cred);
507 
508 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
509 	p[ncp->nc_nlen] = '\0';
510 	strlcpy(tmp, p, sizeof(tmp));
511 
512 	error = fuse_ipc_tx(fip);
513 	if (error == ENOENT) {
514 		cache_setvp(ap->a_nch, NULL);
515 		fuse_dbg("lookup \"%s\" ENOENT\n", tmp);
516 		return ENOENT;
517 	} else if (error) {
518 		fuse_dbg("lookup \"%s\" error=%d\n", tmp, error);
519 		return error;
520 	}
521 
522 	feo = fuse_out_data(fip);
523 	fuse_dbg("lookup \"%s\" ino=%ju/%ju\n", p, feo->nodeid, feo->attr.ino);
524 
525 	mode = feo->attr.mode;
526 	if (S_ISREG(mode))
527 		vtyp = VREG;
528 	else if (S_ISDIR(mode))
529 		vtyp = VDIR;
530 	else if (S_ISBLK(mode))
531 		vtyp = VBLK;
532 	else if (S_ISCHR(mode))
533 		vtyp = VCHR;
534 	else if (S_ISLNK(mode))
535 		vtyp = VLNK;
536 	else if (S_ISSOCK(mode))
537 		vtyp = VSOCK;
538 	else if (S_ISFIFO(mode))
539 		vtyp = VFIFO;
540 	else
541 		vtyp = VBAD;
542 
543 	error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), vtyp, &vp);
544 	if (error) {
545 		fuse_ipc_put(fip);
546 		return error;
547 	}
548 	KKASSERT(vp);
549 	KKASSERT(vn_islocked(vp));
550 
551 	vn_unlock(vp);
552 	cache_setvp(ap->a_nch, vp);
553 	vrele(vp);
554 
555 	/* unused */
556 	//feo->generation;
557 	//feo->entry_valid;
558 	//feo->attr_valid;
559 	//feo->entry_valid_nsec;
560 	//feo->attr_valid_nsec;
561 
562 	fuse_ipc_put(fip);
563 
564 	return 0;
565 }
566 
567 static int
568 fuse_vop_nlink(struct vop_nlink_args *ap)
569 {
570 	struct vnode *dvp = ap->a_dvp;
571 	struct vnode *vp = ap->a_vp;
572 	struct namecache *ncp = ap->a_nch->ncp;
573 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
574 	struct fuse_node *dfnp = VTOI(dvp);
575 	struct fuse_node *fnp = VTOI(vp);
576 	struct fuse_dent *fep;
577 	struct fuse_ipc *fip;
578 	struct fuse_link_in *fli;
579 	struct fuse_entry_out *feo;
580 	char *p;
581 	int error;
582 
583 	if (fuse_test_dead(fmp))
584 		return ENOTCONN;
585 
586 	if (fuse_test_nosys(fmp, FUSE_LINK))
587 		return EOPNOTSUPP;
588 
589 	if (vp->v_type == VDIR)
590 		return EPERM;
591 	if (dvp->v_mount != vp->v_mount)
592 		return EXDEV;
593 	if (fnp->nlink >= LINK_MAX)
594 		return EMLINK;
595 
596 	fip = fuse_ipc_get(fmp, sizeof(fli) + ncp->nc_nlen + 1);
597 	fli = fuse_ipc_fill(fip, FUSE_LINK, dfnp->ino, ap->a_cred);
598 	fli->oldnodeid = fnp->ino;
599 
600 	p = (char*)(fli + 1);
601 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
602 	p[ncp->nc_nlen] = '\0';
603 
604 	error = fuse_ipc_tx(fip);
605 	if (error)
606 		return error;
607 
608 	feo = fuse_out_data(fip);
609 	if (IFTOVT(feo->attr.mode) != vp->v_type) {
610 		fuse_ipc_put(fip);
611 		return EINVAL;
612 	}
613 
614 	mtx_lock(&dfnp->node_lock);
615 	mtx_lock(&fnp->node_lock);
616 	fuse_dent_new(fnp, p, strlen(p), &fep);
617 	fuse_dent_attach(dfnp, fep);
618 	fuse_set_attr(fnp, &feo->attr);
619 	mtx_unlock(&fnp->node_lock);
620 	mtx_unlock(&dfnp->node_lock);
621 
622 	cache_setunresolved(ap->a_nch);
623 	cache_setvp(ap->a_nch, vp);
624 	fuse_knote(dvp, NOTE_WRITE);
625 	fuse_knote(vp, NOTE_LINK);
626 
627 	/* unused */
628 	//feo->nodeid;
629 	//feo->generation;
630 	//feo->entry_valid;
631 	//feo->attr_valid;
632 	//feo->entry_valid_nsec;
633 	//feo->attr_valid_nsec;
634 
635 	fuse_ipc_put(fip);
636 
637 	return 0;
638 }
639 
640 static int
641 fuse_vop_ncreate(struct vop_ncreate_args *ap)
642 {
643 	struct vnode *dvp = ap->a_dvp;
644 	struct vnode *vp;
645 	struct namecache *ncp = ap->a_nch->ncp;
646 	struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
647 	struct fuse_node *dfnp = VTOI(dvp);
648 	struct fuse_node *fnp;
649 	struct fuse_ipc *fip;
650 	struct fuse_create_in *fci;
651 	struct fuse_entry_out *feo;
652 	struct fuse_open_out *foo;
653 	enum vtype vtyp;
654 	char *p;
655 	int error;
656 
657 	if (fuse_test_dead(fmp))
658 		return ENOTCONN;
659 
660 	if (fuse_test_nosys(fmp, FUSE_CREATE))
661 		return EOPNOTSUPP;
662 
663 	fip = fuse_ipc_get(fmp, sizeof(*fci) + ncp->nc_nlen + 1);
664 	fci = fuse_ipc_fill(fip, FUSE_CREATE, dfnp->ino, ap->a_cred);
665 	fci->flags = OFLAGS(ap->a_vap->va_fuseflags);
666 	fci->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
667 	/* unused */
668 	//fci->umask = ...;
669 	fuse_dbg("flags=%X mode=%X\n", fci->flags, fci->mode);
670 
671 	p = (char*)(fci + 1);
672 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
673 	p[ncp->nc_nlen] = '\0';
674 
675 	error = fuse_ipc_tx(fip);
676 	if (error)
677 		return error;
678 
679 	feo = fuse_out_data(fip);
680 	foo = (struct fuse_open_out*)(feo + 1);
681 	vtyp = IFTOVT(feo->attr.mode);
682 	if (vtyp != VREG && vtyp != VSOCK) {
683 		fuse_ipc_put(fip);
684 		return EINVAL;
685 	}
686 
687 	error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VREG, &vp);
688 	if (error) {
689 		fuse_ipc_put(fip);
690 		return error;
691 	}
692 	KKASSERT(vp);
693 	KKASSERT(vn_islocked(vp));
694 
695 	fnp = VTOI(vp);
696 	mtx_lock(&fnp->node_lock);
697 	fuse_set_attr(fnp, &feo->attr);
698 	mtx_unlock(&fnp->node_lock);
699 
700 	cache_setunresolved(ap->a_nch);
701 	cache_setvp(ap->a_nch, vp);
702 	*(ap->a_vpp) = vp;
703 	fuse_knote(dvp, NOTE_WRITE);
704 
705 	/* unused */
706 	//feo->generation;
707 	//feo->entry_valid;
708 	//feo->attr_valid;
709 	//feo->entry_valid_nsec;
710 	//feo->attr_valid_nsec;
711 	/* unused */
712 	//foo->open_flags;
713 
714 	fuse_ipc_put(fip);
715 
716 	return 0;
717 }
718 
719 static int
720 fuse_vop_nmknod(struct vop_nmknod_args *ap)
721 {
722 	struct vnode *dvp = ap->a_dvp;
723 	struct vnode *vp;
724 	struct namecache *ncp = ap->a_nch->ncp;
725 	struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
726 	struct fuse_node *dfnp = VTOI(dvp);
727 	struct fuse_node *fnp;
728 	struct fuse_ipc *fip;
729 	struct fuse_mknod_in *fmi;
730 	struct fuse_entry_out *feo;
731 	enum vtype vtyp;
732 	char *p;
733 	int error;
734 
735 	if (fuse_test_dead(fmp))
736 		return ENOTCONN;
737 
738 	if (fuse_test_nosys(fmp, FUSE_MKNOD))
739 		return EOPNOTSUPP;
740 
741 	fip = fuse_ipc_get(fmp, sizeof(*fmi) + ncp->nc_nlen + 1);
742 	fmi = fuse_ipc_fill(fip, FUSE_MKNOD, dfnp->ino, ap->a_cred);
743 	fmi->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
744 	/* unused */
745 	//fmi->rdev = ...;
746 	//fmi->umask = ...;
747 
748 	p = (char*)(fmi + 1);
749 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
750 	p[ncp->nc_nlen] = '\0';
751 
752 	error = fuse_ipc_tx(fip);
753 	if (error)
754 		return error;
755 
756 	feo = fuse_out_data(fip);
757 	vtyp = IFTOVT(feo->attr.mode);
758 	if (vtyp != VBLK && vtyp != VCHR && vtyp != VFIFO) {
759 		fuse_ipc_put(fip);
760 		return EINVAL;
761 	}
762 
763 	error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p),
764 	    ap->a_vap->va_type, &vp);
765 	if (error) {
766 		fuse_ipc_put(fip);
767 		return error;
768 	}
769 	KKASSERT(vp);
770 	KKASSERT(vn_islocked(vp));
771 
772 	fnp = VTOI(vp);
773 	mtx_lock(&fnp->node_lock);
774 	fuse_set_attr(fnp, &feo->attr);
775 	mtx_unlock(&fnp->node_lock);
776 
777 	cache_setunresolved(ap->a_nch);
778 	cache_setvp(ap->a_nch, vp);
779 	*(ap->a_vpp) = vp;
780 	fuse_knote(dvp, NOTE_WRITE);
781 
782 	/* unused */
783 	//feo->generation;
784 	//feo->entry_valid;
785 	//feo->attr_valid;
786 	//feo->entry_valid_nsec;
787 	//feo->attr_valid_nsec;
788 
789 	fuse_ipc_put(fip);
790 
791 	return 0;
792 }
793 
794 static int
795 fuse_vop_nremove(struct vop_nremove_args *ap)
796 {
797 	struct vnode *dvp = ap->a_dvp;
798 	struct vnode *vp;
799 	struct namecache *ncp = ap->a_nch->ncp;
800 	struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
801 	struct fuse_node *dfnp = VTOI(dvp);
802 	struct fuse_node *fnp;
803 	struct fuse_dent *fep;
804 	struct fuse_ipc *fip;
805 	char *p;
806 	int error;
807 
808 	if (fuse_test_dead(fmp))
809 		return ENOTCONN;
810 
811 	if (fuse_test_nosys(fmp, FUSE_UNLINK))
812 		return EOPNOTSUPP;
813 
814 	error = cache_vget(ap->a_nch, ap->a_cred, LK_SHARED, &vp);
815 	KKASSERT(vp->v_mount == dvp->v_mount);
816 	KKASSERT(!error); /* from tmpfs */
817 	vn_unlock(vp);
818 
819 	fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1);
820 	p = fuse_ipc_fill(fip, FUSE_UNLINK, dfnp->ino, ap->a_cred);
821 
822 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
823 	p[ncp->nc_nlen] = '\0';
824 
825 	error = fuse_ipc_tx(fip);
826 	if (error) {
827 		vrele(vp);
828 		return error;
829 	}
830 
831 	fnp = VTOI(vp);
832 	mtx_lock(&dfnp->node_lock);
833 	mtx_lock(&fnp->node_lock);
834 	error = fuse_dent_find(dfnp, p, strlen(p), &fep);
835 	if (error == ENOENT) {
836 		mtx_unlock(&fnp->node_lock);
837 		mtx_unlock(&dfnp->node_lock);
838 		fuse_ipc_put(fip);
839 		vrele(vp);
840 		return error;
841 	}
842 	fuse_dent_detach(dfnp, fep);
843 	fuse_dent_free(fep);
844 	mtx_unlock(&fnp->node_lock);
845 	mtx_unlock(&dfnp->node_lock);
846 
847 	cache_unlink(ap->a_nch);
848 	fuse_knote(dvp, NOTE_WRITE);
849 	fuse_knote(vp, NOTE_DELETE);
850 
851 	fuse_ipc_put(fip);
852 	vrele(vp);
853 
854 	return 0;
855 }
856 
857 static int
858 fuse_vop_nmkdir(struct vop_nmkdir_args *ap)
859 {
860 	struct vnode *dvp = ap->a_dvp;
861 	struct vnode *vp;
862 	struct namecache *ncp = ap->a_nch->ncp;
863 	struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
864 	struct fuse_node *dfnp = VTOI(dvp);
865 	struct fuse_node *fnp;
866 	struct fuse_ipc *fip;
867 	struct fuse_mkdir_in *fmi;
868 	struct fuse_entry_out *feo;
869 	char *p;
870 	int error;
871 
872 	if (fuse_test_dead(fmp))
873 		return ENOTCONN;
874 
875 	if (fuse_test_nosys(fmp, FUSE_MKDIR))
876 		return EOPNOTSUPP;
877 
878 	fip = fuse_ipc_get(fmp, sizeof(*fmi) + ncp->nc_nlen + 1);
879 	fmi = fuse_ipc_fill(fip, FUSE_MKDIR, dfnp->ino, ap->a_cred);
880 	fmi->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
881 
882 	p = (char*)(fmi + 1);
883 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
884 	p[ncp->nc_nlen] = '\0';
885 
886 	error = fuse_ipc_tx(fip);
887 	if (error)
888 		return error;
889 
890 	feo = fuse_out_data(fip);
891 	if (IFTOVT(feo->attr.mode) != VDIR) {
892 		fuse_ipc_put(fip);
893 		return EINVAL;
894 	}
895 
896 	error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VDIR, &vp);
897 	if (error) {
898 		fuse_ipc_put(fip);
899 		return error;
900 	}
901 	KKASSERT(vp);
902 	KKASSERT(vn_islocked(vp));
903 
904 	fnp = VTOI(vp);
905 	mtx_lock(&fnp->node_lock);
906 	fuse_set_attr(fnp, &feo->attr);
907 	mtx_unlock(&fnp->node_lock);
908 
909 	cache_setunresolved(ap->a_nch);
910 	cache_setvp(ap->a_nch, vp);
911 	*(ap->a_vpp) = vp;
912 	fuse_knote(dvp, NOTE_WRITE | NOTE_LINK);
913 
914 	/* unused */
915 	//feo->generation;
916 	//feo->entry_valid;
917 	//feo->attr_valid;
918 	//feo->entry_valid_nsec;
919 	//feo->attr_valid_nsec;
920 
921 	fuse_ipc_put(fip);
922 
923 	return 0;
924 }
925 
926 static int
927 fuse_vop_nrmdir(struct vop_nrmdir_args *ap)
928 {
929 	struct vnode *dvp = ap->a_dvp;
930 	struct vnode *vp;
931 	struct namecache *ncp = ap->a_nch->ncp;
932 	struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
933 	struct fuse_node *dfnp = VTOI(dvp);
934 	struct fuse_node *fnp;
935 	struct fuse_dent *fep;
936 	struct fuse_ipc *fip;
937 	char *p;
938 	int error;
939 
940 	if (fuse_test_dead(fmp))
941 		return ENOTCONN;
942 
943 	if (fuse_test_nosys(fmp, FUSE_RMDIR))
944 		return EOPNOTSUPP;
945 
946 	error = cache_vget(ap->a_nch, ap->a_cred, LK_SHARED, &vp);
947 	KKASSERT(vp->v_mount == dvp->v_mount);
948 	KKASSERT(!error); /* from tmpfs */
949 	vn_unlock(vp);
950 
951 	fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1);
952 	p = fuse_ipc_fill(fip, FUSE_RMDIR, dfnp->ino, ap->a_cred);
953 
954 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
955 	p[ncp->nc_nlen] = '\0';
956 
957 	error = fuse_ipc_tx(fip);
958 	if (error) {
959 		vrele(vp);
960 		return error;
961 	}
962 
963 	fnp = VTOI(vp);
964 	mtx_lock(&dfnp->node_lock);
965 	mtx_lock(&fnp->node_lock);
966 	error = fuse_dent_find(dfnp, p, strlen(p), &fep);
967 	if (error == ENOENT) {
968 		mtx_unlock(&fnp->node_lock);
969 		mtx_unlock(&dfnp->node_lock);
970 		fuse_ipc_put(fip);
971 		vrele(vp);
972 		return error;
973 	}
974 	fuse_dent_detach(dfnp, fep);
975 	fuse_dent_free(fep);
976 	mtx_unlock(&fnp->node_lock);
977 	mtx_unlock(&dfnp->node_lock);
978 
979 	cache_unlink(ap->a_nch);
980 	fuse_knote(dvp, NOTE_WRITE | NOTE_LINK);
981 
982 	fuse_ipc_put(fip);
983 	vrele(vp);
984 
985 	return 0;
986 }
987 
988 static int
989 fuse_vop_pathconf(struct vop_pathconf_args *ap)
990 {
991 	switch (ap->a_name) {
992 	case _PC_FILESIZEBITS:
993 		*ap->a_retval = 64;
994 		break;
995 	case _PC_NO_TRUNC:
996 		*ap->a_retval = 1;
997 		break;
998 	default:
999 		return vop_stdpathconf(ap);
1000 	}
1001 
1002 	return 0;
1003 }
1004 
1005 static int
1006 fuse_vop_readdir(struct vop_readdir_args *ap)
1007 {
1008 	struct vnode *vp = ap->a_vp;
1009 	struct uio *uio = ap->a_uio;
1010 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1011 	struct fuse_ipc *fip;
1012 	struct fuse_read_in *fri;
1013 	const char *buf;
1014 	size_t len;
1015 	off_t cur_offset = 0;
1016 	int error;
1017 
1018 	if (fuse_test_dead(fmp))
1019 		return ENOTCONN;
1020 
1021 	if (fuse_test_nosys(fmp, FUSE_READDIR))
1022 		return EOPNOTSUPP;
1023 
1024 	fip = fuse_ipc_get(fmp, sizeof(*fri));
1025 	fri = fuse_ipc_fill(fip, FUSE_READDIR, VTOI(vp)->ino, ap->a_cred);
1026 	fri->fh = fuse_nfh(VTOI(vp));
1027 	if (ap->a_fp)
1028 		fri->fh = fuse_fh(ap->a_fp);
1029 	fri->offset = 0;
1030 	/*
1031 	 * XXX This needs to be large enough to read all entries at once.
1032 	 * FUSE filesystems typically just opendir/readdir and return entries.
1033 	 */
1034 	fri->size = FUSE_BLKSIZE * 10;
1035 	/* unused */
1036 	//fri->read_flags = ...;
1037 	//fri->lock_owner = ...;
1038 	//fri->flags = ...;
1039 
1040 	error = fuse_ipc_tx(fip);
1041 	if (error)
1042 		return error;
1043 
1044 	buf = fuse_out_data(fip);
1045 	len = fuse_out_data_size(fip);
1046 
1047 	while (1) {
1048 		const struct fuse_dirent *fde;
1049 		size_t freclen;
1050 
1051 		fuse_dbg("uio_offset=%ju uio_resid=%ju\n",
1052 		    uio->uio_offset, uio->uio_resid);
1053 
1054 		if (len < FUSE_NAME_OFFSET) {
1055 			if (ap->a_eofflag)
1056 				*ap->a_eofflag = 1;
1057 			break;
1058 		}
1059 		if (uio->uio_resid < FUSE_NAME_OFFSET)
1060 			break;
1061 
1062 		fde = (const struct fuse_dirent*)buf;
1063 		if (!fde->namelen) {
1064 			error = EINVAL;
1065 			break;
1066 		}
1067 		freclen = FUSE_DIRENT_SIZE(fde);
1068 
1069 		/*
1070 		 * Also see
1071 		 * getdirentries(2) in sys/kern/vfs_syscalls.c
1072 		 * readdir(3) in lib/libc/gen/readdir.c
1073 		 */
1074 		if (cur_offset >= uio->uio_offset) {
1075 			error = 0;
1076 			if (vop_write_dirent(&error, uio, fde->ino, fde->type,
1077 			    fde->namelen, fde->name))
1078 				error = EINVAL;
1079 			if (error)
1080 				break;
1081 			fuse_dbg("ino=%ju type=%d name=%s len=%u\n",
1082 			    fde->ino, fde->type, fde->name, fde->namelen);
1083 		}
1084 
1085 		cur_offset += _DIRENT_RECLEN(fde->namelen);
1086 		buf += freclen;
1087 		len -= freclen;
1088 	}
1089 	fuse_ipc_put(fip);
1090 
1091 	return error;
1092 }
1093 
1094 static int
1095 fuse_vop_readlink(struct vop_readlink_args *ap)
1096 {
1097 	struct vnode *vp = ap->a_vp;
1098 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1099 	struct fuse_ipc *fip;
1100 	int error;
1101 
1102 	if (fuse_test_dead(fmp))
1103 		return ENOTCONN;
1104 
1105 	if (fuse_test_nosys(fmp, FUSE_READLINK))
1106 		return EOPNOTSUPP;
1107 
1108 	if (vp->v_type != VLNK)
1109 		return EINVAL;
1110 
1111 	fip = fuse_ipc_get(fmp, 0);
1112 	fuse_ipc_fill(fip, FUSE_READLINK, VTOI(vp)->ino, ap->a_cred);
1113 
1114 	error = fuse_ipc_tx(fip);
1115 	if (error)
1116 		return error;
1117 
1118 	error = uiomove(fuse_out_data(fip), fuse_out_data_size(fip), ap->a_uio);
1119 
1120 	fuse_ipc_put(fip);
1121 
1122 	return error;
1123 }
1124 
1125 static int
1126 fuse_vop_nrename(struct vop_nrename_args *ap)
1127 {
1128 	struct namecache *fncp = ap->a_fnch->ncp;
1129 	struct namecache *tncp = ap->a_tnch->ncp;
1130 	struct vnode *fdvp = ap->a_fdvp;
1131 	struct vnode *fvp = fncp->nc_vp;
1132 	struct vnode *tdvp = ap->a_tdvp;
1133 	struct vnode *tvp;
1134 	struct fuse_mount *fmp = VFSTOFUSE(fdvp->v_mount);
1135 	struct fuse_node *fdfnp = VTOI(fdvp);
1136 	struct fuse_node *ffnp = VTOI(fvp);
1137 	struct fuse_node *tdfnp = VTOI(tdvp);
1138 	struct fuse_node *tfnp;
1139 	struct fuse_dent *ffep;
1140 	struct fuse_dent *tfep;
1141 	struct fuse_ipc *fip;
1142 	struct fuse_rename_in *fri;
1143 	char *p, *newname, *oldname;
1144 	int error;
1145 
1146 	KKASSERT(fdvp->v_mount == fvp->v_mount);
1147 
1148 	if (fuse_test_dead(fmp))
1149 		return ENOTCONN;
1150 
1151 	if (fuse_test_nosys(fmp, FUSE_RENAME))
1152 		return EOPNOTSUPP;
1153 
1154 	error = cache_vget(ap->a_tnch, ap->a_cred, LK_SHARED, &tvp);
1155 	if (!error) {
1156 		tfnp = VTOI(tvp);
1157 		vn_unlock(tvp);
1158 	} else
1159 		tfnp = NULL;
1160 
1161 	/* Disallow cross-device renames.
1162 	 * Why isn't this done by the caller? */
1163 	if (fvp->v_mount != tdvp->v_mount ||
1164 	    (tvp && fvp->v_mount != tvp->v_mount)) {
1165 		error = EXDEV;
1166 		goto out;
1167 	}
1168 
1169 	if (fvp == tvp) {
1170 		error = 0;
1171 		goto out;
1172 	}
1173 	error = fuse_dent_find(fdfnp, fncp->nc_name, fncp->nc_nlen, &ffep);
1174 	if (error == ENOENT)
1175 		goto out;
1176 	KKASSERT(ffep->fnp == ffnp);
1177 
1178 	if (tvp) {
1179 		KKASSERT(tfnp);
1180 		if (ffnp->type == VDIR && tfnp->type == VDIR) {
1181 			if (!RB_EMPTY(&tfnp->dent_head)) {
1182 				error = ENOTEMPTY;
1183 				goto out;
1184 			}
1185 		} else if (ffnp->type == VDIR && tfnp->type != VDIR) {
1186 			error = ENOTDIR;
1187 			goto out;
1188 		} else if (ffnp->type != VDIR && tfnp->type == VDIR) {
1189 			error = EISDIR;
1190 			goto out;
1191 		} else
1192 			KKASSERT(ffnp->type != VDIR && tfnp->type != VDIR);
1193 	}
1194 
1195 	fip = fuse_ipc_get(fmp,
1196 	    sizeof(*fri) + fncp->nc_nlen + tncp->nc_nlen + 2);
1197 	/* There is also fuse_rename2_in with flags. */
1198 	fri = fuse_ipc_fill(fip, FUSE_RENAME, fdfnp->ino, ap->a_cred);
1199 	fri->newdir = tdfnp->ino;
1200 
1201 	p = (char*)(fri + 1);
1202 	memcpy(p, fncp->nc_name, fncp->nc_nlen);
1203 	p[fncp->nc_nlen] = '\0';
1204 	memcpy(p + fncp->nc_nlen + 1, tncp->nc_name, tncp->nc_nlen);
1205 	p[fncp->nc_nlen + 1 + tncp->nc_nlen] = '\0';
1206 
1207 	error = fuse_ipc_tx(fip);
1208 	if (error)
1209 		goto out;
1210 	fuse_ipc_put(fip);
1211 
1212 	if (fncp->nc_nlen != tncp->nc_nlen ||
1213 	    memcmp(fncp->nc_name, tncp->nc_name, fncp->nc_nlen)) {
1214 		newname = kmalloc(tncp->nc_nlen + 1, M_TEMP, M_WAITOK | M_ZERO);
1215 		KKASSERT(newname);
1216 		memcpy(newname, tncp->nc_name, tncp->nc_nlen);
1217 		newname[tncp->nc_nlen] = '\0';
1218 		fuse_dbg("newname=\"%s\"\n", newname);
1219 	} else
1220 		newname = NULL;
1221 
1222 	mtx_lock(&tdfnp->node_lock);
1223 	mtx_lock(&fdfnp->node_lock);
1224 	mtx_lock(&ffnp->node_lock);
1225 
1226 	fuse_dbg("detach from_dent=\"%s\"\n", ffep->name);
1227 	fuse_dent_detach(fdfnp, ffep);
1228 
1229 	if (newname) {
1230 		oldname = ffep->name;
1231 		ffep->name = newname;
1232 		newname = oldname;
1233 	}
1234 
1235 	if (tvp) {
1236 		mtx_lock(&tfnp->node_lock);
1237 		error = fuse_dent_find(tdfnp, tncp->nc_name, tncp->nc_nlen,
1238 		    &tfep);
1239 		KKASSERT(!error);
1240 		fuse_dbg("detach/free to_dent=\"%s\"\n", tfep->name);
1241 		fuse_dent_detach(tdfnp, tfep);
1242 		fuse_dent_free(tfep);
1243 		mtx_unlock(&tfnp->node_lock);
1244 		fuse_knote(tdvp, NOTE_DELETE);
1245 	}
1246 
1247 	fuse_dbg("attach from_dent=\"%s\"\n", ffep->name);
1248 	fuse_dent_attach(tdfnp, ffep);
1249 
1250 	mtx_unlock(&ffnp->node_lock);
1251 	mtx_unlock(&fdfnp->node_lock);
1252 	mtx_unlock(&tdfnp->node_lock);
1253 
1254 	if (newname)
1255 		kfree(newname, M_TEMP);
1256 
1257 	cache_rename(ap->a_fnch, ap->a_tnch);
1258 	fuse_knote(fdvp, NOTE_WRITE);
1259 	fuse_knote(tdvp, NOTE_WRITE);
1260 	fuse_knote(fvp, NOTE_RENAME);
1261 out:
1262 	if (tvp)
1263 		vrele(tvp);
1264 
1265 	return error;
1266 }
1267 
1268 static int
1269 fuse_vop_nsymlink(struct vop_nsymlink_args *ap)
1270 {
1271 	struct vnode *dvp = ap->a_dvp;
1272 	struct vnode *vp;
1273 	struct namecache *ncp = ap->a_nch->ncp;
1274 	struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
1275 	struct fuse_node *dfnp = VTOI(dvp);
1276 	struct fuse_node *fnp;
1277 	struct fuse_ipc *fip;
1278 	struct fuse_entry_out *feo;
1279 	char *p;
1280 	int error;
1281 
1282 	if (fuse_test_dead(fmp))
1283 		return ENOTCONN;
1284 
1285 	if (fuse_test_nosys(fmp, FUSE_SYMLINK))
1286 		return EOPNOTSUPP;
1287 
1288 	fip = fuse_ipc_get(fmp, strlen(ap->a_target) + 1 + ncp->nc_nlen + 1);
1289 	p = fuse_ipc_fill(fip, FUSE_SYMLINK, dfnp->ino, ap->a_cred);
1290 
1291 	memcpy(p, ncp->nc_name, ncp->nc_nlen);
1292 	p[ncp->nc_nlen] = '\0';
1293 	memcpy(p + ncp->nc_nlen + 1, ap->a_target, strlen(ap->a_target) + 1);
1294 
1295 	error = fuse_ipc_tx(fip);
1296 	if (error)
1297 		return error;
1298 
1299 	feo = fuse_out_data(fip);
1300 	if (IFTOVT(feo->attr.mode) != VLNK) {
1301 		fuse_ipc_put(fip);
1302 		return EINVAL;
1303 	}
1304 
1305 	error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VLNK, &vp);
1306 	if (error) {
1307 		fuse_ipc_put(fip);
1308 		return error;
1309 	}
1310 	KKASSERT(vp);
1311 	KKASSERT(vn_islocked(vp));
1312 
1313 	fnp = VTOI(vp);
1314 	mtx_lock(&fnp->node_lock);
1315 	fuse_set_attr(fnp, &feo->attr);
1316 	mtx_unlock(&fnp->node_lock);
1317 
1318 	cache_setunresolved(ap->a_nch);
1319 	cache_setvp(ap->a_nch, vp);
1320 	*(ap->a_vpp) = vp;
1321 	fuse_knote(vp, NOTE_WRITE);
1322 
1323 	/* unused */
1324 	//feo->generation;
1325 	//feo->entry_valid;
1326 	//feo->attr_valid;
1327 	//feo->entry_valid_nsec;
1328 	//feo->attr_valid_nsec;
1329 
1330 	fuse_ipc_put(fip);
1331 
1332 	return 0;
1333 }
1334 
1335 static int
1336 fuse_vop_read(struct vop_read_args *ap)
1337 {
1338 	struct vnode *vp = ap->a_vp;
1339 	struct uio *uio = ap->a_uio;
1340 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1341 
1342 	fuse_dbg("ino=%ju ioflag=%x\n", VTOI(vp)->ino, ap->a_ioflag);
1343 
1344 	if (fuse_test_dead(fmp))
1345 		return ENOTCONN;
1346 
1347 	if (fuse_test_nosys(fmp, FUSE_READ))
1348 		return EOPNOTSUPP;
1349 
1350 	if (!uio->uio_resid)
1351 		return 0;
1352 
1353 	return fuse_read(ap);
1354 }
1355 
1356 static int
1357 fuse_vop_write(struct vop_write_args *ap)
1358 {
1359 	struct vnode *vp = ap->a_vp;
1360 	struct uio *uio = ap->a_uio;
1361 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1362 
1363 	fuse_dbg("ino=%ju ioflag=%x\n", VTOI(vp)->ino, ap->a_ioflag);
1364 	return EOPNOTSUPP; /* XXX disabled */
1365 
1366 	if (fuse_test_dead(fmp))
1367 		return ENOTCONN;
1368 
1369 	if (fuse_test_nosys(fmp, FUSE_WRITE))
1370 		return EOPNOTSUPP;
1371 
1372 	if (!uio->uio_resid)
1373 		return 0;
1374 
1375 	if (ap->a_ioflag & IO_DIRECT)
1376 		return fuse_dio_write(ap);
1377 	else
1378 		return fuse_write(ap);
1379 }
1380 
1381 static int
1382 fuse_vop_strategy(struct vop_strategy_args *ap)
1383 {
1384 	struct bio *bio = ap->a_bio;
1385 	struct buf *bp = bio->bio_buf;
1386 
1387 	fuse_dbg("ino=%ju b_cmd=%d\n", VTOI(ap->a_vp)->ino, bp->b_cmd);
1388 
1389 	bp->b_resid = 0;
1390 	bp->b_error = 0;
1391 	biodone(bio);
1392 
1393 	return 0;
1394 }
1395 
1396 static int
1397 fuse_bmap(struct vop_bmap_args *ap)
1398 {
1399 	fuse_dbg("ino=%ju a_cmd=%d a_loffset=%ju\n",
1400 	    VTOI(ap->a_vp)->ino, ap->a_cmd, ap->a_loffset);
1401 
1402 	return EOPNOTSUPP;
1403 }
1404 
1405 static int
1406 fuse_vop_print(struct vop_print_args *ap)
1407 {
1408 	struct fuse_node *fnp = VTOI(ap->a_vp);
1409 
1410 	fuse_print("tag VT_FUSE, node %p, ino %ju, parent ino %ju\n",
1411 	    fnp, VTOI(ap->a_vp)->ino, VTOI(fnp->pfnp->vp)->ino);
1412 
1413 	return 0;
1414 }
1415 
1416 static int
1417 fuse_vop_inactive(struct vop_inactive_args *ap)
1418 {
1419 	struct vnode *vp = ap->a_vp;
1420 	struct mount *mp = vp->v_mount;
1421 	struct fuse_node *fnp = VTOI(vp);
1422 
1423 	lwkt_gettoken(&mp->mnt_token);
1424 	if (!fnp) {
1425 		vrecycle(ap->a_vp);
1426 		lwkt_reltoken(&mp->mnt_token);
1427 		return 0;
1428 	}
1429 
1430 	fuse_dbg("ino=%ju nlink=%d\n", fnp->ino, fnp->nlink);
1431 	vinvalbuf(vp, V_SAVE, 0, 0);
1432 	lwkt_reltoken(&mp->mnt_token);
1433 
1434 	return 0;
1435 }
1436 
1437 static int
1438 fuse_vop_reclaim(struct vop_reclaim_args *ap)
1439 {
1440 	struct vnode *vp = ap->a_vp;
1441 	struct mount *mp = vp->v_mount;
1442 	struct fuse_node *fnp = VTOI(vp);
1443 
1444 	lwkt_gettoken(&mp->mnt_token);
1445 	if (fnp) {
1446 		fuse_dbg("ino=%ju\n", fnp->ino);
1447 		fuse_node_free(fnp);
1448 		vclrisdirty(vp);
1449 	}
1450 	lwkt_reltoken(&mp->mnt_token);
1451 
1452 	return 0;
1453 }
1454 
1455 static int
1456 fuse_vop_mountctl(struct vop_mountctl_args *ap)
1457 {
1458 	struct mount *mp;
1459 	int res = 0;
1460 
1461 	mp = ap->a_head.a_ops->head.vv_mount;
1462 	lwkt_gettoken(&mp->mnt_token);
1463 
1464 	switch (ap->a_op) {
1465 	//case MOUNTCTL_MOUNTFLAGS:
1466 	//	...
1467 	//	break;
1468 	default:
1469 		res = vop_stdmountctl(ap);
1470 		break;
1471 	}
1472 
1473 	lwkt_reltoken(&mp->mnt_token);
1474 	return res;
1475 }
1476 
1477 static void filt_fusedetach(struct knote*);
1478 static int filt_fuseread(struct knote*, long);
1479 static int filt_fusewrite(struct knote*, long);
1480 static int filt_fusevnode(struct knote*, long);
1481 
1482 static struct filterops fuseread_filtops =
1483 	{ FILTEROP_ISFD | FILTEROP_MPSAFE,
1484 	  NULL, filt_fusedetach, filt_fuseread };
1485 static struct filterops fusewrite_filtops =
1486 	{ FILTEROP_ISFD | FILTEROP_MPSAFE,
1487 	  NULL, filt_fusedetach, filt_fusewrite };
1488 static struct filterops fusevnode_filtops =
1489 	{ FILTEROP_ISFD | FILTEROP_MPSAFE,
1490 	  NULL, filt_fusedetach, filt_fusevnode };
1491 
1492 static int
1493 fuse_kqfilter(struct vop_kqfilter_args *ap)
1494 {
1495 	struct vnode *vp = ap->a_vp;
1496 	struct knote *kn = ap->a_kn;
1497 
1498 	switch (kn->kn_filter) {
1499 	case EVFILT_READ:
1500 		kn->kn_fop = &fuseread_filtops;
1501 		break;
1502 	case EVFILT_WRITE:
1503 		kn->kn_fop = &fusewrite_filtops;
1504 		break;
1505 	case EVFILT_VNODE:
1506 		kn->kn_fop = &fusevnode_filtops;
1507 		break;
1508 	default:
1509 		return EOPNOTSUPP;
1510 	}
1511 
1512 	kn->kn_hook = (caddr_t)vp;
1513 	knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1514 
1515 	return 0;
1516 }
1517 
1518 static void
1519 filt_fusedetach(struct knote *kn)
1520 {
1521 	struct vnode *vp = (void*)kn->kn_hook;
1522 
1523 	knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1524 }
1525 
1526 static int
1527 filt_fuseread(struct knote *kn, long hint)
1528 {
1529 	struct vnode *vp = (void*)kn->kn_hook;
1530 	struct fuse_node *fnp = VTOI(vp);
1531 	off_t off;
1532 
1533 	if (hint == NOTE_REVOKE) {
1534 		kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1535 		return 1;
1536 	}
1537 
1538 	/*
1539 	 * Interlock against MP races when performing this function.
1540 	 */
1541 	mtx_lock(&fnp->node_lock);
1542 	off = fnp->size - kn->kn_fp->f_offset;
1543 	kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1544 	if (kn->kn_sfflags & NOTE_OLDAPI) {
1545 		mtx_unlock(&fnp->node_lock);
1546 		return 1;
1547 	}
1548 	if (!kn->kn_data)
1549 		kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1550 	mtx_unlock(&fnp->node_lock);
1551 
1552 	return kn->kn_data != 0;
1553 }
1554 
1555 static int
1556 filt_fusewrite(struct knote *kn, long hint)
1557 {
1558 	if (hint == NOTE_REVOKE)
1559 		kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1560 	kn->kn_data = 0;
1561 
1562 	return 1;
1563 }
1564 
1565 static int
1566 filt_fusevnode(struct knote *kn, long hint)
1567 {
1568 	if (kn->kn_sfflags & hint)
1569 		kn->kn_fflags |= hint;
1570 	if (hint == NOTE_REVOKE) {
1571 		kn->kn_flags |= (EV_EOF | EV_NODATA);
1572 		return 1;
1573 	}
1574 
1575 	return kn->kn_fflags != 0;
1576 }
1577 
1578 static int
1579 fuse_vop_getpages(struct vop_getpages_args *ap)
1580 {
1581 	if (!ap->a_vp->v_mount)
1582 		return VM_PAGER_BAD;
1583 
1584 	return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
1585 	    ap->a_reqpage, ap->a_seqaccess);
1586 }
1587 
1588 static int
1589 fuse_vop_putpages(struct vop_putpages_args *ap)
1590 {
1591 	if (!ap->a_vp->v_mount)
1592 		return VM_PAGER_BAD;
1593 
1594 	return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
1595 	    ap->a_sync, ap->a_rtvals);
1596 }
1597 
1598 struct vop_ops fuse_vnode_vops = {
1599 	.vop_default =		vop_defaultop,
1600 	.vop_access =		fuse_vop_access,
1601 	.vop_open =		fuse_vop_open,
1602 	.vop_close =		fuse_vop_close,
1603 	.vop_fsync =		fuse_vop_fsync,
1604 	.vop_getattr =		fuse_vop_getattr,
1605 	.vop_setattr =		fuse_vop_setattr,
1606 	.vop_nresolve =		fuse_vop_nresolve,
1607 	//.vop_nlookupdotdot =	fuse_nlookupdotdot,
1608 	.vop_nlink =		fuse_vop_nlink,
1609 	.vop_ncreate =		fuse_vop_ncreate,
1610 	.vop_nmknod =		fuse_vop_nmknod,
1611 	.vop_nremove =		fuse_vop_nremove,
1612 	.vop_nmkdir =		fuse_vop_nmkdir,
1613 	.vop_nrmdir =		fuse_vop_nrmdir,
1614 	.vop_pathconf =		fuse_vop_pathconf,
1615 	.vop_readdir =		fuse_vop_readdir,
1616 	.vop_readlink =		fuse_vop_readlink,
1617 	.vop_nrename =		fuse_vop_nrename,
1618 	.vop_nsymlink =		fuse_vop_nsymlink,
1619 	.vop_read =		fuse_vop_read,
1620 	.vop_write =		fuse_vop_write,
1621 	.vop_strategy =		fuse_vop_strategy,
1622 	.vop_bmap =		fuse_bmap,
1623 	//.vop_advlock =	fuse_advlock,
1624 	.vop_print =		fuse_vop_print,
1625 	.vop_inactive =		fuse_vop_inactive,
1626 	.vop_reclaim =		fuse_vop_reclaim,
1627 	.vop_mountctl =		fuse_vop_mountctl,
1628 	.vop_kqfilter =		fuse_kqfilter,
1629 	.vop_getpages =		fuse_vop_getpages,
1630 	.vop_putpages =		fuse_vop_putpages,
1631 };
1632 
1633 struct vop_ops fuse_spec_vops = {
1634 	.vop_default =		vop_defaultop,
1635 	.vop_access =		fuse_vop_access,
1636 	.vop_close =		fuse_vop_close,
1637 	.vop_fsync =		fuse_vop_fsync,
1638 	.vop_getattr =		fuse_vop_getattr,
1639 	.vop_setattr =		fuse_vop_setattr,
1640 	.vop_read =		vop_stdnoread,
1641 	.vop_write =		vop_stdnowrite,
1642 	//.vop_markatime =	fuse_vop_markatime,
1643 	.vop_print =		fuse_vop_print,
1644 	.vop_inactive =		fuse_vop_inactive,
1645 	.vop_reclaim =		fuse_vop_reclaim,
1646 };
1647