xref: /freebsd/sys/fs/fuse/fuse_vnops.c (revision e9e8876a4d6afc1ad5315faaa191b25121a813d7)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2007-2009 Google Inc. and Amit Singh
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  *   copyright notice, this list of conditions and the following disclaimer
15  *   in the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of Google Inc. nor the names of its
18  *   contributors may be used to endorse or promote products derived from
19  *   this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Copyright (C) 2005 Csaba Henk.
34  * All rights reserved.
35  *
36  * Copyright (c) 2019 The FreeBSD Foundation
37  *
38  * Portions of this software were developed by BFF Storage Systems, LLC under
39  * sponsorship from the FreeBSD Foundation.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  *
50  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60  * SUCH DAMAGE.
61  */
62 
63 #include <sys/cdefs.h>
64 __FBSDID("$FreeBSD$");
65 
66 #include <sys/param.h>
67 #include <sys/module.h>
68 #include <sys/systm.h>
69 #include <sys/errno.h>
70 #include <sys/kernel.h>
71 #include <sys/conf.h>
72 #include <sys/filio.h>
73 #include <sys/uio.h>
74 #include <sys/malloc.h>
75 #include <sys/queue.h>
76 #include <sys/limits.h>
77 #include <sys/lock.h>
78 #include <sys/rwlock.h>
79 #include <sys/sx.h>
80 #include <sys/proc.h>
81 #include <sys/mount.h>
82 #include <sys/vnode.h>
83 #include <sys/namei.h>
84 #include <sys/extattr.h>
85 #include <sys/stat.h>
86 #include <sys/unistd.h>
87 #include <sys/filedesc.h>
88 #include <sys/file.h>
89 #include <sys/fcntl.h>
90 #include <sys/dirent.h>
91 #include <sys/bio.h>
92 #include <sys/buf.h>
93 #include <sys/sysctl.h>
94 #include <sys/vmmeter.h>
95 
96 #include <vm/vm.h>
97 #include <vm/vm_extern.h>
98 #include <vm/pmap.h>
99 #include <vm/vm_map.h>
100 #include <vm/vm_page.h>
101 #include <vm/vm_param.h>
102 #include <vm/vm_object.h>
103 #include <vm/vm_pager.h>
104 #include <vm/vnode_pager.h>
105 #include <vm/vm_object.h>
106 
107 #include "fuse.h"
108 #include "fuse_file.h"
109 #include "fuse_internal.h"
110 #include "fuse_ipc.h"
111 #include "fuse_node.h"
112 #include "fuse_io.h"
113 
114 #include <sys/priv.h>
115 
116 /* Maximum number of hardlinks to a single FUSE file */
117 #define FUSE_LINK_MAX                      UINT32_MAX
118 
119 SDT_PROVIDER_DECLARE(fusefs);
120 /*
121  * Fuse trace probe:
122  * arg0: verbosity.  Higher numbers give more verbose messages
123  * arg1: Textual message
124  */
125 SDT_PROBE_DEFINE2(fusefs, , vnops, trace, "int", "char*");
126 
127 /* vnode ops */
128 static vop_access_t fuse_vnop_access;
129 static vop_advlock_t fuse_vnop_advlock;
130 static vop_bmap_t fuse_vnop_bmap;
131 static vop_close_t fuse_fifo_close;
132 static vop_close_t fuse_vnop_close;
133 static vop_copy_file_range_t fuse_vnop_copy_file_range;
134 static vop_create_t fuse_vnop_create;
135 static vop_deleteextattr_t fuse_vnop_deleteextattr;
136 static vop_fdatasync_t fuse_vnop_fdatasync;
137 static vop_fsync_t fuse_vnop_fsync;
138 static vop_getattr_t fuse_vnop_getattr;
139 static vop_getextattr_t fuse_vnop_getextattr;
140 static vop_inactive_t fuse_vnop_inactive;
141 static vop_ioctl_t fuse_vnop_ioctl;
142 static vop_link_t fuse_vnop_link;
143 static vop_listextattr_t fuse_vnop_listextattr;
144 static vop_lookup_t fuse_vnop_lookup;
145 static vop_mkdir_t fuse_vnop_mkdir;
146 static vop_mknod_t fuse_vnop_mknod;
147 static vop_open_t fuse_vnop_open;
148 static vop_pathconf_t fuse_vnop_pathconf;
149 static vop_read_t fuse_vnop_read;
150 static vop_readdir_t fuse_vnop_readdir;
151 static vop_readlink_t fuse_vnop_readlink;
152 static vop_reclaim_t fuse_vnop_reclaim;
153 static vop_remove_t fuse_vnop_remove;
154 static vop_rename_t fuse_vnop_rename;
155 static vop_rmdir_t fuse_vnop_rmdir;
156 static vop_setattr_t fuse_vnop_setattr;
157 static vop_setextattr_t fuse_vnop_setextattr;
158 static vop_strategy_t fuse_vnop_strategy;
159 static vop_symlink_t fuse_vnop_symlink;
160 static vop_write_t fuse_vnop_write;
161 static vop_getpages_t fuse_vnop_getpages;
162 static vop_print_t fuse_vnop_print;
163 static vop_vptofh_t fuse_vnop_vptofh;
164 
165 struct vop_vector fuse_fifoops = {
166 	.vop_default =		&fifo_specops,
167 	.vop_access =		fuse_vnop_access,
168 	.vop_close =		fuse_fifo_close,
169 	.vop_fsync =		fuse_vnop_fsync,
170 	.vop_getattr =		fuse_vnop_getattr,
171 	.vop_inactive =		fuse_vnop_inactive,
172 	.vop_pathconf =		fuse_vnop_pathconf,
173 	.vop_print =		fuse_vnop_print,
174 	.vop_read =		VOP_PANIC,
175 	.vop_reclaim =		fuse_vnop_reclaim,
176 	.vop_setattr =		fuse_vnop_setattr,
177 	.vop_write =		VOP_PANIC,
178 	.vop_vptofh =		fuse_vnop_vptofh,
179 };
180 VFS_VOP_VECTOR_REGISTER(fuse_fifoops);
181 
182 struct vop_vector fuse_vnops = {
183 	.vop_allocate =	VOP_EINVAL,
184 	.vop_default = &default_vnodeops,
185 	.vop_access = fuse_vnop_access,
186 	.vop_advlock = fuse_vnop_advlock,
187 	.vop_bmap = fuse_vnop_bmap,
188 	.vop_close = fuse_vnop_close,
189 	.vop_copy_file_range = fuse_vnop_copy_file_range,
190 	.vop_create = fuse_vnop_create,
191 	.vop_deleteextattr = fuse_vnop_deleteextattr,
192 	.vop_fsync = fuse_vnop_fsync,
193 	.vop_fdatasync = fuse_vnop_fdatasync,
194 	.vop_getattr = fuse_vnop_getattr,
195 	.vop_getextattr = fuse_vnop_getextattr,
196 	.vop_inactive = fuse_vnop_inactive,
197 	.vop_ioctl = fuse_vnop_ioctl,
198 	.vop_link = fuse_vnop_link,
199 	.vop_listextattr = fuse_vnop_listextattr,
200 	.vop_lookup = fuse_vnop_lookup,
201 	.vop_mkdir = fuse_vnop_mkdir,
202 	.vop_mknod = fuse_vnop_mknod,
203 	.vop_open = fuse_vnop_open,
204 	.vop_pathconf = fuse_vnop_pathconf,
205 	/*
206 	 * TODO: implement vop_poll after upgrading to protocol 7.21.
207 	 * FUSE_POLL was added in protocol 7.11, but it's kind of broken until
208 	 * 7.21, which adds the ability for the client to choose which poll
209 	 * events it wants, and for a client to deregister a file handle
210 	 */
211 	.vop_read = fuse_vnop_read,
212 	.vop_readdir = fuse_vnop_readdir,
213 	.vop_readlink = fuse_vnop_readlink,
214 	.vop_reclaim = fuse_vnop_reclaim,
215 	.vop_remove = fuse_vnop_remove,
216 	.vop_rename = fuse_vnop_rename,
217 	.vop_rmdir = fuse_vnop_rmdir,
218 	.vop_setattr = fuse_vnop_setattr,
219 	.vop_setextattr = fuse_vnop_setextattr,
220 	.vop_strategy = fuse_vnop_strategy,
221 	.vop_symlink = fuse_vnop_symlink,
222 	.vop_write = fuse_vnop_write,
223 	.vop_getpages = fuse_vnop_getpages,
224 	.vop_print = fuse_vnop_print,
225 	.vop_vptofh = fuse_vnop_vptofh,
226 };
227 VFS_VOP_VECTOR_REGISTER(fuse_vnops);
228 
229 uma_zone_t fuse_pbuf_zone;
230 
231 /* Check permission for extattr operations, much like extattr_check_cred */
232 static int
233 fuse_extattr_check_cred(struct vnode *vp, int ns, struct ucred *cred,
234 	struct thread *td, accmode_t accmode)
235 {
236 	struct mount *mp = vnode_mount(vp);
237 	struct fuse_data *data = fuse_get_mpdata(mp);
238 	int default_permissions = data->dataflags & FSESS_DEFAULT_PERMISSIONS;
239 
240 	/*
241 	 * Kernel-invoked always succeeds.
242 	 */
243 	if (cred == NOCRED)
244 		return (0);
245 
246 	/*
247 	 * Do not allow privileged processes in jail to directly manipulate
248 	 * system attributes.
249 	 */
250 	switch (ns) {
251 	case EXTATTR_NAMESPACE_SYSTEM:
252 		if (default_permissions) {
253 			return (priv_check_cred(cred, PRIV_VFS_EXTATTR_SYSTEM));
254 		}
255 		return (0);
256 	case EXTATTR_NAMESPACE_USER:
257 		if (default_permissions) {
258 			return (fuse_internal_access(vp, accmode, td, cred));
259 		}
260 		return (0);
261 	default:
262 		return (EPERM);
263 	}
264 }
265 
266 /* Get a filehandle for a directory */
267 static int
268 fuse_filehandle_get_dir(struct vnode *vp, struct fuse_filehandle **fufhp,
269 	struct ucred *cred, pid_t pid)
270 {
271 	if (fuse_filehandle_get(vp, FREAD, fufhp, cred, pid) == 0)
272 		return 0;
273 	return fuse_filehandle_get(vp, FEXEC, fufhp, cred, pid);
274 }
275 
276 /* Send FUSE_FLUSH for this vnode */
277 static int
278 fuse_flush(struct vnode *vp, struct ucred *cred, pid_t pid, int fflag)
279 {
280 	struct fuse_flush_in *ffi;
281 	struct fuse_filehandle *fufh;
282 	struct fuse_dispatcher fdi;
283 	struct thread *td = curthread;
284 	struct mount *mp = vnode_mount(vp);
285 	int err;
286 
287 	if (fsess_not_impl(vnode_mount(vp), FUSE_FLUSH))
288 		return 0;
289 
290 	err = fuse_filehandle_getrw(vp, fflag, &fufh, cred, pid);
291 	if (err)
292 		return err;
293 
294 	fdisp_init(&fdi, sizeof(*ffi));
295 	fdisp_make_vp(&fdi, FUSE_FLUSH, vp, td, cred);
296 	ffi = fdi.indata;
297 	ffi->fh = fufh->fh_id;
298 	/*
299 	 * If the file has a POSIX lock then we're supposed to set lock_owner.
300 	 * If not, then lock_owner is undefined.  So we may as well always set
301 	 * it.
302 	 */
303 	ffi->lock_owner = td->td_proc->p_pid;
304 
305 	err = fdisp_wait_answ(&fdi);
306 	if (err == ENOSYS) {
307 		fsess_set_notimpl(mp, FUSE_FLUSH);
308 		err = 0;
309 	}
310 	fdisp_destroy(&fdi);
311 	return err;
312 }
313 
314 /* Close wrapper for fifos.  */
315 static int
316 fuse_fifo_close(struct vop_close_args *ap)
317 {
318 	return (fifo_specops.vop_close(ap));
319 }
320 
321 /* Invalidate a range of cached data, whether dirty of not */
322 static int
323 fuse_inval_buf_range(struct vnode *vp, off_t filesize, off_t start, off_t end)
324 {
325 	struct buf *bp;
326 	daddr_t left_lbn, end_lbn, right_lbn;
327 	off_t new_filesize;
328 	int iosize, left_on, right_on, right_blksize;
329 
330 	iosize = fuse_iosize(vp);
331 	left_lbn = start / iosize;
332 	end_lbn = howmany(end, iosize);
333 	left_on = start & (iosize - 1);
334 	if (left_on != 0) {
335 		bp = getblk(vp, left_lbn, iosize, PCATCH, 0, 0);
336 		if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyend >= left_on) {
337 			/*
338 			 * Flush the dirty buffer, because we don't have a
339 			 * byte-granular way to record which parts of the
340 			 * buffer are valid.
341 			 */
342 			bwrite(bp);
343 			if (bp->b_error)
344 				return (bp->b_error);
345 		} else {
346 			brelse(bp);
347 		}
348 	}
349 	right_on = end & (iosize - 1);
350 	if (right_on != 0) {
351 		right_lbn = end / iosize;
352 		new_filesize = MAX(filesize, end);
353 		right_blksize = MIN(iosize, new_filesize - iosize * right_lbn);
354 		bp = getblk(vp, right_lbn, right_blksize, PCATCH, 0, 0);
355 		if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyoff < right_on) {
356 			/*
357 			 * Flush the dirty buffer, because we don't have a
358 			 * byte-granular way to record which parts of the
359 			 * buffer are valid.
360 			 */
361 			bwrite(bp);
362 			if (bp->b_error)
363 				return (bp->b_error);
364 		} else {
365 			brelse(bp);
366 		}
367 	}
368 
369 	v_inval_buf_range(vp, left_lbn, end_lbn, iosize);
370 	return (0);
371 }
372 
373 
374 /* Send FUSE_LSEEK for this node */
375 static int
376 fuse_vnop_do_lseek(struct vnode *vp, struct thread *td, struct ucred *cred,
377 	pid_t pid, off_t *offp, int whence)
378 {
379 	struct fuse_dispatcher fdi;
380 	struct fuse_filehandle *fufh;
381 	struct fuse_lseek_in *flsi;
382 	struct fuse_lseek_out *flso;
383 	struct mount *mp = vnode_mount(vp);
384 	int err;
385 
386 	ASSERT_VOP_LOCKED(vp, __func__);
387 
388 	err = fuse_filehandle_getrw(vp, FREAD, &fufh, cred, pid);
389 	if (err)
390 		return (err);
391 	fdisp_init(&fdi, sizeof(*flsi));
392 	fdisp_make_vp(&fdi, FUSE_LSEEK, vp, td, cred);
393 	flsi = fdi.indata;
394 	flsi->fh = fufh->fh_id;
395 	flsi->offset = *offp;
396 	flsi->whence = whence;
397 	err = fdisp_wait_answ(&fdi);
398 	if (err == ENOSYS) {
399 		fsess_set_notimpl(mp, FUSE_LSEEK);
400 	} else if (err == 0) {
401 		fsess_set_impl(mp, FUSE_LSEEK);
402 		flso = fdi.answ;
403 		*offp = flso->offset;
404 	}
405 	fdisp_destroy(&fdi);
406 
407 	return (err);
408 }
409 
410 /*
411     struct vnop_access_args {
412 	struct vnode *a_vp;
413 #if VOP_ACCESS_TAKES_ACCMODE_T
414 	accmode_t a_accmode;
415 #else
416 	int a_mode;
417 #endif
418 	struct ucred *a_cred;
419 	struct thread *a_td;
420     };
421 */
422 static int
423 fuse_vnop_access(struct vop_access_args *ap)
424 {
425 	struct vnode *vp = ap->a_vp;
426 	int accmode = ap->a_accmode;
427 	struct ucred *cred = ap->a_cred;
428 
429 	struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp));
430 
431 	int err;
432 
433 	if (fuse_isdeadfs(vp)) {
434 		if (vnode_isvroot(vp)) {
435 			return 0;
436 		}
437 		return ENXIO;
438 	}
439 	if (!(data->dataflags & FSESS_INITED)) {
440 		if (vnode_isvroot(vp)) {
441 			if (priv_check_cred(cred, PRIV_VFS_ADMIN) ||
442 			    (fuse_match_cred(data->daemoncred, cred) == 0)) {
443 				return 0;
444 			}
445 		}
446 		return EBADF;
447 	}
448 	if (vnode_islnk(vp)) {
449 		return 0;
450 	}
451 
452 	err = fuse_internal_access(vp, accmode, ap->a_td, ap->a_cred);
453 	return err;
454 }
455 
456 /*
457  * struct vop_advlock_args {
458  *	struct vop_generic_args a_gen;
459  *	struct vnode *a_vp;
460  *	void *a_id;
461  *	int a_op;
462  *	struct flock *a_fl;
463  *	int a_flags;
464  * }
465  */
466 static int
467 fuse_vnop_advlock(struct vop_advlock_args *ap)
468 {
469 	struct vnode *vp = ap->a_vp;
470 	struct flock *fl = ap->a_fl;
471 	struct thread *td = curthread;
472 	struct ucred *cred = td->td_ucred;
473 	pid_t pid = td->td_proc->p_pid;
474 	struct fuse_filehandle *fufh;
475 	struct fuse_dispatcher fdi;
476 	struct fuse_lk_in *fli;
477 	struct fuse_lk_out *flo;
478 	enum fuse_opcode op;
479 	int dataflags, err;
480 	int flags = ap->a_flags;
481 
482 	dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags;
483 
484 	if (fuse_isdeadfs(vp)) {
485 		return ENXIO;
486 	}
487 
488 	switch(ap->a_op) {
489 	case F_GETLK:
490 		op = FUSE_GETLK;
491 		break;
492 	case F_SETLK:
493 		if (flags & F_WAIT)
494 			op = FUSE_SETLKW;
495 		else
496 			op = FUSE_SETLK;
497 		break;
498 	case F_UNLCK:
499 		op = FUSE_SETLK;
500 		break;
501 	default:
502 		return EINVAL;
503 	}
504 
505 	if (!(dataflags & FSESS_POSIX_LOCKS))
506 		return vop_stdadvlock(ap);
507 	/* FUSE doesn't properly support flock until protocol 7.17 */
508 	if (flags & F_FLOCK)
509 		return vop_stdadvlock(ap);
510 
511 	vn_lock(vp, LK_SHARED | LK_RETRY);
512 
513 	err = fuse_filehandle_get_anyflags(vp, &fufh, cred, pid);
514 	if (err)
515 		goto out;
516 
517 	fdisp_init(&fdi, sizeof(*fli));
518 
519 	fdisp_make_vp(&fdi, op, vp, td, cred);
520 	fli = fdi.indata;
521 	fli->fh = fufh->fh_id;
522 	fli->owner = td->td_proc->p_pid;
523 	fli->lk.start = fl->l_start;
524 	if (fl->l_len != 0)
525 		fli->lk.end = fl->l_start + fl->l_len - 1;
526 	else
527 		fli->lk.end = INT64_MAX;
528 	fli->lk.type = fl->l_type;
529 	fli->lk.pid = td->td_proc->p_pid;
530 
531 	err = fdisp_wait_answ(&fdi);
532 	fdisp_destroy(&fdi);
533 
534 	if (err == 0 && op == FUSE_GETLK) {
535 		flo = fdi.answ;
536 		fl->l_type = flo->lk.type;
537 		fl->l_pid = flo->lk.pid;
538 		if (flo->lk.type != F_UNLCK) {
539 			fl->l_start = flo->lk.start;
540 			if (flo->lk.end == INT64_MAX)
541 				fl->l_len = 0;
542 			else
543 				fl->l_len = flo->lk.end - flo->lk.start + 1;
544 			fl->l_start = flo->lk.start;
545 		}
546 	}
547 
548 out:
549 	VOP_UNLOCK(vp);
550 	return err;
551 }
552 
553 /* {
554 	struct vnode *a_vp;
555 	daddr_t a_bn;
556 	struct bufobj **a_bop;
557 	daddr_t *a_bnp;
558 	int *a_runp;
559 	int *a_runb;
560 } */
561 static int
562 fuse_vnop_bmap(struct vop_bmap_args *ap)
563 {
564 	struct vnode *vp = ap->a_vp;
565 	struct bufobj **bo = ap->a_bop;
566 	struct thread *td = curthread;
567 	struct mount *mp;
568 	struct fuse_dispatcher fdi;
569 	struct fuse_bmap_in *fbi;
570 	struct fuse_bmap_out *fbo;
571 	struct fuse_data *data;
572 	struct fuse_vnode_data *fvdat = VTOFUD(vp);
573 	uint64_t biosize;
574 	off_t fsize;
575 	daddr_t lbn = ap->a_bn;
576 	daddr_t *pbn = ap->a_bnp;
577 	int *runp = ap->a_runp;
578 	int *runb = ap->a_runb;
579 	int error = 0;
580 	int maxrun;
581 
582 	if (fuse_isdeadfs(vp)) {
583 		return ENXIO;
584 	}
585 
586 	mp = vnode_mount(vp);
587 	data = fuse_get_mpdata(mp);
588 	biosize = fuse_iosize(vp);
589 	maxrun = MIN(vp->v_mount->mnt_iosize_max / biosize - 1,
590 		data->max_readahead_blocks);
591 
592 	if (bo != NULL)
593 		*bo = &vp->v_bufobj;
594 
595 	/*
596 	 * The FUSE_BMAP operation does not include the runp and runb
597 	 * variables, so we must guess.  Report nonzero contiguous runs so
598 	 * cluster_read will combine adjacent reads.  It's worthwhile to reduce
599 	 * upcalls even if we don't know the true physical layout of the file.
600 	 *
601 	 * FUSE file systems may opt out of read clustering in two ways:
602 	 * * mounting with -onoclusterr
603 	 * * Setting max_readahead <= maxbcachebuf during FUSE_INIT
604 	 */
605 	if (runb != NULL)
606 		*runb = MIN(lbn, maxrun);
607 	if (runp != NULL && maxrun == 0)
608 		*runp = 0;
609 	else if (runp != NULL) {
610 		/*
611 		 * If the file's size is cached, use that value to calculate
612 		 * runp, even if the cache is expired.  runp is only advisory,
613 		 * and the risk of getting it wrong is not worth the cost of
614 		 * another upcall.
615 		 */
616 		if (fvdat->cached_attrs.va_size != VNOVAL)
617 			fsize = fvdat->cached_attrs.va_size;
618 		else
619 			error = fuse_vnode_size(vp, &fsize, td->td_ucred, td);
620 		if (error == 0)
621 			*runp = MIN(MAX(0, fsize / (off_t)biosize - lbn - 1),
622 				    maxrun);
623 		else
624 			*runp = 0;
625 	}
626 
627 	if (fsess_maybe_impl(mp, FUSE_BMAP)) {
628 		fdisp_init(&fdi, sizeof(*fbi));
629 		fdisp_make_vp(&fdi, FUSE_BMAP, vp, td, td->td_ucred);
630 		fbi = fdi.indata;
631 		fbi->block = lbn;
632 		fbi->blocksize = biosize;
633 		error = fdisp_wait_answ(&fdi);
634 		if (error == ENOSYS) {
635 			fdisp_destroy(&fdi);
636 			fsess_set_notimpl(mp, FUSE_BMAP);
637 			error = 0;
638 		} else {
639 			fbo = fdi.answ;
640 			if (error == 0 && pbn != NULL)
641 				*pbn = fbo->block;
642 			fdisp_destroy(&fdi);
643 			return error;
644 		}
645 	}
646 
647 	/* If the daemon doesn't support BMAP, make up a sensible default */
648 	if (pbn != NULL)
649 		*pbn = lbn * btodb(biosize);
650 	return (error);
651 }
652 
653 /*
654     struct vop_close_args {
655 	struct vnode *a_vp;
656 	int  a_fflag;
657 	struct ucred *a_cred;
658 	struct thread *a_td;
659     };
660 */
661 static int
662 fuse_vnop_close(struct vop_close_args *ap)
663 {
664 	struct vnode *vp = ap->a_vp;
665 	struct ucred *cred = ap->a_cred;
666 	int fflag = ap->a_fflag;
667 	struct thread *td = ap->a_td;
668 	pid_t pid = td->td_proc->p_pid;
669 	struct fuse_vnode_data *fvdat = VTOFUD(vp);
670 	int err = 0;
671 
672 	if (fuse_isdeadfs(vp))
673 		return 0;
674 	if (vnode_isdir(vp))
675 		return 0;
676 	if (fflag & IO_NDELAY)
677 		return 0;
678 
679 	err = fuse_flush(vp, cred, pid, fflag);
680 	if (err == 0 && (fvdat->flag & FN_ATIMECHANGE)) {
681 		struct vattr vap;
682 
683 		VATTR_NULL(&vap);
684 		vap.va_atime = fvdat->cached_attrs.va_atime;
685 		err = fuse_internal_setattr(vp, &vap, td, NULL);
686 	}
687 	/* TODO: close the file handle, if we're sure it's no longer used */
688 	if ((fvdat->flag & FN_SIZECHANGE) != 0) {
689 		fuse_vnode_savesize(vp, cred, td->td_proc->p_pid);
690 	}
691 	return err;
692 }
693 
694 /*
695    struct vop_copy_file_range_args {
696 	struct vop_generic_args a_gen;
697 	struct vnode *a_invp;
698 	off_t *a_inoffp;
699 	struct vnode *a_outvp;
700 	off_t *a_outoffp;
701 	size_t *a_lenp;
702 	unsigned int a_flags;
703 	struct ucred *a_incred;
704 	struct ucred *a_outcred;
705 	struct thread *a_fsizetd;
706 }
707  */
708 static int
709 fuse_vnop_copy_file_range(struct vop_copy_file_range_args *ap)
710 {
711 	struct vnode *invp = ap->a_invp;
712 	struct vnode *outvp = ap->a_outvp;
713 	struct mount *mp = vnode_mount(invp);
714 	struct fuse_vnode_data *outfvdat = VTOFUD(outvp);
715 	struct fuse_dispatcher fdi;
716 	struct fuse_filehandle *infufh, *outfufh;
717 	struct fuse_copy_file_range_in *fcfri;
718 	struct ucred *incred = ap->a_incred;
719 	struct ucred *outcred = ap->a_outcred;
720 	struct fuse_write_out *fwo;
721 	struct thread *td;
722 	struct uio io;
723 	off_t outfilesize;
724 	pid_t pid;
725 	int err;
726 
727 	if (mp != vnode_mount(outvp))
728 		goto fallback;
729 
730 	if (incred->cr_uid != outcred->cr_uid)
731 		goto fallback;
732 
733 	if (incred->cr_groups[0] != outcred->cr_groups[0])
734 		goto fallback;
735 
736 	if (fsess_not_impl(mp, FUSE_COPY_FILE_RANGE))
737 		goto fallback;
738 
739 	if (ap->a_fsizetd == NULL)
740 		td = curthread;
741 	else
742 		td = ap->a_fsizetd;
743 	pid = td->td_proc->p_pid;
744 
745 	/* Lock both vnodes, avoiding risk of deadlock. */
746 	do {
747 		err = vn_lock(outvp, LK_EXCLUSIVE);
748 		if (invp == outvp)
749 			break;
750 		if (err == 0) {
751 			err = vn_lock(invp, LK_SHARED | LK_NOWAIT);
752 			if (err == 0)
753 				break;
754 			VOP_UNLOCK(outvp);
755 			err = vn_lock(invp, LK_SHARED);
756 			if (err == 0)
757 				VOP_UNLOCK(invp);
758 		}
759 	} while (err == 0);
760 	if (err != 0)
761 		return (err);
762 
763 	err = fuse_filehandle_getrw(invp, FREAD, &infufh, incred, pid);
764 	if (err)
765 		goto unlock;
766 
767 	err = fuse_filehandle_getrw(outvp, FWRITE, &outfufh, outcred, pid);
768 	if (err)
769 		goto unlock;
770 
771 	if (ap->a_fsizetd) {
772 		io.uio_offset = *ap->a_outoffp;
773 		io.uio_resid = *ap->a_lenp;
774 		err = vn_rlimit_fsize(outvp, &io, ap->a_fsizetd);
775 		if (err)
776 			goto unlock;
777 	}
778 
779 	err = fuse_vnode_size(outvp, &outfilesize, outcred, curthread);
780 	if (err)
781 		goto unlock;
782 
783 	err = fuse_inval_buf_range(outvp, outfilesize, *ap->a_outoffp,
784 		*ap->a_outoffp + *ap->a_lenp);
785 	if (err)
786 		goto unlock;
787 
788 	fdisp_init(&fdi, sizeof(*fcfri));
789 	fdisp_make_vp(&fdi, FUSE_COPY_FILE_RANGE, invp, td, incred);
790 	fcfri = fdi.indata;
791 	fcfri->fh_in = infufh->fh_id;
792 	fcfri->off_in = *ap->a_inoffp;
793 	fcfri->nodeid_out = VTOI(outvp);
794 	fcfri->fh_out = outfufh->fh_id;
795 	fcfri->off_out = *ap->a_outoffp;
796 	fcfri->len = *ap->a_lenp;
797 	fcfri->flags = 0;
798 
799 	err = fdisp_wait_answ(&fdi);
800 	if (err == 0) {
801 		fwo = fdi.answ;
802 		*ap->a_lenp = fwo->size;
803 		*ap->a_inoffp += fwo->size;
804 		*ap->a_outoffp += fwo->size;
805 		fuse_internal_clear_suid_on_write(outvp, outcred, td);
806 		if (*ap->a_outoffp > outfvdat->cached_attrs.va_size)
807 			fuse_vnode_setsize(outvp, *ap->a_outoffp, false);
808 	}
809 	fdisp_destroy(&fdi);
810 
811 unlock:
812 	if (invp != outvp)
813 		VOP_UNLOCK(invp);
814 	VOP_UNLOCK(outvp);
815 
816 	if (err == ENOSYS) {
817 		fsess_set_notimpl(mp, FUSE_COPY_FILE_RANGE);
818 fallback:
819 		err = vn_generic_copy_file_range(ap->a_invp, ap->a_inoffp,
820 		    ap->a_outvp, ap->a_outoffp, ap->a_lenp, ap->a_flags,
821 		    ap->a_incred, ap->a_outcred, ap->a_fsizetd);
822 	}
823 
824 	return (err);
825 }
826 
827 static void
828 fdisp_make_mknod_for_fallback(
829 	struct fuse_dispatcher *fdip,
830 	struct componentname *cnp,
831 	struct vnode *dvp,
832 	uint64_t parentnid,
833 	struct thread *td,
834 	struct ucred *cred,
835 	mode_t mode,
836 	enum fuse_opcode *op)
837 {
838 	struct fuse_mknod_in *fmni;
839 
840 	fdisp_init(fdip, sizeof(*fmni) + cnp->cn_namelen + 1);
841 	*op = FUSE_MKNOD;
842 	fdisp_make(fdip, *op, vnode_mount(dvp), parentnid, td, cred);
843 	fmni = fdip->indata;
844 	fmni->mode = mode;
845 	fmni->rdev = 0;
846 	memcpy((char *)fdip->indata + sizeof(*fmni), cnp->cn_nameptr,
847 	    cnp->cn_namelen);
848 	((char *)fdip->indata)[sizeof(*fmni) + cnp->cn_namelen] = '\0';
849 }
850 /*
851     struct vnop_create_args {
852 	struct vnode *a_dvp;
853 	struct vnode **a_vpp;
854 	struct componentname *a_cnp;
855 	struct vattr *a_vap;
856     };
857 */
858 static int
859 fuse_vnop_create(struct vop_create_args *ap)
860 {
861 	struct vnode *dvp = ap->a_dvp;
862 	struct vnode **vpp = ap->a_vpp;
863 	struct componentname *cnp = ap->a_cnp;
864 	struct vattr *vap = ap->a_vap;
865 	struct thread *td = curthread;
866 	struct ucred *cred = cnp->cn_cred;
867 
868 	struct fuse_data *data;
869 	struct fuse_create_in *fci;
870 	struct fuse_entry_out *feo;
871 	struct fuse_open_out *foo;
872 	struct fuse_dispatcher fdi, fdi2;
873 	struct fuse_dispatcher *fdip = &fdi;
874 	struct fuse_dispatcher *fdip2 = NULL;
875 
876 	int err;
877 
878 	struct mount *mp = vnode_mount(dvp);
879 	data = fuse_get_mpdata(mp);
880 	uint64_t parentnid = VTOFUD(dvp)->nid;
881 	mode_t mode = MAKEIMODE(vap->va_type, vap->va_mode);
882 	enum fuse_opcode op;
883 	int flags;
884 
885 	if (fuse_isdeadfs(dvp))
886 		return ENXIO;
887 
888 	/* FUSE expects sockets to be created with FUSE_MKNOD */
889 	if (vap->va_type == VSOCK)
890 		return fuse_internal_mknod(dvp, vpp, cnp, vap);
891 
892 	/*
893 	 * VOP_CREATE doesn't tell us the open(2) flags, so we guess.  Only a
894 	 * writable mode makes sense, and we might as well include readability
895 	 * too.
896 	 */
897 	flags = O_RDWR;
898 
899 	bzero(&fdi, sizeof(fdi));
900 
901 	if (vap->va_type != VREG)
902 		return (EINVAL);
903 
904 	if (fsess_not_impl(mp, FUSE_CREATE) || vap->va_type == VSOCK) {
905 		/* Fallback to FUSE_MKNOD/FUSE_OPEN */
906 		fdisp_make_mknod_for_fallback(fdip, cnp, dvp, parentnid, td,
907 			cred, mode, &op);
908 	} else {
909 		/* Use FUSE_CREATE */
910 		size_t insize;
911 
912 		op = FUSE_CREATE;
913 		fdisp_init(fdip, sizeof(*fci) + cnp->cn_namelen + 1);
914 		fdisp_make(fdip, op, vnode_mount(dvp), parentnid, td, cred);
915 		fci = fdip->indata;
916 		fci->mode = mode;
917 		fci->flags = O_CREAT | flags;
918 		if (fuse_libabi_geq(data, 7, 12)) {
919 			insize = sizeof(*fci);
920 			fci->umask = td->td_proc->p_pd->pd_cmask;
921 		} else {
922 			insize = sizeof(struct fuse_open_in);
923 		}
924 
925 		memcpy((char *)fdip->indata + insize, cnp->cn_nameptr,
926 		    cnp->cn_namelen);
927 		((char *)fdip->indata)[insize + cnp->cn_namelen] = '\0';
928 	}
929 
930 	err = fdisp_wait_answ(fdip);
931 
932 	if (err) {
933 		if (err == ENOSYS && op == FUSE_CREATE) {
934 			fsess_set_notimpl(mp, FUSE_CREATE);
935 			fdisp_destroy(fdip);
936 			fdisp_make_mknod_for_fallback(fdip, cnp, dvp,
937 				parentnid, td, cred, mode, &op);
938 			err = fdisp_wait_answ(fdip);
939 		}
940 		if (err)
941 			goto out;
942 	}
943 
944 	feo = fdip->answ;
945 
946 	if ((err = fuse_internal_checkentry(feo, vap->va_type))) {
947 		goto out;
948 	}
949 
950 	if (op == FUSE_CREATE) {
951 		foo = (struct fuse_open_out*)(feo + 1);
952 	} else {
953 		/* Issue a separate FUSE_OPEN */
954 		struct fuse_open_in *foi;
955 
956 		fdip2 = &fdi2;
957 		fdisp_init(fdip2, sizeof(*foi));
958 		fdisp_make(fdip2, FUSE_OPEN, vnode_mount(dvp), feo->nodeid, td,
959 			cred);
960 		foi = fdip2->indata;
961 		foi->flags = flags;
962 		err = fdisp_wait_answ(fdip2);
963 		if (err)
964 			goto out;
965 		foo = fdip2->answ;
966 	}
967 	err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, vap->va_type);
968 	if (err) {
969 		struct fuse_release_in *fri;
970 		uint64_t nodeid = feo->nodeid;
971 		uint64_t fh_id = foo->fh;
972 
973 		fdisp_init(fdip, sizeof(*fri));
974 		fdisp_make(fdip, FUSE_RELEASE, mp, nodeid, td, cred);
975 		fri = fdip->indata;
976 		fri->fh = fh_id;
977 		fri->flags = flags;
978 		fuse_insert_callback(fdip->tick, fuse_internal_forget_callback);
979 		fuse_insert_message(fdip->tick, false);
980 		goto out;
981 	}
982 	ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create");
983 	fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid,
984 		feo->attr_valid_nsec, NULL, true);
985 
986 	fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td, cred, foo);
987 	fuse_vnode_open(*vpp, foo->open_flags, td);
988 	/*
989 	 * Purge the parent's attribute cache because the daemon should've
990 	 * updated its mtime and ctime
991 	 */
992 	fuse_vnode_clear_attr_cache(dvp);
993 	cache_purge_negative(dvp);
994 
995 out:
996 	if (fdip2)
997 		fdisp_destroy(fdip2);
998 	fdisp_destroy(fdip);
999 	return err;
1000 }
1001 
1002 /*
1003     struct vnop_fdatasync_args {
1004 	struct vop_generic_args a_gen;
1005 	struct vnode * a_vp;
1006 	struct thread * a_td;
1007     };
1008 */
1009 static int
1010 fuse_vnop_fdatasync(struct vop_fdatasync_args *ap)
1011 {
1012 	struct vnode *vp = ap->a_vp;
1013 	struct thread *td = ap->a_td;
1014 	int waitfor = MNT_WAIT;
1015 
1016 	int err = 0;
1017 
1018 	if (fuse_isdeadfs(vp)) {
1019 		return 0;
1020 	}
1021 	if ((err = vop_stdfdatasync_buf(ap)))
1022 		return err;
1023 
1024 	return fuse_internal_fsync(vp, td, waitfor, true);
1025 }
1026 
1027 /*
1028     struct vnop_fsync_args {
1029 	struct vop_generic_args a_gen;
1030 	struct vnode * a_vp;
1031 	int  a_waitfor;
1032 	struct thread * a_td;
1033     };
1034 */
1035 static int
1036 fuse_vnop_fsync(struct vop_fsync_args *ap)
1037 {
1038 	struct vnode *vp = ap->a_vp;
1039 	struct thread *td = ap->a_td;
1040 	int waitfor = ap->a_waitfor;
1041 	int err = 0;
1042 
1043 	if (fuse_isdeadfs(vp)) {
1044 		return 0;
1045 	}
1046 	if ((err = vop_stdfsync(ap)))
1047 		return err;
1048 
1049 	return fuse_internal_fsync(vp, td, waitfor, false);
1050 }
1051 
1052 /*
1053     struct vnop_getattr_args {
1054 	struct vnode *a_vp;
1055 	struct vattr *a_vap;
1056 	struct ucred *a_cred;
1057 	struct thread *a_td;
1058     };
1059 */
1060 static int
1061 fuse_vnop_getattr(struct vop_getattr_args *ap)
1062 {
1063 	struct vnode *vp = ap->a_vp;
1064 	struct vattr *vap = ap->a_vap;
1065 	struct ucred *cred = ap->a_cred;
1066 	struct thread *td = curthread;
1067 
1068 	int err = 0;
1069 	int dataflags;
1070 
1071 	dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags;
1072 
1073 	/* Note that we are not bailing out on a dead file system just yet. */
1074 
1075 	if (!(dataflags & FSESS_INITED)) {
1076 		if (!vnode_isvroot(vp)) {
1077 			fdata_set_dead(fuse_get_mpdata(vnode_mount(vp)));
1078 			err = ENOTCONN;
1079 			return err;
1080 		} else {
1081 			goto fake;
1082 		}
1083 	}
1084 	err = fuse_internal_getattr(vp, vap, cred, td);
1085 	if (err == ENOTCONN && vnode_isvroot(vp)) {
1086 		/* see comment in fuse_vfsop_statfs() */
1087 		goto fake;
1088 	} else {
1089 		return err;
1090 	}
1091 
1092 fake:
1093 	bzero(vap, sizeof(*vap));
1094 	vap->va_type = vnode_vtype(vp);
1095 
1096 	return 0;
1097 }
1098 
1099 /*
1100     struct vnop_inactive_args {
1101 	struct vnode *a_vp;
1102     };
1103 */
1104 static int
1105 fuse_vnop_inactive(struct vop_inactive_args *ap)
1106 {
1107 	struct vnode *vp = ap->a_vp;
1108 	struct thread *td = curthread;
1109 
1110 	struct fuse_vnode_data *fvdat = VTOFUD(vp);
1111 	struct fuse_filehandle *fufh, *fufh_tmp;
1112 
1113 	int need_flush = 1;
1114 
1115 	LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) {
1116 		if (need_flush && vp->v_type == VREG) {
1117 			if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) {
1118 				fuse_vnode_savesize(vp, NULL, 0);
1119 			}
1120 			if ((fvdat->flag & FN_REVOKED) != 0)
1121 				fuse_io_invalbuf(vp, td);
1122 			else
1123 				fuse_io_flushbuf(vp, MNT_WAIT, td);
1124 			need_flush = 0;
1125 		}
1126 		fuse_filehandle_close(vp, fufh, td, NULL);
1127 	}
1128 
1129 	if ((fvdat->flag & FN_REVOKED) != 0)
1130 		vrecycle(vp);
1131 
1132 	return 0;
1133 }
1134 
1135 /*
1136     struct vnop_ioctl_args {
1137 	struct vnode *a_vp;
1138 	u_long a_command;
1139 	caddr_t a_data;
1140 	int a_fflag;
1141 	struct ucred *a_cred;
1142 	struct thread *a_td;
1143     };
1144 */
1145 static int
1146 fuse_vnop_ioctl(struct vop_ioctl_args *ap)
1147 {
1148 	struct vnode *vp = ap->a_vp;
1149 	struct mount *mp = vnode_mount(vp);
1150 	struct ucred *cred = ap->a_cred;
1151 	off_t *offp;
1152 	pid_t pid = ap->a_td->td_proc->p_pid;
1153 	int err;
1154 
1155 	switch (ap->a_command) {
1156 	case FIOSEEKDATA:
1157 	case FIOSEEKHOLE:
1158 		/* Call FUSE_LSEEK, if we can, or fall back to vop_stdioctl */
1159 		if (fsess_maybe_impl(mp, FUSE_LSEEK)) {
1160 			int whence;
1161 
1162 			offp = ap->a_data;
1163 			if (ap->a_command == FIOSEEKDATA)
1164 				whence = SEEK_DATA;
1165 			else
1166 				whence = SEEK_HOLE;
1167 
1168 			vn_lock(vp, LK_SHARED | LK_RETRY);
1169 			err = fuse_vnop_do_lseek(vp, ap->a_td, cred, pid, offp,
1170 			    whence);
1171 			VOP_UNLOCK(vp);
1172 		}
1173 		if (fsess_not_impl(mp, FUSE_LSEEK))
1174 			err = vop_stdioctl(ap);
1175 		break;
1176 	default:
1177 		/* TODO: implement FUSE_IOCTL */
1178 		err = ENOTTY;
1179 		break;
1180 	}
1181 	return (err);
1182 }
1183 
1184 
1185 /*
1186     struct vnop_link_args {
1187 	struct vnode *a_tdvp;
1188 	struct vnode *a_vp;
1189 	struct componentname *a_cnp;
1190     };
1191 */
1192 static int
1193 fuse_vnop_link(struct vop_link_args *ap)
1194 {
1195 	struct vnode *vp = ap->a_vp;
1196 	struct vnode *tdvp = ap->a_tdvp;
1197 	struct componentname *cnp = ap->a_cnp;
1198 
1199 	struct vattr *vap = VTOVA(vp);
1200 
1201 	struct fuse_dispatcher fdi;
1202 	struct fuse_entry_out *feo;
1203 	struct fuse_link_in fli;
1204 
1205 	int err;
1206 
1207 	if (fuse_isdeadfs(vp)) {
1208 		return ENXIO;
1209 	}
1210 	if (vnode_mount(tdvp) != vnode_mount(vp)) {
1211 		return EXDEV;
1212 	}
1213 
1214 	/*
1215 	 * This is a seatbelt check to protect naive userspace filesystems from
1216 	 * themselves and the limitations of the FUSE IPC protocol.  If a
1217 	 * filesystem does not allow attribute caching, assume it is capable of
1218 	 * validating that nlink does not overflow.
1219 	 */
1220 	if (vap != NULL && vap->va_nlink >= FUSE_LINK_MAX)
1221 		return EMLINK;
1222 	fli.oldnodeid = VTOI(vp);
1223 
1224 	fdisp_init(&fdi, 0);
1225 	fuse_internal_newentry_makerequest(vnode_mount(tdvp), VTOI(tdvp), cnp,
1226 	    FUSE_LINK, &fli, sizeof(fli), &fdi);
1227 	if ((err = fdisp_wait_answ(&fdi))) {
1228 		goto out;
1229 	}
1230 	feo = fdi.answ;
1231 
1232 	err = fuse_internal_checkentry(feo, vnode_vtype(vp));
1233 	if (!err) {
1234 		/*
1235 		 * Purge the parent's attribute cache because the daemon
1236 		 * should've updated its mtime and ctime
1237 		 */
1238 		fuse_vnode_clear_attr_cache(tdvp);
1239 		fuse_internal_cache_attrs(vp, &feo->attr, feo->attr_valid,
1240 			feo->attr_valid_nsec, NULL, true);
1241 	}
1242 out:
1243 	fdisp_destroy(&fdi);
1244 	return err;
1245 }
1246 
1247 struct fuse_lookup_alloc_arg {
1248 	struct fuse_entry_out *feo;
1249 	struct componentname *cnp;
1250 	uint64_t nid;
1251 	enum vtype vtyp;
1252 };
1253 
1254 /* Callback for vn_get_ino */
1255 static int
1256 fuse_lookup_alloc(struct mount *mp, void *arg, int lkflags, struct vnode **vpp)
1257 {
1258 	struct fuse_lookup_alloc_arg *flaa = arg;
1259 
1260 	return fuse_vnode_get(mp, flaa->feo, flaa->nid, NULL, vpp, flaa->cnp,
1261 		flaa->vtyp);
1262 }
1263 
1264 SDT_PROBE_DEFINE3(fusefs, , vnops, cache_lookup,
1265 	"int", "struct timespec*", "struct timespec*");
1266 /*
1267     struct vnop_lookup_args {
1268 	struct vnodeop_desc *a_desc;
1269 	struct vnode *a_dvp;
1270 	struct vnode **a_vpp;
1271 	struct componentname *a_cnp;
1272     };
1273 */
1274 int
1275 fuse_vnop_lookup(struct vop_lookup_args *ap)
1276 {
1277 	struct vnode *dvp = ap->a_dvp;
1278 	struct vnode **vpp = ap->a_vpp;
1279 	struct componentname *cnp = ap->a_cnp;
1280 	struct thread *td = curthread;
1281 	struct ucred *cred = cnp->cn_cred;
1282 
1283 	int nameiop = cnp->cn_nameiop;
1284 	int flags = cnp->cn_flags;
1285 	int wantparent = flags & (LOCKPARENT | WANTPARENT);
1286 	int islastcn = flags & ISLASTCN;
1287 	struct mount *mp = vnode_mount(dvp);
1288 	struct fuse_data *data = fuse_get_mpdata(mp);
1289 	int default_permissions = data->dataflags & FSESS_DEFAULT_PERMISSIONS;
1290 
1291 	int err = 0;
1292 	int lookup_err = 0;
1293 	struct vnode *vp = NULL;
1294 
1295 	struct fuse_dispatcher fdi;
1296 	bool did_lookup = false;
1297 	struct fuse_entry_out *feo = NULL;
1298 	enum vtype vtyp;	/* vnode type of target */
1299 	off_t filesize;		/* filesize of target */
1300 
1301 	uint64_t nid;
1302 
1303 	if (fuse_isdeadfs(dvp)) {
1304 		*vpp = NULL;
1305 		return ENXIO;
1306 	}
1307 	if (!vnode_isdir(dvp))
1308 		return ENOTDIR;
1309 
1310 	if (islastcn && vfs_isrdonly(mp) && (nameiop != LOOKUP))
1311 		return EROFS;
1312 
1313 	if ((cnp->cn_flags & NOEXECCHECK) != 0)
1314 		cnp->cn_flags &= ~NOEXECCHECK;
1315 	else if ((err = fuse_internal_access(dvp, VEXEC, td, cred)))
1316 		return err;
1317 
1318 	if (flags & ISDOTDOT) {
1319 		KASSERT(VTOFUD(dvp)->flag & FN_PARENT_NID,
1320 			("Looking up .. is TODO"));
1321 		nid = VTOFUD(dvp)->parent_nid;
1322 		if (nid == 0)
1323 			return ENOENT;
1324 		/* .. is obviously a directory */
1325 		vtyp = VDIR;
1326 		filesize = 0;
1327 	} else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
1328 		nid = VTOI(dvp);
1329 		/* . is obviously a directory */
1330 		vtyp = VDIR;
1331 		filesize = 0;
1332 	} else {
1333 		struct timespec now, timeout;
1334 		int ncpticks; /* here to accomodate for API contract */
1335 
1336 		err = cache_lookup(dvp, vpp, cnp, &timeout, &ncpticks);
1337 		getnanouptime(&now);
1338 		SDT_PROBE3(fusefs, , vnops, cache_lookup, err, &timeout, &now);
1339 		switch (err) {
1340 		case -1:		/* positive match */
1341 			if (timespeccmp(&timeout, &now, >)) {
1342 				counter_u64_add(fuse_lookup_cache_hits, 1);
1343 			} else {
1344 				/* Cache timeout */
1345 				counter_u64_add(fuse_lookup_cache_misses, 1);
1346 				bintime_clear(
1347 					&VTOFUD(*vpp)->entry_cache_timeout);
1348 				cache_purge(*vpp);
1349 				if (dvp != *vpp)
1350 					vput(*vpp);
1351 				else
1352 					vrele(*vpp);
1353 				*vpp = NULL;
1354 				break;
1355 			}
1356 			return 0;
1357 
1358 		case 0:		/* no match in cache */
1359 			counter_u64_add(fuse_lookup_cache_misses, 1);
1360 			break;
1361 
1362 		case ENOENT:		/* negative match */
1363 			if (timespeccmp(&timeout, &now, <=)) {
1364 				/* Cache timeout */
1365 				cache_purge_negative(dvp);
1366 				break;
1367 			}
1368 			/* fall through */
1369 		default:
1370 			return err;
1371 		}
1372 
1373 		nid = VTOI(dvp);
1374 		fdisp_init(&fdi, cnp->cn_namelen + 1);
1375 		fdisp_make(&fdi, FUSE_LOOKUP, mp, nid, td, cred);
1376 
1377 		memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen);
1378 		((char *)fdi.indata)[cnp->cn_namelen] = '\0';
1379 		lookup_err = fdisp_wait_answ(&fdi);
1380 		did_lookup = true;
1381 
1382 		if (!lookup_err) {
1383 			/* lookup call succeeded */
1384 			feo = (struct fuse_entry_out *)fdi.answ;
1385 			nid = feo->nodeid;
1386 			if (nid == 0) {
1387 				/* zero nodeid means ENOENT and cache it */
1388 				struct timespec timeout;
1389 
1390 				fdi.answ_stat = ENOENT;
1391 				lookup_err = ENOENT;
1392 				if (cnp->cn_flags & MAKEENTRY) {
1393 					fuse_validity_2_timespec(feo, &timeout);
1394 					cache_enter_time(dvp, *vpp, cnp,
1395 						&timeout, NULL);
1396 				}
1397 			} else if (nid == FUSE_ROOT_ID) {
1398 				lookup_err = EINVAL;
1399 			}
1400 			vtyp = IFTOVT(feo->attr.mode);
1401 			filesize = feo->attr.size;
1402 		}
1403 		if (lookup_err && (!fdi.answ_stat || lookup_err != ENOENT)) {
1404 			fdisp_destroy(&fdi);
1405 			return lookup_err;
1406 		}
1407 	}
1408 	/* lookup_err, if non-zero, must be ENOENT at this point */
1409 
1410 	if (lookup_err) {
1411 		/* Entry not found */
1412 		if ((nameiop == CREATE || nameiop == RENAME) && islastcn) {
1413 			if (default_permissions)
1414 				err = fuse_internal_access(dvp, VWRITE, td,
1415 				    cred);
1416 			else
1417 				err = 0;
1418 			if (!err) {
1419 				/*
1420 				 * Set the SAVENAME flag to hold onto the
1421 				 * pathname for use later in VOP_CREATE or
1422 				 * VOP_RENAME.
1423 				 */
1424 				cnp->cn_flags |= SAVENAME;
1425 
1426 				err = EJUSTRETURN;
1427 			}
1428 		} else {
1429 			err = ENOENT;
1430 		}
1431 	} else {
1432 		/* Entry was found */
1433 		if (flags & ISDOTDOT) {
1434 			struct fuse_lookup_alloc_arg flaa;
1435 
1436 			flaa.nid = nid;
1437 			flaa.feo = feo;
1438 			flaa.cnp = cnp;
1439 			flaa.vtyp = vtyp;
1440 			err = vn_vget_ino_gen(dvp, fuse_lookup_alloc, &flaa, 0,
1441 				&vp);
1442 			*vpp = vp;
1443 		} else if (nid == VTOI(dvp)) {
1444 			vref(dvp);
1445 			*vpp = dvp;
1446 		} else {
1447 			struct fuse_vnode_data *fvdat;
1448 
1449 			err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
1450 			    &vp, cnp, vtyp);
1451 			if (err)
1452 				goto out;
1453 			*vpp = vp;
1454 			fvdat = VTOFUD(vp);
1455 
1456 			MPASS(feo != NULL);
1457 			fuse_internal_cache_attrs(*vpp, &feo->attr,
1458 				feo->attr_valid, feo->attr_valid_nsec, NULL, true);
1459 			fuse_validity_2_bintime(feo->entry_valid,
1460 				feo->entry_valid_nsec,
1461 				&fvdat->entry_cache_timeout);
1462 
1463 			if ((nameiop == DELETE || nameiop == RENAME) &&
1464 				islastcn && default_permissions)
1465 			{
1466 				struct vattr dvattr;
1467 
1468 				err = fuse_internal_access(dvp, VWRITE, td,
1469 					cred);
1470 				if (err != 0)
1471 					goto out;
1472 				/*
1473 				 * if the parent's sticky bit is set, check
1474 				 * whether we're allowed to remove the file.
1475 				 * Need to figure out the vnode locking to make
1476 				 * this work.
1477 				 */
1478 				fuse_internal_getattr(dvp, &dvattr, cred, td);
1479 				if ((dvattr.va_mode & S_ISTXT) &&
1480 					fuse_internal_access(dvp, VADMIN, td,
1481 						cred) &&
1482 					fuse_internal_access(*vpp, VADMIN, td,
1483 						cred)) {
1484 					err = EPERM;
1485 					goto out;
1486 				}
1487 			}
1488 
1489 			if (islastcn && (
1490 				(nameiop == DELETE) ||
1491 				(nameiop == RENAME && wantparent))) {
1492 				cnp->cn_flags |= SAVENAME;
1493 			}
1494 		}
1495 	}
1496 out:
1497 	if (err) {
1498 		if (vp != NULL && dvp != vp)
1499 			vput(vp);
1500 		else if (vp != NULL)
1501 			vrele(vp);
1502 		*vpp = NULL;
1503 	}
1504 	if (did_lookup)
1505 		fdisp_destroy(&fdi);
1506 
1507 	return err;
1508 }
1509 
1510 /*
1511     struct vnop_mkdir_args {
1512 	struct vnode *a_dvp;
1513 	struct vnode **a_vpp;
1514 	struct componentname *a_cnp;
1515 	struct vattr *a_vap;
1516     };
1517 */
1518 static int
1519 fuse_vnop_mkdir(struct vop_mkdir_args *ap)
1520 {
1521 	struct vnode *dvp = ap->a_dvp;
1522 	struct vnode **vpp = ap->a_vpp;
1523 	struct componentname *cnp = ap->a_cnp;
1524 	struct vattr *vap = ap->a_vap;
1525 
1526 	struct fuse_mkdir_in fmdi;
1527 
1528 	if (fuse_isdeadfs(dvp)) {
1529 		return ENXIO;
1530 	}
1531 	fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);
1532 	fmdi.umask = curthread->td_proc->p_pd->pd_cmask;
1533 
1534 	return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi,
1535 	    sizeof(fmdi), VDIR));
1536 }
1537 
1538 /*
1539     struct vnop_mknod_args {
1540 	struct vnode *a_dvp;
1541 	struct vnode **a_vpp;
1542 	struct componentname *a_cnp;
1543 	struct vattr *a_vap;
1544     };
1545 */
1546 static int
1547 fuse_vnop_mknod(struct vop_mknod_args *ap)
1548 {
1549 
1550 	struct vnode *dvp = ap->a_dvp;
1551 	struct vnode **vpp = ap->a_vpp;
1552 	struct componentname *cnp = ap->a_cnp;
1553 	struct vattr *vap = ap->a_vap;
1554 
1555 	if (fuse_isdeadfs(dvp))
1556 		return ENXIO;
1557 
1558 	return fuse_internal_mknod(dvp, vpp, cnp, vap);
1559 }
1560 
1561 /*
1562     struct vop_open_args {
1563 	struct vnode *a_vp;
1564 	int  a_mode;
1565 	struct ucred *a_cred;
1566 	struct thread *a_td;
1567 	int a_fdidx; / struct file *a_fp;
1568     };
1569 */
1570 static int
1571 fuse_vnop_open(struct vop_open_args *ap)
1572 {
1573 	struct vnode *vp = ap->a_vp;
1574 	int a_mode = ap->a_mode;
1575 	struct thread *td = ap->a_td;
1576 	struct ucred *cred = ap->a_cred;
1577 	pid_t pid = td->td_proc->p_pid;
1578 	struct fuse_vnode_data *fvdat;
1579 
1580 	if (fuse_isdeadfs(vp))
1581 		return ENXIO;
1582 	if (vp->v_type == VCHR || vp->v_type == VBLK || vp->v_type == VFIFO)
1583 		return (EOPNOTSUPP);
1584 	if ((a_mode & (FREAD | FWRITE | FEXEC)) == 0)
1585 		return EINVAL;
1586 
1587 	fvdat = VTOFUD(vp);
1588 
1589 	if (fuse_filehandle_validrw(vp, a_mode, cred, pid)) {
1590 		fuse_vnode_open(vp, 0, td);
1591 		return 0;
1592 	}
1593 
1594 	return fuse_filehandle_open(vp, a_mode, NULL, td, cred);
1595 }
1596 
1597 static int
1598 fuse_vnop_pathconf(struct vop_pathconf_args *ap)
1599 {
1600 	struct vnode *vp = ap->a_vp;
1601 	struct mount *mp;
1602 
1603 	switch (ap->a_name) {
1604 	case _PC_FILESIZEBITS:
1605 		*ap->a_retval = 64;
1606 		return (0);
1607 	case _PC_NAME_MAX:
1608 		*ap->a_retval = NAME_MAX;
1609 		return (0);
1610 	case _PC_LINK_MAX:
1611 		*ap->a_retval = MIN(LONG_MAX, FUSE_LINK_MAX);
1612 		return (0);
1613 	case _PC_SYMLINK_MAX:
1614 		*ap->a_retval = MAXPATHLEN;
1615 		return (0);
1616 	case _PC_NO_TRUNC:
1617 		*ap->a_retval = 1;
1618 		return (0);
1619 	case _PC_MIN_HOLE_SIZE:
1620 		/*
1621 		 * The FUSE protocol provides no mechanism for a server to
1622 		 * report _PC_MIN_HOLE_SIZE.  It's a protocol bug.  Instead,
1623 		 * return EINVAL if the server does not support FUSE_LSEEK, or
1624 		 * 1 if it does.
1625 		 */
1626 		mp = vnode_mount(vp);
1627 		if (!fsess_is_impl(mp, FUSE_LSEEK) &&
1628 		    !fsess_not_impl(mp, FUSE_LSEEK)) {
1629 			off_t offset = 0;
1630 
1631 			/* Issue a FUSE_LSEEK to find out if it's implemented */
1632 			fuse_vnop_do_lseek(vp, curthread, curthread->td_ucred,
1633 			    curthread->td_proc->p_pid, &offset, SEEK_DATA);
1634 		}
1635 
1636 		if (fsess_is_impl(mp, FUSE_LSEEK)) {
1637 			*ap->a_retval = 1;
1638 			return (0);
1639 		} else {
1640 			/*
1641 			 * Probably FUSE_LSEEK is not implemented.  It might
1642 			 * be, if the FUSE_LSEEK above returned an error like
1643 			 * EACCES, but in that case we can't tell, so it's
1644 			 * safest to report EINVAL anyway.
1645 			 */
1646 			return (EINVAL);
1647 		}
1648 	default:
1649 		return (vop_stdpathconf(ap));
1650 	}
1651 }
1652 
1653 SDT_PROBE_DEFINE3(fusefs, , vnops, filehandles_closed, "struct vnode*",
1654     "struct uio*", "struct ucred*");
1655 /*
1656     struct vnop_read_args {
1657 	struct vnode *a_vp;
1658 	struct uio *a_uio;
1659 	int  a_ioflag;
1660 	struct ucred *a_cred;
1661     };
1662 */
1663 static int
1664 fuse_vnop_read(struct vop_read_args *ap)
1665 {
1666 	struct vnode *vp = ap->a_vp;
1667 	struct uio *uio = ap->a_uio;
1668 	int ioflag = ap->a_ioflag;
1669 	struct ucred *cred = ap->a_cred;
1670 	pid_t pid = curthread->td_proc->p_pid;
1671 	struct fuse_filehandle *fufh;
1672 	int err;
1673 	bool closefufh = false, directio;
1674 
1675 	MPASS(vp->v_type == VREG || vp->v_type == VDIR);
1676 
1677 	if (fuse_isdeadfs(vp)) {
1678 		return ENXIO;
1679 	}
1680 
1681 	if (VTOFUD(vp)->flag & FN_DIRECTIO) {
1682 		ioflag |= IO_DIRECT;
1683 	}
1684 
1685 	err = fuse_filehandle_getrw(vp, FREAD, &fufh, cred, pid);
1686 	if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) {
1687 		/*
1688 		 * nfsd will do I/O without first doing VOP_OPEN.  We
1689 		 * must implicitly open the file here
1690 		 */
1691 		err = fuse_filehandle_open(vp, FREAD, &fufh, curthread, cred);
1692 		closefufh = true;
1693 	}
1694 	if (err) {
1695 		SDT_PROBE3(fusefs, , vnops, filehandles_closed, vp, uio, cred);
1696 		return err;
1697 	}
1698 
1699 	/*
1700          * Ideally, when the daemon asks for direct io at open time, the
1701          * standard file flag should be set according to this, so that would
1702          * just change the default mode, which later on could be changed via
1703          * fcntl(2).
1704          * But this doesn't work, the O_DIRECT flag gets cleared at some point
1705          * (don't know where). So to make any use of the Fuse direct_io option,
1706          * we hardwire it into the file's private data (similarly to Linux,
1707          * btw.).
1708          */
1709 	directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp));
1710 
1711 	fuse_vnode_update(vp, FN_ATIMECHANGE);
1712 	if (directio) {
1713 		SDT_PROBE2(fusefs, , vnops, trace, 1, "direct read of vnode");
1714 		err = fuse_read_directbackend(vp, uio, cred, fufh);
1715 	} else {
1716 		SDT_PROBE2(fusefs, , vnops, trace, 1, "buffered read of vnode");
1717 		err = fuse_read_biobackend(vp, uio, ioflag, cred, fufh, pid);
1718 	}
1719 
1720 	if (closefufh)
1721 		fuse_filehandle_close(vp, fufh, curthread, cred);
1722 
1723 	return (err);
1724 }
1725 
1726 /*
1727     struct vnop_readdir_args {
1728 	struct vnode *a_vp;
1729 	struct uio *a_uio;
1730 	struct ucred *a_cred;
1731 	int *a_eofflag;
1732 	int *a_ncookies;
1733 	uint64_t **a_cookies;
1734     };
1735 */
1736 static int
1737 fuse_vnop_readdir(struct vop_readdir_args *ap)
1738 {
1739 	struct vnode *vp = ap->a_vp;
1740 	struct uio *uio = ap->a_uio;
1741 	struct ucred *cred = ap->a_cred;
1742 	struct fuse_filehandle *fufh = NULL;
1743 	struct fuse_iov cookediov;
1744 	int err = 0;
1745 	uint64_t *cookies;
1746 	off_t startoff;
1747 	ssize_t tresid;
1748 	int ncookies;
1749 	bool closefufh = false;
1750 	pid_t pid = curthread->td_proc->p_pid;
1751 
1752 	if (ap->a_eofflag)
1753 		*ap->a_eofflag = 0;
1754 	if (fuse_isdeadfs(vp)) {
1755 		return ENXIO;
1756 	}
1757 	if (				/* XXXIP ((uio_iovcnt(uio) > 1)) || */
1758 	    (uio_resid(uio) < sizeof(struct dirent))) {
1759 		return EINVAL;
1760 	}
1761 
1762 	tresid = uio->uio_resid;
1763 	startoff = uio->uio_offset;
1764 	err = fuse_filehandle_get_dir(vp, &fufh, cred, pid);
1765 	if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) {
1766 		/*
1767 		 * nfsd will do VOP_READDIR without first doing VOP_OPEN.  We
1768 		 * must implicitly open the directory here
1769 		 */
1770 		err = fuse_filehandle_open(vp, FREAD, &fufh, curthread, cred);
1771 		if (err == 0) {
1772 			/*
1773 			 * When a directory is opened, it must be read from
1774 			 * the beginning.  Hopefully, the "startoff" still
1775 			 * exists as an offset cookie for the directory.
1776 			 * If not, it will read the entire directory without
1777 			 * returning any entries and just return eof.
1778 			 */
1779 			uio->uio_offset = 0;
1780 		}
1781 		closefufh = true;
1782 	}
1783 	if (err)
1784 		return (err);
1785 	if (ap->a_ncookies != NULL) {
1786 		ncookies = uio->uio_resid /
1787 			(offsetof(struct dirent, d_name) + 4) + 1;
1788 		cookies = malloc(ncookies * sizeof(*cookies), M_TEMP, M_WAITOK);
1789 		*ap->a_ncookies = ncookies;
1790 		*ap->a_cookies = cookies;
1791 	} else {
1792 		ncookies = 0;
1793 		cookies = NULL;
1794 	}
1795 #define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1)
1796 	fiov_init(&cookediov, DIRCOOKEDSIZE);
1797 
1798 	err = fuse_internal_readdir(vp, uio, startoff, fufh, &cookediov,
1799 		&ncookies, cookies);
1800 
1801 	fiov_teardown(&cookediov);
1802 	if (closefufh)
1803 		fuse_filehandle_close(vp, fufh, curthread, cred);
1804 
1805 	if (ap->a_ncookies != NULL) {
1806 		if (err == 0) {
1807 			*ap->a_ncookies -= ncookies;
1808 		} else {
1809 			free(*ap->a_cookies, M_TEMP);
1810 			*ap->a_ncookies = 0;
1811 			*ap->a_cookies = NULL;
1812 		}
1813 	}
1814 	if (err == 0 && tresid == uio->uio_resid)
1815 		*ap->a_eofflag = 1;
1816 
1817 	return err;
1818 }
1819 
1820 /*
1821     struct vnop_readlink_args {
1822 	struct vnode *a_vp;
1823 	struct uio *a_uio;
1824 	struct ucred *a_cred;
1825     };
1826 */
1827 static int
1828 fuse_vnop_readlink(struct vop_readlink_args *ap)
1829 {
1830 	struct vnode *vp = ap->a_vp;
1831 	struct uio *uio = ap->a_uio;
1832 	struct ucred *cred = ap->a_cred;
1833 
1834 	struct fuse_dispatcher fdi;
1835 	int err;
1836 
1837 	if (fuse_isdeadfs(vp)) {
1838 		return ENXIO;
1839 	}
1840 	if (!vnode_islnk(vp)) {
1841 		return EINVAL;
1842 	}
1843 	fdisp_init(&fdi, 0);
1844 	err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred);
1845 	if (err) {
1846 		goto out;
1847 	}
1848 	if (((char *)fdi.answ)[0] == '/' &&
1849 	    fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_PUSH_SYMLINKS_IN) {
1850 		char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname;
1851 
1852 		err = uiomove(mpth, strlen(mpth), uio);
1853 	}
1854 	if (!err) {
1855 		err = uiomove(fdi.answ, fdi.iosize, uio);
1856 	}
1857 out:
1858 	fdisp_destroy(&fdi);
1859 	return err;
1860 }
1861 
1862 /*
1863     struct vnop_reclaim_args {
1864 	struct vnode *a_vp;
1865     };
1866 */
1867 static int
1868 fuse_vnop_reclaim(struct vop_reclaim_args *ap)
1869 {
1870 	struct vnode *vp = ap->a_vp;
1871 	struct thread *td = curthread;
1872 	struct fuse_vnode_data *fvdat = VTOFUD(vp);
1873 	struct fuse_filehandle *fufh, *fufh_tmp;
1874 
1875 	if (!fvdat) {
1876 		panic("FUSE: no vnode data during recycling");
1877 	}
1878 	LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) {
1879 		printf("FUSE: vnode being reclaimed with open fufh "
1880 			"(type=%#x)", fufh->fufh_type);
1881 		fuse_filehandle_close(vp, fufh, td, NULL);
1882 	}
1883 
1884 	if (!fuse_isdeadfs(vp) && fvdat->nlookup > 0) {
1885 		fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp),
1886 		    fvdat->nlookup);
1887 	}
1888 	cache_purge(vp);
1889 	vfs_hash_remove(vp);
1890 	fuse_vnode_destroy(vp);
1891 
1892 	return 0;
1893 }
1894 
1895 /*
1896     struct vnop_remove_args {
1897 	struct vnode *a_dvp;
1898 	struct vnode *a_vp;
1899 	struct componentname *a_cnp;
1900     };
1901 */
1902 static int
1903 fuse_vnop_remove(struct vop_remove_args *ap)
1904 {
1905 	struct vnode *dvp = ap->a_dvp;
1906 	struct vnode *vp = ap->a_vp;
1907 	struct componentname *cnp = ap->a_cnp;
1908 
1909 	int err;
1910 
1911 	if (fuse_isdeadfs(vp)) {
1912 		return ENXIO;
1913 	}
1914 	if (vnode_isdir(vp)) {
1915 		return EPERM;
1916 	}
1917 
1918 	err = fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK);
1919 
1920 	return err;
1921 }
1922 
1923 /*
1924     struct vnop_rename_args {
1925 	struct vnode *a_fdvp;
1926 	struct vnode *a_fvp;
1927 	struct componentname *a_fcnp;
1928 	struct vnode *a_tdvp;
1929 	struct vnode *a_tvp;
1930 	struct componentname *a_tcnp;
1931     };
1932 */
1933 static int
1934 fuse_vnop_rename(struct vop_rename_args *ap)
1935 {
1936 	struct vnode *fdvp = ap->a_fdvp;
1937 	struct vnode *fvp = ap->a_fvp;
1938 	struct componentname *fcnp = ap->a_fcnp;
1939 	struct vnode *tdvp = ap->a_tdvp;
1940 	struct vnode *tvp = ap->a_tvp;
1941 	struct componentname *tcnp = ap->a_tcnp;
1942 	struct fuse_data *data;
1943 	bool newparent = fdvp != tdvp;
1944 	bool isdir = fvp->v_type == VDIR;
1945 	int err = 0;
1946 
1947 	if (fuse_isdeadfs(fdvp)) {
1948 		return ENXIO;
1949 	}
1950 	if (fvp->v_mount != tdvp->v_mount ||
1951 	    (tvp && fvp->v_mount != tvp->v_mount)) {
1952 		SDT_PROBE2(fusefs, , vnops, trace, 1, "cross-device rename");
1953 		err = EXDEV;
1954 		goto out;
1955 	}
1956 	cache_purge(fvp);
1957 
1958 	/*
1959 	 * FUSE library is expected to check if target directory is not
1960 	 * under the source directory in the file system tree.
1961 	 * Linux performs this check at VFS level.
1962 	 */
1963 	/*
1964 	 * If source is a directory, and it will get a new parent, user must
1965 	 * have write permission to it, so ".." can be modified.
1966 	 */
1967 	data = fuse_get_mpdata(vnode_mount(tdvp));
1968 	if (data->dataflags & FSESS_DEFAULT_PERMISSIONS && isdir && newparent) {
1969 		err = fuse_internal_access(fvp, VWRITE,
1970 			curthread, tcnp->cn_cred);
1971 		if (err)
1972 			goto out;
1973 	}
1974 	sx_xlock(&data->rename_lock);
1975 	err = fuse_internal_rename(fdvp, fcnp, tdvp, tcnp);
1976 	if (err == 0) {
1977 		if (tdvp != fdvp)
1978 			fuse_vnode_setparent(fvp, tdvp);
1979 		if (tvp != NULL)
1980 			fuse_vnode_setparent(tvp, NULL);
1981 	}
1982 	sx_unlock(&data->rename_lock);
1983 
1984 	if (tvp != NULL && tvp != fvp) {
1985 		cache_purge(tvp);
1986 	}
1987 	if (vnode_isdir(fvp)) {
1988 		if ((tvp != NULL) && vnode_isdir(tvp)) {
1989 			cache_purge(tdvp);
1990 		}
1991 		cache_purge(fdvp);
1992 	}
1993 out:
1994 	if (tdvp == tvp) {
1995 		vrele(tdvp);
1996 	} else {
1997 		vput(tdvp);
1998 	}
1999 	if (tvp != NULL) {
2000 		vput(tvp);
2001 	}
2002 	vrele(fdvp);
2003 	vrele(fvp);
2004 
2005 	return err;
2006 }
2007 
2008 /*
2009     struct vnop_rmdir_args {
2010 	    struct vnode *a_dvp;
2011 	    struct vnode *a_vp;
2012 	    struct componentname *a_cnp;
2013     } *ap;
2014 */
2015 static int
2016 fuse_vnop_rmdir(struct vop_rmdir_args *ap)
2017 {
2018 	struct vnode *dvp = ap->a_dvp;
2019 	struct vnode *vp = ap->a_vp;
2020 
2021 	int err;
2022 
2023 	if (fuse_isdeadfs(vp)) {
2024 		return ENXIO;
2025 	}
2026 	if (VTOFUD(vp) == VTOFUD(dvp)) {
2027 		return EINVAL;
2028 	}
2029 	err = fuse_internal_remove(dvp, vp, ap->a_cnp, FUSE_RMDIR);
2030 
2031 	return err;
2032 }
2033 
2034 /*
2035     struct vnop_setattr_args {
2036 	struct vnode *a_vp;
2037 	struct vattr *a_vap;
2038 	struct ucred *a_cred;
2039 	struct thread *a_td;
2040     };
2041 */
2042 static int
2043 fuse_vnop_setattr(struct vop_setattr_args *ap)
2044 {
2045 	struct vnode *vp = ap->a_vp;
2046 	struct vattr *vap = ap->a_vap;
2047 	struct ucred *cred = ap->a_cred;
2048 	struct thread *td = curthread;
2049 	struct mount *mp;
2050 	struct fuse_data *data;
2051 	struct vattr old_va;
2052 	int dataflags;
2053 	int err = 0, err2;
2054 	accmode_t accmode = 0;
2055 	bool checkperm;
2056 	bool drop_suid = false;
2057 	gid_t cr_gid;
2058 
2059 	mp = vnode_mount(vp);
2060 	data = fuse_get_mpdata(mp);
2061 	dataflags = data->dataflags;
2062 	checkperm = dataflags & FSESS_DEFAULT_PERMISSIONS;
2063 	if (cred->cr_ngroups > 0)
2064 		cr_gid = cred->cr_groups[0];
2065 	else
2066 		cr_gid = 0;
2067 
2068 	if (fuse_isdeadfs(vp)) {
2069 		return ENXIO;
2070 	}
2071 
2072 	if (vap->va_uid != (uid_t)VNOVAL) {
2073 		if (checkperm) {
2074 			/* Only root may change a file's owner */
2075 			err = priv_check_cred(cred, PRIV_VFS_CHOWN);
2076 			if (err) {
2077 				/* As a special case, allow the null chown */
2078 				err2 = fuse_internal_getattr(vp, &old_va, cred,
2079 					td);
2080 				if (err2)
2081 					return (err2);
2082 				if (vap->va_uid != old_va.va_uid)
2083 					return err;
2084 				else
2085 					accmode |= VADMIN;
2086 				drop_suid = true;
2087 			} else
2088 				accmode |= VADMIN;
2089 		} else
2090 			accmode |= VADMIN;
2091 	}
2092 	if (vap->va_gid != (gid_t)VNOVAL) {
2093 		if (checkperm && priv_check_cred(cred, PRIV_VFS_CHOWN))
2094 			drop_suid = true;
2095 		if (checkperm && !groupmember(vap->va_gid, cred))
2096 		{
2097 			/*
2098 			 * Non-root users may only chgrp to one of their own
2099 			 * groups
2100 			 */
2101 			err = priv_check_cred(cred, PRIV_VFS_CHOWN);
2102 			if (err) {
2103 				/* As a special case, allow the null chgrp */
2104 				err2 = fuse_internal_getattr(vp, &old_va, cred,
2105 					td);
2106 				if (err2)
2107 					return (err2);
2108 				if (vap->va_gid != old_va.va_gid)
2109 					return err;
2110 				accmode |= VADMIN;
2111 			} else
2112 				accmode |= VADMIN;
2113 		} else
2114 			accmode |= VADMIN;
2115 	}
2116 	if (vap->va_size != VNOVAL) {
2117 		switch (vp->v_type) {
2118 		case VDIR:
2119 			return (EISDIR);
2120 		case VLNK:
2121 		case VREG:
2122 			if (vfs_isrdonly(mp))
2123 				return (EROFS);
2124 			break;
2125 		default:
2126 			/*
2127 			 * According to POSIX, the result is unspecified
2128 			 * for file types other than regular files,
2129 			 * directories and shared memory objects.  We
2130 			 * don't support shared memory objects in the file
2131 			 * system, and have dubious support for truncating
2132 			 * symlinks.  Just ignore the request in other cases.
2133 			 */
2134 			return (0);
2135 		}
2136 		/* Don't set accmode.  Permission to trunc is checked upstack */
2137 	}
2138 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
2139 		if (vap->va_vaflags & VA_UTIMES_NULL)
2140 			accmode |= VWRITE;
2141 		else
2142 			accmode |= VADMIN;
2143 	}
2144 	if (drop_suid) {
2145 		if (vap->va_mode != (mode_t)VNOVAL)
2146 			vap->va_mode &= ~(S_ISUID | S_ISGID);
2147 		else {
2148 			err = fuse_internal_getattr(vp, &old_va, cred, td);
2149 			if (err)
2150 				return (err);
2151 			vap->va_mode = old_va.va_mode & ~(S_ISUID | S_ISGID);
2152 		}
2153 	}
2154 	if (vap->va_mode != (mode_t)VNOVAL) {
2155 		/* Only root may set the sticky bit on non-directories */
2156 		if (checkperm && vp->v_type != VDIR && (vap->va_mode & S_ISTXT)
2157 		    && priv_check_cred(cred, PRIV_VFS_STICKYFILE))
2158 			return EFTYPE;
2159 		if (checkperm && (vap->va_mode & S_ISGID)) {
2160 			err = fuse_internal_getattr(vp, &old_va, cred, td);
2161 			if (err)
2162 				return (err);
2163 			if (!groupmember(old_va.va_gid, cred)) {
2164 				err = priv_check_cred(cred, PRIV_VFS_SETGID);
2165 				if (err)
2166 					return (err);
2167 			}
2168 		}
2169 		accmode |= VADMIN;
2170 	}
2171 
2172 	if (vfs_isrdonly(mp))
2173 		return EROFS;
2174 
2175 	if (checkperm) {
2176 		err = fuse_internal_access(vp, accmode, td, cred);
2177 	} else {
2178 		err = 0;
2179 	}
2180 	if (err)
2181 		return err;
2182 	else
2183 		return fuse_internal_setattr(vp, vap, td, cred);
2184 }
2185 
2186 /*
2187     struct vnop_strategy_args {
2188 	struct vnode *a_vp;
2189 	struct buf *a_bp;
2190     };
2191 */
2192 static int
2193 fuse_vnop_strategy(struct vop_strategy_args *ap)
2194 {
2195 	struct vnode *vp = ap->a_vp;
2196 	struct buf *bp = ap->a_bp;
2197 
2198 	if (!vp || fuse_isdeadfs(vp)) {
2199 		bp->b_ioflags |= BIO_ERROR;
2200 		bp->b_error = ENXIO;
2201 		bufdone(bp);
2202 		return 0;
2203 	}
2204 
2205 	/*
2206 	 * VOP_STRATEGY always returns zero and signals error via bp->b_ioflags.
2207 	 * fuse_io_strategy sets bp's error fields
2208 	 */
2209 	(void)fuse_io_strategy(vp, bp);
2210 
2211 	return 0;
2212 }
2213 
2214 /*
2215     struct vnop_symlink_args {
2216 	struct vnode *a_dvp;
2217 	struct vnode **a_vpp;
2218 	struct componentname *a_cnp;
2219 	struct vattr *a_vap;
2220 	char *a_target;
2221     };
2222 */
2223 static int
2224 fuse_vnop_symlink(struct vop_symlink_args *ap)
2225 {
2226 	struct vnode *dvp = ap->a_dvp;
2227 	struct vnode **vpp = ap->a_vpp;
2228 	struct componentname *cnp = ap->a_cnp;
2229 	const char *target = ap->a_target;
2230 
2231 	struct fuse_dispatcher fdi;
2232 
2233 	int err;
2234 	size_t len;
2235 
2236 	if (fuse_isdeadfs(dvp)) {
2237 		return ENXIO;
2238 	}
2239 	/*
2240 	 * Unlike the other creator type calls, here we have to create a message
2241 	 * where the name of the new entry comes first, and the data describing
2242 	 * the entry comes second.
2243 	 * Hence we can't rely on our handy fuse_internal_newentry() routine,
2244 	 * but put together the message manually and just call the core part.
2245 	 */
2246 
2247 	len = strlen(target) + 1;
2248 	fdisp_init(&fdi, len + cnp->cn_namelen + 1);
2249 	fdisp_make_vp(&fdi, FUSE_SYMLINK, dvp, curthread, NULL);
2250 
2251 	memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen);
2252 	((char *)fdi.indata)[cnp->cn_namelen] = '\0';
2253 	memcpy((char *)fdi.indata + cnp->cn_namelen + 1, target, len);
2254 
2255 	err = fuse_internal_newentry_core(dvp, vpp, cnp, VLNK, &fdi);
2256 	fdisp_destroy(&fdi);
2257 	return err;
2258 }
2259 
2260 /*
2261     struct vnop_write_args {
2262 	struct vnode *a_vp;
2263 	struct uio *a_uio;
2264 	int  a_ioflag;
2265 	struct ucred *a_cred;
2266     };
2267 */
2268 static int
2269 fuse_vnop_write(struct vop_write_args *ap)
2270 {
2271 	struct vnode *vp = ap->a_vp;
2272 	struct uio *uio = ap->a_uio;
2273 	int ioflag = ap->a_ioflag;
2274 	struct ucred *cred = ap->a_cred;
2275 	pid_t pid = curthread->td_proc->p_pid;
2276 	struct fuse_filehandle *fufh;
2277 	int err;
2278 	bool closefufh = false, directio;
2279 
2280 	MPASS(vp->v_type == VREG || vp->v_type == VDIR);
2281 
2282 	if (fuse_isdeadfs(vp)) {
2283 		return ENXIO;
2284 	}
2285 
2286 	if (VTOFUD(vp)->flag & FN_DIRECTIO) {
2287 		ioflag |= IO_DIRECT;
2288 	}
2289 
2290 	err = fuse_filehandle_getrw(vp, FWRITE, &fufh, cred, pid);
2291 	if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) {
2292 		/*
2293 		 * nfsd will do I/O without first doing VOP_OPEN.  We
2294 		 * must implicitly open the file here
2295 		 */
2296 		err = fuse_filehandle_open(vp, FWRITE, &fufh, curthread, cred);
2297 		closefufh = true;
2298 	}
2299 	if (err) {
2300 		SDT_PROBE3(fusefs, , vnops, filehandles_closed, vp, uio, cred);
2301 		return err;
2302 	}
2303 
2304 	/*
2305          * Ideally, when the daemon asks for direct io at open time, the
2306          * standard file flag should be set according to this, so that would
2307          * just change the default mode, which later on could be changed via
2308          * fcntl(2).
2309          * But this doesn't work, the O_DIRECT flag gets cleared at some point
2310          * (don't know where). So to make any use of the Fuse direct_io option,
2311          * we hardwire it into the file's private data (similarly to Linux,
2312          * btw.).
2313          */
2314 	directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp));
2315 
2316 	fuse_vnode_update(vp, FN_MTIMECHANGE | FN_CTIMECHANGE);
2317 	if (directio) {
2318 		off_t start, end, filesize;
2319 		bool pages = (ioflag & IO_VMIO) != 0;
2320 
2321 		SDT_PROBE2(fusefs, , vnops, trace, 1, "direct write of vnode");
2322 
2323 		err = fuse_vnode_size(vp, &filesize, cred, curthread);
2324 		if (err)
2325 			goto out;
2326 
2327 		start = uio->uio_offset;
2328 		end = start + uio->uio_resid;
2329 		if (!pages) {
2330 			err = fuse_inval_buf_range(vp, filesize, start,
2331 			    end);
2332 			if (err)
2333 				goto out;
2334 		}
2335 		err = fuse_write_directbackend(vp, uio, cred, fufh,
2336 			filesize, ioflag, pages);
2337 	} else {
2338 		SDT_PROBE2(fusefs, , vnops, trace, 1,
2339 			"buffered write of vnode");
2340 		if (!fsess_opt_writeback(vnode_mount(vp)))
2341 			ioflag |= IO_SYNC;
2342 		err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag, pid);
2343 	}
2344 	fuse_internal_clear_suid_on_write(vp, cred, uio->uio_td);
2345 
2346 out:
2347 	if (closefufh)
2348 		fuse_filehandle_close(vp, fufh, curthread, cred);
2349 
2350 	return (err);
2351 }
2352 
2353 static daddr_t
2354 fuse_gbp_getblkno(struct vnode *vp, vm_ooffset_t off)
2355 {
2356 	const int biosize = fuse_iosize(vp);
2357 
2358 	return (off / biosize);
2359 }
2360 
2361 static int
2362 fuse_gbp_getblksz(struct vnode *vp, daddr_t lbn, long *blksz)
2363 {
2364 	off_t filesize;
2365 	int err;
2366 	const int biosize = fuse_iosize(vp);
2367 
2368 	err = fuse_vnode_size(vp, &filesize, NULL, NULL);
2369 	if (err) {
2370 		/* This will turn into a SIGBUS */
2371 		return (EIO);
2372 	} else if ((off_t)lbn * biosize >= filesize) {
2373 		*blksz = 0;
2374 	} else if ((off_t)(lbn + 1) * biosize > filesize) {
2375 		*blksz = filesize - (off_t)lbn *biosize;
2376 	} else {
2377 		*blksz = biosize;
2378 	}
2379 	return (0);
2380 }
2381 
2382 /*
2383     struct vnop_getpages_args {
2384 	struct vnode *a_vp;
2385 	vm_page_t *a_m;
2386 	int a_count;
2387 	int a_reqpage;
2388     };
2389 */
2390 static int
2391 fuse_vnop_getpages(struct vop_getpages_args *ap)
2392 {
2393 	struct vnode *vp = ap->a_vp;
2394 
2395 	if (!fsess_opt_mmap(vnode_mount(vp))) {
2396 		SDT_PROBE2(fusefs, , vnops, trace, 1,
2397 			"called on non-cacheable vnode??\n");
2398 		return (VM_PAGER_ERROR);
2399 	}
2400 
2401 	return (vfs_bio_getpages(vp, ap->a_m, ap->a_count, ap->a_rbehind,
2402 	    ap->a_rahead, fuse_gbp_getblkno, fuse_gbp_getblksz));
2403 }
2404 
2405 static const char extattr_namespace_separator = '.';
2406 
2407 /*
2408     struct vop_getextattr_args {
2409 	struct vop_generic_args a_gen;
2410 	struct vnode *a_vp;
2411 	int a_attrnamespace;
2412 	const char *a_name;
2413 	struct uio *a_uio;
2414 	size_t *a_size;
2415 	struct ucred *a_cred;
2416 	struct thread *a_td;
2417     };
2418 */
2419 static int
2420 fuse_vnop_getextattr(struct vop_getextattr_args *ap)
2421 {
2422 	struct vnode *vp = ap->a_vp;
2423 	struct uio *uio = ap->a_uio;
2424 	struct fuse_dispatcher fdi;
2425 	struct fuse_getxattr_in *get_xattr_in;
2426 	struct fuse_getxattr_out *get_xattr_out;
2427 	struct mount *mp = vnode_mount(vp);
2428 	struct thread *td = ap->a_td;
2429 	struct ucred *cred = ap->a_cred;
2430 	char *prefix;
2431 	char *attr_str;
2432 	size_t len;
2433 	int err;
2434 
2435 	if (fuse_isdeadfs(vp))
2436 		return (ENXIO);
2437 
2438 	if (fsess_not_impl(mp, FUSE_GETXATTR))
2439 		return EOPNOTSUPP;
2440 
2441 	err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD);
2442 	if (err)
2443 		return err;
2444 
2445 	/* Default to looking for user attributes. */
2446 	if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2447 		prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2448 	else
2449 		prefix = EXTATTR_NAMESPACE_USER_STRING;
2450 
2451 	len = strlen(prefix) + sizeof(extattr_namespace_separator) +
2452 	    strlen(ap->a_name) + 1;
2453 
2454 	fdisp_init(&fdi, len + sizeof(*get_xattr_in));
2455 	fdisp_make_vp(&fdi, FUSE_GETXATTR, vp, td, cred);
2456 
2457 	get_xattr_in = fdi.indata;
2458 	/*
2459 	 * Check to see whether we're querying the available size or
2460 	 * issuing the actual request.  If we pass in 0, we get back struct
2461 	 * fuse_getxattr_out.  If we pass in a non-zero size, we get back
2462 	 * that much data, without the struct fuse_getxattr_out header.
2463 	 */
2464 	if (uio == NULL)
2465 		get_xattr_in->size = 0;
2466 	else
2467 		get_xattr_in->size = uio->uio_resid;
2468 
2469 	attr_str = (char *)fdi.indata + sizeof(*get_xattr_in);
2470 	snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator,
2471 	    ap->a_name);
2472 
2473 	err = fdisp_wait_answ(&fdi);
2474 	if (err != 0) {
2475 		if (err == ENOSYS) {
2476 			fsess_set_notimpl(mp, FUSE_GETXATTR);
2477 			err = EOPNOTSUPP;
2478 		}
2479 		goto out;
2480 	}
2481 
2482 	get_xattr_out = fdi.answ;
2483 
2484 	if (ap->a_size != NULL)
2485 		*ap->a_size = get_xattr_out->size;
2486 
2487 	if (uio != NULL)
2488 		err = uiomove(fdi.answ, fdi.iosize, uio);
2489 
2490 out:
2491 	fdisp_destroy(&fdi);
2492 	return (err);
2493 }
2494 
2495 /*
2496     struct vop_setextattr_args {
2497 	struct vop_generic_args a_gen;
2498 	struct vnode *a_vp;
2499 	int a_attrnamespace;
2500 	const char *a_name;
2501 	struct uio *a_uio;
2502 	struct ucred *a_cred;
2503 	struct thread *a_td;
2504     };
2505 */
2506 static int
2507 fuse_vnop_setextattr(struct vop_setextattr_args *ap)
2508 {
2509 	struct vnode *vp = ap->a_vp;
2510 	struct uio *uio = ap->a_uio;
2511 	struct fuse_dispatcher fdi;
2512 	struct fuse_setxattr_in *set_xattr_in;
2513 	struct mount *mp = vnode_mount(vp);
2514 	struct thread *td = ap->a_td;
2515 	struct ucred *cred = ap->a_cred;
2516 	char *prefix;
2517 	size_t len;
2518 	char *attr_str;
2519 	int err;
2520 
2521 	if (fuse_isdeadfs(vp))
2522 		return (ENXIO);
2523 
2524 	if (fsess_not_impl(mp, FUSE_SETXATTR))
2525 		return EOPNOTSUPP;
2526 
2527 	if (vfs_isrdonly(mp))
2528 		return EROFS;
2529 
2530 	/* Deleting xattrs must use VOP_DELETEEXTATTR instead */
2531 	if (ap->a_uio == NULL) {
2532 		/*
2533 		 * If we got here as fallback from VOP_DELETEEXTATTR, then
2534 		 * return EOPNOTSUPP.
2535 		 */
2536 		if (fsess_not_impl(mp, FUSE_REMOVEXATTR))
2537 			return (EOPNOTSUPP);
2538 		else
2539 			return (EINVAL);
2540 	}
2541 
2542 	err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td,
2543 		VWRITE);
2544 	if (err)
2545 		return err;
2546 
2547 	/* Default to looking for user attributes. */
2548 	if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2549 		prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2550 	else
2551 		prefix = EXTATTR_NAMESPACE_USER_STRING;
2552 
2553 	len = strlen(prefix) + sizeof(extattr_namespace_separator) +
2554 	    strlen(ap->a_name) + 1;
2555 
2556 	fdisp_init(&fdi, len + sizeof(*set_xattr_in) + uio->uio_resid);
2557 	fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, td, cred);
2558 
2559 	set_xattr_in = fdi.indata;
2560 	set_xattr_in->size = uio->uio_resid;
2561 
2562 	attr_str = (char *)fdi.indata + sizeof(*set_xattr_in);
2563 	snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator,
2564 	    ap->a_name);
2565 
2566 	err = uiomove((char *)fdi.indata + sizeof(*set_xattr_in) + len,
2567 	    uio->uio_resid, uio);
2568 	if (err != 0) {
2569 		goto out;
2570 	}
2571 
2572 	err = fdisp_wait_answ(&fdi);
2573 
2574 	if (err == ENOSYS) {
2575 		fsess_set_notimpl(mp, FUSE_SETXATTR);
2576 		err = EOPNOTSUPP;
2577 	}
2578 	if (err == ERESTART) {
2579 		/* Can't restart after calling uiomove */
2580 		err = EINTR;
2581 	}
2582 
2583 out:
2584 	fdisp_destroy(&fdi);
2585 	return (err);
2586 }
2587 
2588 /*
2589  * The Linux / FUSE extended attribute list is simply a collection of
2590  * NUL-terminated strings.  The FreeBSD extended attribute list is a single
2591  * byte length followed by a non-NUL terminated string.  So, this allows
2592  * conversion of the Linux / FUSE format to the FreeBSD format in place.
2593  * Linux attribute names are reported with the namespace as a prefix (e.g.
2594  * "user.attribute_name"), but in FreeBSD they are reported without the
2595  * namespace prefix (e.g. "attribute_name").  So, we're going from:
2596  *
2597  * user.attr_name1\0user.attr_name2\0
2598  *
2599  * to:
2600  *
2601  * <num>attr_name1<num>attr_name2
2602  *
2603  * Where "<num>" is a single byte number of characters in the attribute name.
2604  *
2605  * Args:
2606  * prefix - exattr namespace prefix string
2607  * list, list_len - input list with namespace prefixes
2608  * bsd_list, bsd_list_len - output list compatible with bsd vfs
2609  */
2610 static int
2611 fuse_xattrlist_convert(char *prefix, const char *list, int list_len,
2612     char *bsd_list, int *bsd_list_len)
2613 {
2614 	int len, pos, dist_to_next, prefix_len;
2615 
2616 	pos = 0;
2617 	*bsd_list_len = 0;
2618 	prefix_len = strlen(prefix);
2619 
2620 	while (pos < list_len && list[pos] != '\0') {
2621 		dist_to_next = strlen(&list[pos]) + 1;
2622 		if (bcmp(&list[pos], prefix, prefix_len) == 0 &&
2623 		    list[pos + prefix_len] == extattr_namespace_separator) {
2624 			len = dist_to_next -
2625 			    (prefix_len + sizeof(extattr_namespace_separator)) - 1;
2626 			if (len >= EXTATTR_MAXNAMELEN)
2627 				return (ENAMETOOLONG);
2628 
2629 			bsd_list[*bsd_list_len] = len;
2630 			memcpy(&bsd_list[*bsd_list_len + 1],
2631 			    &list[pos + prefix_len +
2632 			    sizeof(extattr_namespace_separator)], len);
2633 
2634 			*bsd_list_len += len + 1;
2635 		}
2636 
2637 		pos += dist_to_next;
2638 	}
2639 
2640 	return (0);
2641 }
2642 
2643 /*
2644  * List extended attributes
2645  *
2646  * The FUSE_LISTXATTR operation is based on Linux's listxattr(2) syscall, which
2647  * has a number of differences compared to its FreeBSD equivalent,
2648  * extattr_list_file:
2649  *
2650  * - FUSE_LISTXATTR returns all extended attributes across all namespaces,
2651  *   whereas listxattr(2) only returns attributes for a single namespace
2652  * - FUSE_LISTXATTR prepends each attribute name with "namespace."
2653  * - If the provided buffer is not large enough to hold the result,
2654  *   FUSE_LISTXATTR should return ERANGE, whereas listxattr is expected to
2655  *   return as many results as will fit.
2656  */
2657 /*
2658     struct vop_listextattr_args {
2659 	struct vop_generic_args a_gen;
2660 	struct vnode *a_vp;
2661 	int a_attrnamespace;
2662 	struct uio *a_uio;
2663 	size_t *a_size;
2664 	struct ucred *a_cred;
2665 	struct thread *a_td;
2666     };
2667 */
2668 static int
2669 fuse_vnop_listextattr(struct vop_listextattr_args *ap)
2670 {
2671 	struct vnode *vp = ap->a_vp;
2672 	struct uio *uio = ap->a_uio;
2673 	struct fuse_dispatcher fdi;
2674 	struct fuse_listxattr_in *list_xattr_in;
2675 	struct fuse_listxattr_out *list_xattr_out;
2676 	struct mount *mp = vnode_mount(vp);
2677 	struct thread *td = ap->a_td;
2678 	struct ucred *cred = ap->a_cred;
2679 	char *prefix;
2680 	char *bsd_list = NULL;
2681 	char *linux_list;
2682 	int bsd_list_len;
2683 	int linux_list_len;
2684 	int err;
2685 
2686 	if (fuse_isdeadfs(vp))
2687 		return (ENXIO);
2688 
2689 	if (fsess_not_impl(mp, FUSE_LISTXATTR))
2690 		return EOPNOTSUPP;
2691 
2692 	err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD);
2693 	if (err)
2694 		return err;
2695 
2696 	/*
2697 	 * Add space for a NUL and the period separator if enabled.
2698 	 * Default to looking for user attributes.
2699 	 */
2700 	if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2701 		prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2702 	else
2703 		prefix = EXTATTR_NAMESPACE_USER_STRING;
2704 
2705 	fdisp_init(&fdi, sizeof(*list_xattr_in));
2706 	fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred);
2707 
2708 	/*
2709 	 * Retrieve Linux / FUSE compatible list size.
2710 	 */
2711 	list_xattr_in = fdi.indata;
2712 	list_xattr_in->size = 0;
2713 
2714 	err = fdisp_wait_answ(&fdi);
2715 	if (err != 0) {
2716 		if (err == ENOSYS) {
2717 			fsess_set_notimpl(mp, FUSE_LISTXATTR);
2718 			err = EOPNOTSUPP;
2719 		}
2720 		goto out;
2721 	}
2722 
2723 	list_xattr_out = fdi.answ;
2724 	linux_list_len = list_xattr_out->size;
2725 	if (linux_list_len == 0) {
2726 		if (ap->a_size != NULL)
2727 			*ap->a_size = linux_list_len;
2728 		goto out;
2729 	}
2730 
2731 	/*
2732 	 * Retrieve Linux / FUSE compatible list values.
2733 	 */
2734 	fdisp_refresh_vp(&fdi, FUSE_LISTXATTR, vp, td, cred);
2735 	list_xattr_in = fdi.indata;
2736 	list_xattr_in->size = linux_list_len;
2737 
2738 	err = fdisp_wait_answ(&fdi);
2739 	if (err == ERANGE) {
2740 		/*
2741 		 * Race detected.  The attribute list must've grown since the
2742 		 * first FUSE_LISTXATTR call.  Start over.  Go all the way back
2743 		 * to userland so we can process signals, if necessary, before
2744 		 * restarting.
2745 		 */
2746 		err = ERESTART;
2747 		goto out;
2748 	} else if (err != 0)
2749 		goto out;
2750 
2751 	linux_list = fdi.answ;
2752 	/* FUSE doesn't allow the server to return more data than requested */
2753 	if (fdi.iosize > linux_list_len) {
2754 		struct fuse_data *data = fuse_get_mpdata(mp);
2755 
2756 		fuse_warn(data, FSESS_WARN_LSEXTATTR_LONG,
2757 			"server returned "
2758 			"more extended attribute data than requested; "
2759 			"should've returned ERANGE instead.");
2760 	} else {
2761 		/* But returning less data is fine */
2762 		linux_list_len = fdi.iosize;
2763 	}
2764 
2765 	/*
2766 	 * Retrieve the BSD compatible list values.
2767 	 * The Linux / FUSE attribute list format isn't the same
2768 	 * as FreeBSD's format. So we need to transform it into
2769 	 * FreeBSD's format before giving it to the user.
2770 	 */
2771 	bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK);
2772 	err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len,
2773 	    bsd_list, &bsd_list_len);
2774 	if (err != 0)
2775 		goto out;
2776 
2777 	if (ap->a_size != NULL)
2778 		*ap->a_size = bsd_list_len;
2779 
2780 	if (uio != NULL)
2781 		err = uiomove(bsd_list, bsd_list_len, uio);
2782 
2783 out:
2784 	free(bsd_list, M_TEMP);
2785 	fdisp_destroy(&fdi);
2786 	return (err);
2787 }
2788 
2789 /*
2790     struct vop_deleteextattr_args {
2791 	struct vop_generic_args a_gen;
2792 	struct vnode *a_vp;
2793 	int a_attrnamespace;
2794 	const char *a_name;
2795 	struct ucred *a_cred;
2796 	struct thread *a_td;
2797     };
2798 */
2799 static int
2800 fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap)
2801 {
2802 	struct vnode *vp = ap->a_vp;
2803 	struct fuse_dispatcher fdi;
2804 	struct mount *mp = vnode_mount(vp);
2805 	struct thread *td = ap->a_td;
2806 	struct ucred *cred = ap->a_cred;
2807 	char *prefix;
2808 	size_t len;
2809 	char *attr_str;
2810 	int err;
2811 
2812 	if (fuse_isdeadfs(vp))
2813 		return (ENXIO);
2814 
2815 	if (fsess_not_impl(mp, FUSE_REMOVEXATTR))
2816 		return EOPNOTSUPP;
2817 
2818 	if (vfs_isrdonly(mp))
2819 		return EROFS;
2820 
2821 	err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td,
2822 		VWRITE);
2823 	if (err)
2824 		return err;
2825 
2826 	/* Default to looking for user attributes. */
2827 	if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2828 		prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2829 	else
2830 		prefix = EXTATTR_NAMESPACE_USER_STRING;
2831 
2832 	len = strlen(prefix) + sizeof(extattr_namespace_separator) +
2833 	    strlen(ap->a_name) + 1;
2834 
2835 	fdisp_init(&fdi, len);
2836 	fdisp_make_vp(&fdi, FUSE_REMOVEXATTR, vp, td, cred);
2837 
2838 	attr_str = fdi.indata;
2839 	snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator,
2840 	    ap->a_name);
2841 
2842 	err = fdisp_wait_answ(&fdi);
2843 	if (err == ENOSYS) {
2844 		fsess_set_notimpl(mp, FUSE_REMOVEXATTR);
2845 		err = EOPNOTSUPP;
2846 	}
2847 
2848 	fdisp_destroy(&fdi);
2849 	return (err);
2850 }
2851 
2852 /*
2853     struct vnop_print_args {
2854 	struct vnode *a_vp;
2855     };
2856 */
2857 static int
2858 fuse_vnop_print(struct vop_print_args *ap)
2859 {
2860 	struct fuse_vnode_data *fvdat = VTOFUD(ap->a_vp);
2861 
2862 	printf("nodeid: %ju, parent nodeid: %ju, nlookup: %ju, flag: %#x\n",
2863 	    (uintmax_t)VTOILLU(ap->a_vp), (uintmax_t)fvdat->parent_nid,
2864 	    (uintmax_t)fvdat->nlookup,
2865 	    fvdat->flag);
2866 
2867 	return 0;
2868 }
2869 
2870 /*
2871  * Get an NFS filehandle for a FUSE file.
2872  *
2873  * This will only work for FUSE file systems that guarantee the uniqueness of
2874  * nodeid:generation, which most don't.
2875  */
2876 /*
2877 vop_vptofh {
2878 	IN struct vnode *a_vp;
2879 	IN struct fid *a_fhp;
2880 };
2881 */
2882 static int
2883 fuse_vnop_vptofh(struct vop_vptofh_args *ap)
2884 {
2885 	struct vnode *vp = ap->a_vp;
2886 	struct fuse_vnode_data *fvdat = VTOFUD(vp);
2887 	struct fuse_fid *fhp = (struct fuse_fid *)(ap->a_fhp);
2888 	_Static_assert(sizeof(struct fuse_fid) <= sizeof(struct fid),
2889 		"FUSE fid type is too big");
2890 	struct mount *mp = vnode_mount(vp);
2891 	struct fuse_data *data = fuse_get_mpdata(mp);
2892 	struct vattr va;
2893 	int err;
2894 
2895 	if (!(data->dataflags & FSESS_EXPORT_SUPPORT))
2896 		return EOPNOTSUPP;
2897 
2898 	err = fuse_internal_getattr(vp, &va, curthread->td_ucred, curthread);
2899 	if (err)
2900 		return err;
2901 
2902 	/*ip = VTOI(ap->a_vp);*/
2903 	/*ufhp = (struct ufid *)ap->a_fhp;*/
2904 	fhp->len = sizeof(struct fuse_fid);
2905 	fhp->nid = fvdat->nid;
2906 	if (fvdat->generation <= UINT32_MAX)
2907 		fhp->gen = fvdat->generation;
2908 	else
2909 		return EOVERFLOW;
2910 	return (0);
2911 }
2912