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