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