xref: /openbsd-src/sys/miscfs/fuse/fuse_vnops.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
1 /* $OpenBSD: fuse_vnops.c,v 1.63 2021/03/24 16:11:32 semarie Exp $ */
2 /*
3  * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/dirent.h>
21 #include <sys/fcntl.h>
22 #include <sys/file.h>
23 #include <sys/lockf.h>
24 #include <sys/malloc.h>
25 #include <sys/mount.h>
26 #include <sys/namei.h>
27 #include <sys/poll.h>
28 #include <sys/proc.h>
29 #include <sys/specdev.h>
30 #include <sys/stat.h>
31 #include <sys/statvfs.h>
32 #include <sys/vnode.h>
33 #include <sys/lock.h>
34 #include <sys/fusebuf.h>
35 
36 #include "fusefs_node.h"
37 #include "fusefs.h"
38 
39 /* Prototypes for fusefs vnode ops */
40 int	fusefs_kqfilter(void *);
41 int	fusefs_lookup(void *);
42 int	fusefs_open(void *);
43 int	fusefs_close(void *);
44 int	fusefs_access(void *);
45 int	fusefs_getattr(void *);
46 int	fusefs_setattr(void *);
47 int	fusefs_ioctl(void *);
48 int	fusefs_link(void *);
49 int	fusefs_symlink(void *);
50 int	fusefs_readdir(void *);
51 int	fusefs_readlink(void *);
52 int	fusefs_inactive(void *);
53 int	fusefs_reclaim(void *);
54 int	fusefs_print(void *);
55 int	fusefs_create(void *);
56 int	fusefs_mknod(void *);
57 int	fusefs_read(void *);
58 int	fusefs_write(void *);
59 int	fusefs_poll(void *);
60 int	fusefs_remove(void *);
61 int	fusefs_rename(void *);
62 int	fusefs_mkdir(void *);
63 int	fusefs_rmdir(void *);
64 int	fusefs_strategy(void *);
65 int	fusefs_lock(void *);
66 int	fusefs_unlock(void *);
67 int	fusefs_islocked(void *);
68 int	fusefs_advlock(void *);
69 int	fusefs_fsync(void *);
70 
71 /* Prototypes for fusefs kqfilter */
72 int	filt_fusefsread(struct knote *, long);
73 int	filt_fusefswrite(struct knote *, long);
74 int	filt_fusefsvnode(struct knote *, long);
75 void	filt_fusefsdetach(struct knote *);
76 
77 const struct vops fusefs_vops = {
78 	.vop_lookup	= fusefs_lookup,
79 	.vop_create	= fusefs_create,
80 	.vop_mknod	= fusefs_mknod,
81 	.vop_open	= fusefs_open,
82 	.vop_close	= fusefs_close,
83 	.vop_access	= fusefs_access,
84 	.vop_getattr	= fusefs_getattr,
85 	.vop_setattr	= fusefs_setattr,
86 	.vop_read	= fusefs_read,
87 	.vop_write	= fusefs_write,
88 	.vop_ioctl	= fusefs_ioctl,
89 	.vop_poll	= fusefs_poll,
90 	.vop_kqfilter	= fusefs_kqfilter,
91 	.vop_revoke	= NULL,
92 	.vop_fsync	= fusefs_fsync,
93 	.vop_remove	= fusefs_remove,
94 	.vop_link	= fusefs_link,
95 	.vop_rename	= fusefs_rename,
96 	.vop_mkdir	= fusefs_mkdir,
97 	.vop_rmdir	= fusefs_rmdir,
98 	.vop_symlink	= fusefs_symlink,
99 	.vop_readdir	= fusefs_readdir,
100 	.vop_readlink	= fusefs_readlink,
101 	.vop_abortop	= vop_generic_abortop,
102 	.vop_inactive	= fusefs_inactive,
103 	.vop_reclaim	= fusefs_reclaim,
104 	.vop_lock	= fusefs_lock,
105 	.vop_unlock	= fusefs_unlock,
106 	.vop_bmap	= vop_generic_bmap,
107 	.vop_strategy	= fusefs_strategy,
108 	.vop_print	= fusefs_print,
109 	.vop_islocked	= fusefs_islocked,
110 	.vop_pathconf	= spec_pathconf,
111 	.vop_advlock	= fusefs_advlock,
112 	.vop_bwrite	= NULL,
113 };
114 
115 const struct filterops fusefsread_filtops = {
116 	.f_flags	= FILTEROP_ISFD,
117 	.f_attach	= NULL,
118 	.f_detach	= filt_fusefsdetach,
119 	.f_event	= filt_fusefsread,
120 };
121 
122 const struct filterops fusefswrite_filtops = {
123 	.f_flags	= FILTEROP_ISFD,
124 	.f_attach	= NULL,
125 	.f_detach	= filt_fusefsdetach,
126 	.f_event	= filt_fusefswrite,
127 };
128 
129 const struct filterops fusefsvnode_filtops = {
130 	.f_flags	= FILTEROP_ISFD,
131 	.f_attach	= NULL,
132 	.f_detach	= filt_fusefsdetach,
133 	.f_event	= filt_fusefsvnode,
134 };
135 
136 int
137 fusefs_kqfilter(void *v)
138 {
139 	struct vop_kqfilter_args *ap = v;
140 	struct vnode *vp = ap->a_vp;
141 	struct knote *kn = ap->a_kn;
142 
143 	switch (kn->kn_filter) {
144 	case EVFILT_READ:
145 		kn->kn_fop = &fusefsread_filtops;
146 		break;
147 	case EVFILT_WRITE:
148 		kn->kn_fop = &fusefswrite_filtops;
149 		break;
150 	case EVFILT_VNODE:
151 		kn->kn_fop = &fusefsvnode_filtops;
152 		break;
153 	default:
154 		return (EINVAL);
155 	}
156 
157 	kn->kn_hook = (caddr_t)vp;
158 
159 	klist_insert_locked(&vp->v_selectinfo.si_note, kn);
160 
161 	return (0);
162 }
163 
164 void
165 filt_fusefsdetach(struct knote *kn)
166 {
167 	struct vnode *vp = (struct vnode *)kn->kn_hook;
168 
169 	klist_remove_locked(&vp->v_selectinfo.si_note, kn);
170 }
171 
172 int
173 filt_fusefsread(struct knote *kn, long hint)
174 {
175 	struct vnode *vp = (struct vnode *)kn->kn_hook;
176 	struct fusefs_node *ip = VTOI(vp);
177 
178 	/*
179 	 * filesystem is gone, so set the EOF flag and schedule
180 	 * the knote for deletion
181 	 */
182 	if (hint == NOTE_REVOKE) {
183 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
184 		return (1);
185 	}
186 
187 	kn->kn_data = ip->filesize - foffset(kn->kn_fp);
188 	if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) {
189 		kn->kn_fflags |= NOTE_EOF;
190 		return (1);
191 	}
192 
193 	if (kn->kn_flags & __EV_POLL)
194 		return (1);
195 
196 	return (kn->kn_data != 0);
197 }
198 
199 int
200 filt_fusefswrite(struct knote *kn, long hint)
201 {
202 	/*
203 	 * filesystem is gone, so set the EOF flag and schedule
204 	 * the knote for deletion
205 	 */
206 	if (hint == NOTE_REVOKE) {
207 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
208 		return (1);
209 	}
210 
211 	kn->kn_data = 0;
212 	return (1);
213 }
214 
215 int
216 filt_fusefsvnode(struct knote *kn, long int hint)
217 {
218 	if (kn->kn_sfflags & hint)
219 		kn->kn_fflags |= hint;
220 	if (hint == NOTE_REVOKE) {
221 		kn->kn_flags |= EV_EOF;
222 		return (1);
223 	}
224 	return (kn->kn_fflags != 0);
225 }
226 
227 /*
228  * FUSE file systems can maintain a file handle for each VFS file descriptor
229  * that is opened. The OpenBSD VFS does not make file descriptors visible to
230  * us so we fake it by mapping open flags to file handles.
231  * There is no way for FUSE to know which file descriptor is being used
232  * by an application for a file operation. We only maintain 3 descriptors,
233  * one each for O_RDONLY, O_WRONLY and O_RDWR. When reading and writing, the
234  * first open descriptor is used and this may well not be the one that was set
235  * by FUSE open and may have even been opened by another application.
236  */
237 int
238 fusefs_open(void *v)
239 {
240 	struct vop_open_args *ap;
241 	struct fusefs_node *ip;
242 	struct fusefs_mnt *fmp;
243 	struct vnode *vp;
244 	enum fufh_type fufh_type = FUFH_RDONLY;
245 	int flags;
246 	int error;
247 	int isdir;
248 
249 	ap = v;
250 	vp = ap->a_vp;
251 	ip = VTOI(vp);
252 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
253 
254 	if (!fmp->sess_init)
255 		return (ENXIO);
256 
257 	isdir = 0;
258 	if (vp->v_type == VDIR)
259 		isdir = 1;
260 	else {
261 		if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE))
262 			fufh_type = FUFH_RDWR;
263 		else if (ap->a_mode & (FWRITE))
264 			fufh_type = FUFH_WRONLY;
265 
266 		/*
267 		 * Due to possible attribute caching, there is no
268 		 * reliable way to determine if the file was modified
269 		 * externally (e.g. network file system) so clear the
270 		 * UVM cache to ensure that it is not stale. The file
271 		 * can still become stale later on read but this will
272 		 * satisfy most situations.
273 		 */
274 		uvm_vnp_uncache(vp);
275 	}
276 
277 	/* already open i think all is ok */
278 	if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
279 		return (0);
280 
281 	/*
282 	 * The file has already been created and/or truncated so FUSE dictates
283 	 * that no creation and truncation flags are passed to open.
284 	 */
285 	flags = OFLAGS(ap->a_mode) & ~(O_CREAT|O_EXCL|O_TRUNC);
286 	error = fusefs_file_open(fmp, ip, fufh_type, flags, isdir, ap->a_p);
287 
288 	return (error);
289 }
290 
291 int
292 fusefs_close(void *v)
293 {
294 	struct vop_close_args *ap;
295 	struct fusefs_node *ip;
296 	struct fusefs_mnt *fmp;
297 	struct fusebuf *fbuf;
298 	enum fufh_type fufh_type = FUFH_RDONLY;
299 	int error = 0;
300 
301 	ap = v;
302 	ip = VTOI(ap->a_vp);
303 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
304 
305 	if (!fmp->sess_init)
306 		return (0);
307 
308 	/*
309 	 * The file or directory may have been opened more than once so there
310 	 * is no reliable way to determine when to ask the FUSE daemon to
311 	 * release its file descriptor. For files, ask the daemon to flush any
312 	 * buffers to disk now. All open file descriptors will be released on
313 	 * VOP_INACTIVE(9).
314 	 */
315 
316 	if (ap->a_vp->v_type == VDIR)
317 		return (0);
318 
319 	/* Implementing flush is optional so don't error. */
320 	if (fmp->undef_op & UNDEF_FLUSH)
321 		return (0);
322 
323 	/* Only flush writeable file descriptors. */
324 	if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE))
325 		fufh_type = FUFH_RDWR;
326 	else if (ap->a_fflag & (FWRITE))
327 		fufh_type = FUFH_WRONLY;
328 	else
329 		return (0);
330 
331 	if (ip->fufh[fufh_type].fh_type == FUFH_INVALID)
332 		return (EBADF);
333 
334 	fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_FLUSH, ap->a_p);
335 	fbuf->fb_io_fd = ip->fufh[fufh_type].fh_id;
336 	error = fb_queue(fmp->dev, fbuf);
337 	fb_delete(fbuf);
338 	if (error == ENOSYS) {
339 		fmp->undef_op |= UNDEF_FLUSH;
340 
341 		/* Implementing flush is optional so don't error. */
342 		return (0);
343 	}
344 
345 	return (error);
346 }
347 
348 int
349 fusefs_access(void *v)
350 {
351 	struct vop_access_args *ap;
352 	struct fusefs_node *ip;
353 	struct fusefs_mnt *fmp;
354 	struct ucred *cred;
355 	struct vattr vattr;
356 	struct proc *p;
357 	int error = 0;
358 
359 	ap = v;
360 	p = ap->a_p;
361 	cred = p->p_ucred;
362 	ip = VTOI(ap->a_vp);
363 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
364 
365 	/*
366 	 * Only user that mounted the file system can access it unless
367 	 * allow_other mount option was specified.
368 	 */
369 	if (!fmp->allow_other && cred->cr_uid != fmp->mp->mnt_stat.f_owner)
370 		return (EACCES);
371 
372 	if (!fmp->sess_init)
373 		return (ENXIO);
374 
375 	/*
376 	 * Disallow write attempts on filesystems mounted read-only;
377 	 * unless the file is a socket, fifo, or a block or character
378 	 * device resident on the filesystem.
379 	 */
380 	if ((ap->a_mode & VWRITE) && (fmp->mp->mnt_flag & MNT_RDONLY)) {
381 		switch (ap->a_vp->v_type) {
382 		case VREG:
383 		case VDIR:
384 		case VLNK:
385 			return (EROFS);
386 		default:
387 			break;
388 		}
389 	}
390 
391 	if ((error = VOP_GETATTR(ap->a_vp, &vattr, cred, p)) != 0)
392 		return (error);
393 
394 	return (vaccess(ap->a_vp->v_type, vattr.va_mode & ALLPERMS,
395 	    vattr.va_uid, vattr.va_gid, ap->a_mode,
396 	    ap->a_cred));
397 }
398 
399 int
400 fusefs_getattr(void *v)
401 {
402 	struct vop_getattr_args *ap = v;
403 	struct vnode *vp = ap->a_vp;
404 	struct fusefs_mnt *fmp;
405 	struct vattr *vap = ap->a_vap;
406 	struct proc *p = ap->a_p;
407 	struct ucred *cred = p->p_ucred;
408 	struct fusefs_node *ip;
409 	struct fusebuf *fbuf;
410 	struct stat *st;
411 	int error = 0;
412 
413 	ip = VTOI(vp);
414 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
415 
416 	/*
417 	 * Only user that mounted the file system can access it unless
418 	 * allow_other mount option was specified. Return dummy values
419 	 * for the root inode in this situation.
420 	 */
421 	if (!fmp->allow_other && cred->cr_uid != fmp->mp->mnt_stat.f_owner) {
422 		memset(vap, 0, sizeof(*vap));
423 		vap->va_type = VNON;
424 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
425 			vap->va_mode = S_IRUSR | S_IXUSR;
426 		else
427 			vap->va_mode = S_IRWXU;
428 		vap->va_nlink = 1;
429 		vap->va_uid = fmp->mp->mnt_stat.f_owner;
430 		vap->va_gid = fmp->mp->mnt_stat.f_owner;
431 		vap->va_fsid = fmp->mp->mnt_stat.f_fsid.val[0];
432 		vap->va_fileid = ip->ufs_ino.i_number;
433 		vap->va_size = S_BLKSIZE;
434 		vap->va_blocksize = S_BLKSIZE;
435 		vap->va_atime.tv_sec = fmp->mp->mnt_stat.f_ctime;
436 		vap->va_mtime.tv_sec = fmp->mp->mnt_stat.f_ctime;
437 		vap->va_ctime.tv_sec = fmp->mp->mnt_stat.f_ctime;
438 		vap->va_rdev = fmp->dev;
439 		vap->va_bytes = S_BLKSIZE;
440 		return (0);
441 	}
442 
443 	if (!fmp->sess_init)
444 		return (ENXIO);
445 
446 	fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_GETATTR, p);
447 
448 	error = fb_queue(fmp->dev, fbuf);
449 	if (error) {
450 		fb_delete(fbuf);
451 		return (error);
452 	}
453 
454 	st = &fbuf->fb_attr;
455 
456 	memset(vap, 0, sizeof(*vap));
457 	vap->va_type = IFTOVT(st->st_mode);
458 	vap->va_mode = st->st_mode & ~S_IFMT;
459 	vap->va_nlink = st->st_nlink;
460 	vap->va_uid = st->st_uid;
461 	vap->va_gid = st->st_gid;
462 	vap->va_fsid = fmp->mp->mnt_stat.f_fsid.val[0];
463 	vap->va_fileid = st->st_ino;
464 	vap->va_size = st->st_size;
465 	vap->va_blocksize = st->st_blksize;
466 	vap->va_atime = st->st_atim;
467 	vap->va_mtime = st->st_mtim;
468 	vap->va_ctime = st->st_ctim;
469 	vap->va_rdev = st->st_rdev;
470 	vap->va_bytes = st->st_blocks * S_BLKSIZE;
471 
472 	fb_delete(fbuf);
473 	return (error);
474 }
475 
476 int
477 fusefs_setattr(void *v)
478 {
479 	struct vop_setattr_args *ap = v;
480 	struct vattr *vap = ap->a_vap;
481 	struct vnode *vp = ap->a_vp;
482 	struct fusefs_node *ip = VTOI(vp);
483 	struct ucred *cred = ap->a_cred;
484 	struct proc *p = ap->a_p;
485 	struct fusefs_mnt *fmp;
486 	struct fusebuf *fbuf;
487 	struct fb_io *io;
488 	int error = 0;
489 
490 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
491 	/*
492 	 * Check for unsettable attributes.
493 	 */
494 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
495 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
496 	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
497 	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL))
498 		return (EINVAL);
499 
500 	if (!fmp->sess_init)
501 		return (ENXIO);
502 
503 	if (fmp->undef_op & UNDEF_SETATTR)
504 		return (ENOSYS);
505 
506 	fbuf = fb_setup(sizeof(*io), ip->ufs_ino.i_number, FBT_SETATTR, p);
507 	io = fbtod(fbuf, struct fb_io *);
508 	io->fi_flags = 0;
509 
510 	if (vap->va_uid != (uid_t)VNOVAL) {
511 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
512 			error = EROFS;
513 			goto out;
514 		}
515 		fbuf->fb_attr.st_uid = vap->va_uid;
516 		io->fi_flags |= FUSE_FATTR_UID;
517 	}
518 
519 	if (vap->va_gid != (gid_t)VNOVAL) {
520 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
521 			error = EROFS;
522 			goto out;
523 		}
524 		fbuf->fb_attr.st_gid = vap->va_gid;
525 		io->fi_flags |= FUSE_FATTR_GID;
526 	}
527 
528 	if (vap->va_size != VNOVAL) {
529 		/*
530 		 * Disallow write attempts on read-only file systems;
531 		 * unless the file is a socket, fifo, or a block or
532 		 * character device resident on the file system.
533 		 */
534 		switch (vp->v_type) {
535 		case VDIR:
536 			error = EISDIR;
537 			goto out;
538 		case VLNK:
539 		case VREG:
540 			if (vp->v_mount->mnt_flag & MNT_RDONLY) {
541 				error = EROFS;
542 				goto out;
543 			}
544 			break;
545 		default:
546 			break;
547 		}
548 
549 		fbuf->fb_attr.st_size = vap->va_size;
550 		io->fi_flags |= FUSE_FATTR_SIZE;
551 	}
552 
553 	if (vap->va_atime.tv_nsec != VNOVAL) {
554 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
555 			error = EROFS;
556 			goto out;
557 		}
558 		fbuf->fb_attr.st_atim = vap->va_atime;
559 		io->fi_flags |= FUSE_FATTR_ATIME;
560 	}
561 
562 	if (vap->va_mtime.tv_nsec != VNOVAL) {
563 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
564 			error = EROFS;
565 			goto out;
566 		}
567 		fbuf->fb_attr.st_mtim = vap->va_mtime;
568 		io->fi_flags |= FUSE_FATTR_MTIME;
569 	}
570 	/* XXX should set a flag if (vap->va_vaflags & VA_UTIMES_CHANGE) */
571 
572 	if (vap->va_mode != (mode_t)VNOVAL) {
573 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
574 			error = EROFS;
575 			goto out;
576 		}
577 
578 		/*
579 		 * chmod returns EFTYPE if the effective user ID is not the
580 		 * super-user, the mode includes the sticky bit (S_ISVTX), and
581 		 * path does not refer to a directory
582 		 */
583 		if (cred->cr_uid != 0 && vp->v_type != VDIR &&
584 		    (vap->va_mode & S_ISTXT)) {
585 			error = EFTYPE;
586 			goto out;
587 		}
588 
589 		fbuf->fb_attr.st_mode = vap->va_mode & ALLPERMS;
590 		io->fi_flags |= FUSE_FATTR_MODE;
591 	}
592 
593 	if (!io->fi_flags) {
594 		goto out;
595 	}
596 
597 	error = fb_queue(fmp->dev, fbuf);
598 	if (error) {
599 		if (error == ENOSYS)
600 			fmp->undef_op |= UNDEF_SETATTR;
601 		goto out;
602 	}
603 
604 	/* truncate was successful, let uvm know */
605 	if (vap->va_size != VNOVAL && vap->va_size != ip->filesize) {
606 		ip->filesize = vap->va_size;
607 		uvm_vnp_setsize(vp, vap->va_size);
608 	}
609 
610 	VN_KNOTE(ap->a_vp, NOTE_ATTRIB);
611 
612 out:
613 	fb_delete(fbuf);
614 	return (error);
615 }
616 
617 int
618 fusefs_ioctl(void *v)
619 {
620 	return (ENOTTY);
621 }
622 
623 int
624 fusefs_link(void *v)
625 {
626 	struct vop_link_args *ap = v;
627 	struct vnode *dvp = ap->a_dvp;
628 	struct vnode *vp = ap->a_vp;
629 	struct componentname *cnp = ap->a_cnp;
630 	struct proc *p = cnp->cn_proc;
631 	struct fusefs_mnt *fmp;
632 	struct fusefs_node *ip;
633 	struct fusefs_node *dip;
634 	struct fusebuf *fbuf;
635 	int error = 0;
636 
637 	ip = VTOI(vp);
638 	dip = VTOI(dvp);
639 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
640 
641 	if (!fmp->sess_init) {
642 		VOP_ABORTOP(dvp, cnp);
643 		error = ENXIO;
644 		goto out2;
645 	}
646 	if (fmp->undef_op & UNDEF_LINK) {
647 		VOP_ABORTOP(dvp, cnp);
648 		error = ENOSYS;
649 		goto out2;
650 	}
651 	if (vp->v_type == VDIR) {
652 		VOP_ABORTOP(dvp, cnp);
653 		error = EPERM;
654 		goto out2;
655 	}
656 	if (dvp->v_mount != vp->v_mount) {
657 		VOP_ABORTOP(dvp, cnp);
658 		error = EXDEV;
659 		goto out2;
660 	}
661 	if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) {
662 		VOP_ABORTOP(dvp, cnp);
663 		goto out2;
664 	}
665 
666 	fbuf = fb_setup(cnp->cn_namelen + 1, dip->ufs_ino.i_number,
667 	    FBT_LINK, p);
668 
669 	fbuf->fb_io_ino = ip->ufs_ino.i_number;
670 	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
671 	fbuf->fb_dat[cnp->cn_namelen] = '\0';
672 
673 	error = fb_queue(fmp->dev, fbuf);
674 
675 	if (error) {
676 		if (error == ENOSYS)
677 			fmp->undef_op |= UNDEF_LINK;
678 
679 		fb_delete(fbuf);
680 		goto out1;
681 	}
682 
683 	fb_delete(fbuf);
684 	VN_KNOTE(vp, NOTE_LINK);
685 	VN_KNOTE(dvp, NOTE_WRITE);
686 
687 out1:
688 	if (dvp != vp)
689 		VOP_UNLOCK(vp);
690 out2:
691 	vput(dvp);
692 	return (error);
693 }
694 
695 int
696 fusefs_symlink(void *v)
697 {
698 	struct vop_symlink_args *ap = v;
699 	struct vnode **vpp = ap->a_vpp;
700 	struct componentname *cnp = ap->a_cnp;
701 	struct vnode *dvp = ap->a_dvp;
702 	struct proc *p = cnp->cn_proc;
703 	char *target = ap->a_target;
704 	struct fusefs_node *dp;
705 	struct fusefs_mnt *fmp;
706 	struct fusebuf *fbuf;
707 	struct vnode *tdp;
708 	int error = 0;
709 	int len;
710 
711 	dp = VTOI(dvp);
712 	fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump;
713 
714 	if (!fmp->sess_init) {
715 		error = ENXIO;
716 		goto bad;
717 	}
718 
719 	if (fmp->undef_op & UNDEF_SYMLINK) {
720 		error = ENOSYS;
721 		goto bad;
722 	}
723 
724 	len = strlen(target) + 1;
725 
726 	fbuf = fb_setup(len + cnp->cn_namelen + 1, dp->ufs_ino.i_number,
727 	    FBT_SYMLINK, p);
728 
729 	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
730 	fbuf->fb_dat[cnp->cn_namelen] = '\0';
731 	memcpy(&fbuf->fb_dat[cnp->cn_namelen + 1], target, len);
732 
733 	error = fb_queue(fmp->dev, fbuf);
734 	if (error) {
735 		if (error == ENOSYS)
736 			fmp->undef_op |= UNDEF_SYMLINK;
737 
738 		fb_delete(fbuf);
739 		goto bad;
740 	}
741 
742 	if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
743 		fb_delete(fbuf);
744 		goto bad;
745 	}
746 
747 	tdp->v_type = VLNK;
748 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
749 
750 	*vpp = tdp;
751 	fb_delete(fbuf);
752 	vput(tdp);
753 bad:
754 	vput(dvp);
755 	return (error);
756 }
757 
758 int
759 fusefs_readdir(void *v)
760 {
761 	struct vop_readdir_args *ap = v;
762 	struct fusefs_node *ip;
763 	struct fusefs_mnt *fmp;
764 	struct fusebuf *fbuf;
765 	struct vnode *vp;
766 	struct proc *p;
767 	struct uio *uio;
768 	int error = 0, eofflag = 0, diropen = 0;
769 
770 	vp = ap->a_vp;
771 	uio = ap->a_uio;
772 	p = uio->uio_procp;
773 
774 	ip = VTOI(vp);
775 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
776 
777 	if (!fmp->sess_init)
778 		return (ENXIO);
779 
780 	if (uio->uio_resid < sizeof(struct dirent))
781 		return (EINVAL);
782 
783 	if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) {
784 		error = fusefs_file_open(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p);
785 		if (error)
786 			return (error);
787 
788 		diropen = 1;
789 	}
790 
791 	while (uio->uio_resid > 0) {
792 		fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READDIR, p);
793 
794 		fbuf->fb_io_fd = ip->fufh[FUFH_RDONLY].fh_id;
795 		fbuf->fb_io_off = uio->uio_offset;
796 		fbuf->fb_io_len = MIN(uio->uio_resid, fmp->max_read);
797 
798 		error = fb_queue(fmp->dev, fbuf);
799 
800 		if (error) {
801 			/*
802 			 * dirent was larger than residual space left in
803 			 * buffer.
804 			 */
805 			if (error == ENOBUFS)
806 				error = 0;
807 
808 			fb_delete(fbuf);
809 			break;
810 		}
811 
812 		/* ack end of readdir */
813 		if (fbuf->fb_len == 0) {
814 			eofflag = 1;
815 			fb_delete(fbuf);
816 			break;
817 		}
818 
819 		if ((error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio))) {
820 			fb_delete(fbuf);
821 			break;
822 		}
823 
824 		fb_delete(fbuf);
825 	}
826 
827 	if (!error && ap->a_eofflag != NULL)
828 		*ap->a_eofflag = eofflag;
829 
830 	if (diropen)
831 		fusefs_file_close(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p);
832 
833 	return (error);
834 }
835 
836 int
837 fusefs_inactive(void *v)
838 {
839 	struct vop_inactive_args *ap = v;
840 	struct vnode *vp = ap->a_vp;
841 	struct proc *p = ap->a_p;
842 	struct fusefs_node *ip = VTOI(vp);
843 	struct fusefs_filehandle *fufh = NULL;
844 	struct fusefs_mnt *fmp;
845 	int type, flags;
846 
847 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
848 
849 	/* Close all open file handles. */
850 	for (type = 0; type < FUFH_MAXTYPE; type++) {
851 		fufh = &(ip->fufh[type]);
852 		if (fufh->fh_type != FUFH_INVALID) {
853 
854 			/*
855 			 * FUSE file systems expect the same flags to be sent
856 			 * on release that were sent on open. We don't have a
857 			 * record of them so make a best guess.
858 			 */
859 			switch (type) {
860 			case FUFH_RDONLY:
861 				flags = O_RDONLY;
862 				break;
863 			case FUFH_WRONLY:
864 				flags = O_WRONLY;
865 				break;
866 			default:
867 				flags = O_RDWR;
868 			}
869 
870 			fusefs_file_close(fmp, ip, fufh->fh_type, flags,
871 			    (vp->v_type == VDIR), p);
872 		}
873 	}
874 
875 	VOP_UNLOCK(vp);
876 
877 	/* Don't return error to prevent kernel panic in vclean(9). */
878 	return (0);
879 }
880 
881 int
882 fusefs_readlink(void *v)
883 {
884 	struct vop_readlink_args *ap = v;
885 	struct vnode *vp = ap->a_vp;
886 	struct fusefs_node *ip;
887 	struct fusefs_mnt *fmp;
888 	struct fusebuf *fbuf;
889 	struct uio *uio;
890 	struct proc *p;
891 	int error = 0;
892 
893 	ip = VTOI(vp);
894 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
895 	uio = ap->a_uio;
896 	p = uio->uio_procp;
897 
898 	if (!fmp->sess_init)
899 		return (ENXIO);
900 
901 	if (fmp->undef_op & UNDEF_READLINK)
902 		return (ENOSYS);
903 
904 	fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READLINK, p);
905 
906 	error = fb_queue(fmp->dev, fbuf);
907 
908 	if (error) {
909 		if (error == ENOSYS)
910 			fmp->undef_op |= UNDEF_READLINK;
911 
912 		fb_delete(fbuf);
913 		return (error);
914 	}
915 
916 	error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio);
917 	fb_delete(fbuf);
918 
919 	return (error);
920 }
921 
922 int
923 fusefs_reclaim(void *v)
924 {
925 	struct vop_reclaim_args *ap = v;
926 	struct vnode *vp = ap->a_vp;
927 	struct proc *p = ap->a_p;
928 	struct fusefs_node *ip = VTOI(vp);
929 	struct fusefs_filehandle *fufh = NULL;
930 	struct fusefs_mnt *fmp;
931 	struct fusebuf *fbuf;
932 	int type, error = 0;
933 
934 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
935 
936 	/* Close opened files. */
937 	for (type = 0; type < FUFH_MAXTYPE; type++) {
938 		fufh = &(ip->fufh[type]);
939 		if (fufh->fh_type != FUFH_INVALID) {
940 			printf("fusefs: vnode being reclaimed is valid\n");
941 			fusefs_file_close(fmp, ip, fufh->fh_type, type,
942 			    (vp->v_type == VDIR), ap->a_p);
943 		}
944 	}
945 
946 	/*
947 	 * If the fuse connection is opened ask libfuse to free the vnodes.
948 	 */
949 	if (fmp->sess_init && ip->ufs_ino.i_number != FUSE_ROOTINO) {
950 		fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_RECLAIM, p);
951 		error = fb_queue(fmp->dev, fbuf);
952 		if (error)
953 			printf("fusefs: vnode reclaim failed: %d\n", error);
954 		fb_delete(fbuf);
955 	}
956 
957 	/*
958 	 * Remove the inode from its hash chain.
959 	 */
960 	ufs_ihashrem(&ip->ufs_ino);
961 
962 	free(ip, M_FUSEFS, sizeof(*ip));
963 	vp->v_data = NULL;
964 
965 	/* Must return success otherwise kernel panic in vclean(9). */
966 	return (0);
967 }
968 
969 int
970 fusefs_print(void *v)
971 {
972 	struct vop_print_args *ap = v;
973 	struct vnode *vp = ap->a_vp;
974 	struct fusefs_node *ip = VTOI(vp);
975 
976 	/* Complete the information given by vprint(). */
977 	printf("tag VT_FUSE, hash id %u ", ip->ufs_ino.i_number);
978 	printf("\n");
979 	return (0);
980 }
981 
982 int
983 fusefs_create(void *v)
984 {
985 	struct vop_create_args *ap = v;
986 	struct componentname *cnp = ap->a_cnp;
987 	struct vnode **vpp = ap->a_vpp;
988 	struct vnode *dvp = ap->a_dvp;
989 	struct vattr *vap = ap->a_vap;
990 	struct proc *p = cnp->cn_proc;
991 	struct vnode *tdp = NULL;
992 	struct fusefs_mnt *fmp;
993 	struct fusefs_node *ip;
994 	struct fusebuf *fbuf;
995 	int error = 0;
996 	mode_t mode;
997 
998 	ip = VTOI(dvp);
999 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1000 	mode = MAKEIMODE(vap->va_type, vap->va_mode);
1001 
1002 	if (!fmp->sess_init)
1003 		return (ENXIO);
1004 
1005 	if (fmp->undef_op & UNDEF_MKNOD)
1006 		return (ENOSYS);
1007 
1008 	fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number,
1009 	    FBT_MKNOD, p);
1010 
1011 	fbuf->fb_io_mode = mode;
1012 
1013 	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
1014 	fbuf->fb_dat[cnp->cn_namelen] = '\0';
1015 
1016 	error = fb_queue(fmp->dev, fbuf);
1017 	if (error) {
1018 		if (error == ENOSYS)
1019 			fmp->undef_op |= UNDEF_MKNOD;
1020 
1021 		goto out;
1022 	}
1023 
1024 	if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp)))
1025 		goto out;
1026 
1027 	tdp->v_type = IFTOVT(fbuf->fb_io_mode);
1028 
1029 	*vpp = tdp;
1030 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1031 out:
1032 	fb_delete(fbuf);
1033 	return (error);
1034 }
1035 
1036 int
1037 fusefs_mknod(void *v)
1038 {
1039 	struct vop_mknod_args *ap = v;
1040 	struct componentname *cnp = ap->a_cnp;
1041 	struct vnode **vpp = ap->a_vpp;
1042 	struct vnode *dvp = ap->a_dvp;
1043 	struct vattr *vap = ap->a_vap;
1044 	struct proc *p = cnp->cn_proc;
1045 	struct vnode *tdp = NULL;
1046 	struct fusefs_mnt *fmp;
1047 	struct fusefs_node *ip;
1048 	struct fusebuf *fbuf;
1049 	int error = 0;
1050 
1051 	ip = VTOI(dvp);
1052 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1053 
1054 	if (!fmp->sess_init)
1055 		return (ENXIO);
1056 
1057 	if (fmp->undef_op & UNDEF_MKNOD)
1058 		return (ENOSYS);
1059 
1060 	fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number,
1061 	    FBT_MKNOD, p);
1062 
1063 	fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode);
1064 	if (vap->va_rdev != VNOVAL)
1065 		fbuf->fb_io_rdev = vap->va_rdev;
1066 
1067 	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
1068 	fbuf->fb_dat[cnp->cn_namelen] = '\0';
1069 
1070 	error = fb_queue(fmp->dev, fbuf);
1071 	if (error) {
1072 		if (error == ENOSYS)
1073 			fmp->undef_op |= UNDEF_MKNOD;
1074 
1075 		goto out;
1076 	}
1077 
1078 	if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp)))
1079 		goto out;
1080 
1081 	tdp->v_type = IFTOVT(fbuf->fb_io_mode);
1082 
1083 	*vpp = tdp;
1084 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1085 
1086 	/* Remove inode so that it will be reloaded by VFS_VGET and
1087 	 * checked to see if it is an alias of an existing entry in
1088 	 * the inode cache.
1089 	 */
1090 	vput(*vpp);
1091 	(*vpp)->v_type = VNON;
1092 	vgone(*vpp);
1093 	*vpp = NULL;
1094 out:
1095 	fb_delete(fbuf);
1096 	return (error);
1097 }
1098 
1099 int
1100 fusefs_read(void *v)
1101 {
1102 	struct vop_read_args *ap = v;
1103 	struct vnode *vp = ap->a_vp;
1104 	struct uio *uio = ap->a_uio;
1105 	struct proc *p = uio->uio_procp;
1106 	struct fusefs_node *ip;
1107 	struct fusefs_mnt *fmp;
1108 	struct fusebuf *fbuf = NULL;
1109 	size_t size;
1110 	int error=0;
1111 
1112 	ip = VTOI(vp);
1113 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1114 
1115 	if (!fmp->sess_init)
1116 		return (ENXIO);
1117 	if (uio->uio_resid == 0)
1118 		return (error);
1119 	if (uio->uio_offset < 0)
1120 		return (EINVAL);
1121 
1122 	while (uio->uio_resid > 0) {
1123 		fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READ, p);
1124 
1125 		size = MIN(uio->uio_resid, fmp->max_read);
1126 		fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_RDONLY);
1127 		fbuf->fb_io_off = uio->uio_offset;
1128 		fbuf->fb_io_len = size;
1129 
1130 		error = fb_queue(fmp->dev, fbuf);
1131 
1132 		if (error)
1133 			break;
1134 
1135 		error = uiomove(fbuf->fb_dat, ulmin(size, fbuf->fb_len), uio);
1136 		if (error)
1137 			break;
1138 
1139 		if (fbuf->fb_len < size)
1140 			break;
1141 
1142 		fb_delete(fbuf);
1143 		fbuf = NULL;
1144 	}
1145 
1146 	fb_delete(fbuf);
1147 	return (error);
1148 }
1149 
1150 int
1151 fusefs_write(void *v)
1152 {
1153 	struct vop_write_args *ap = v;
1154 	struct vnode *vp = ap->a_vp;
1155 	struct uio *uio = ap->a_uio;
1156 	struct proc *p = uio->uio_procp;
1157 	struct ucred *cred = p->p_ucred;
1158 	struct vattr vattr;
1159 	int ioflag = ap->a_ioflag;
1160 	struct fusefs_node *ip;
1161 	struct fusefs_mnt *fmp;
1162 	struct fusebuf *fbuf = NULL;
1163 	size_t len, diff;
1164 	int error=0;
1165 
1166 	ip = VTOI(vp);
1167 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1168 
1169 	if (!fmp->sess_init)
1170 		return (ENXIO);
1171 	if (uio->uio_resid == 0)
1172 		return (error);
1173 
1174 	if (ioflag & IO_APPEND) {
1175 		if ((error = VOP_GETATTR(vp, &vattr, cred, p)) != 0)
1176 			return (error);
1177 
1178 		uio->uio_offset = vattr.va_size;
1179 	}
1180 
1181 	while (uio->uio_resid > 0) {
1182 		len = MIN(uio->uio_resid, fmp->max_read);
1183 		fbuf = fb_setup(len, ip->ufs_ino.i_number, FBT_WRITE, p);
1184 
1185 		fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_WRONLY);
1186 		fbuf->fb_io_off = uio->uio_offset;
1187 		fbuf->fb_io_len = len;
1188 
1189 		if ((error = uiomove(fbuf->fb_dat, len, uio))) {
1190 			printf("fusefs: uio error %i\n", error);
1191 			break;
1192 		}
1193 
1194 		error = fb_queue(fmp->dev, fbuf);
1195 
1196 		if (error)
1197 			break;
1198 
1199 		diff = len - fbuf->fb_io_len;
1200 		if (fbuf->fb_io_len > len) {
1201 			error = EINVAL;
1202 			break;
1203 		}
1204 
1205 		uio->uio_resid += diff;
1206 		uio->uio_offset -= diff;
1207 
1208 		if (uio->uio_offset > ip->filesize) {
1209 			ip->filesize = uio->uio_offset;
1210 			uvm_vnp_setsize(vp, uio->uio_offset);
1211 		}
1212 		uvm_vnp_uncache(vp);
1213 
1214 		fb_delete(fbuf);
1215 		fbuf = NULL;
1216 	}
1217 
1218 	fb_delete(fbuf);
1219 	return (error);
1220 }
1221 
1222 int
1223 fusefs_poll(void *v)
1224 {
1225 	struct vop_poll_args *ap = v;
1226 
1227 	/*
1228 	 * We should really check to see if I/O is possible.
1229 	 */
1230 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1231 }
1232 
1233 int
1234 fusefs_rename(void *v)
1235 {
1236 	struct vop_rename_args *ap = v;
1237 	struct vnode *tvp = ap->a_tvp;
1238 	struct vnode *tdvp = ap->a_tdvp;
1239 	struct vnode *fvp = ap->a_fvp;
1240 	struct vnode *fdvp = ap->a_fdvp;
1241 	struct componentname *tcnp = ap->a_tcnp;
1242 	struct componentname *fcnp = ap->a_fcnp;
1243 	struct proc *p = fcnp->cn_proc;
1244 	struct fusefs_node *ip, *dp;
1245 	struct fusefs_mnt *fmp;
1246 	struct fusebuf *fbuf;
1247 	int error = 0;
1248 
1249 #ifdef DIAGNOSTIC
1250 	if ((tcnp->cn_flags & HASBUF) == 0 ||
1251 	    (fcnp->cn_flags & HASBUF) == 0)
1252 		panic("fusefs_rename: no name");
1253 #endif
1254 	/*
1255 	 * Check for cross-device rename.
1256 	 */
1257 	if ((fvp->v_mount != tdvp->v_mount) ||
1258 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
1259 		error = EXDEV;
1260 abortit:
1261 		VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
1262 		if (tdvp == tvp)
1263 			vrele(tdvp);
1264 		else
1265 			vput(tdvp);
1266 		if (tvp)
1267 			vput(tvp);
1268 		VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
1269 		vrele(fdvp);
1270 		vrele(fvp);
1271 		return (error);
1272 	}
1273 
1274 	/*
1275 	 * If source and dest are the same, do nothing.
1276 	 */
1277 	if (tvp == fvp) {
1278 		error = 0;
1279 		goto abortit;
1280 	}
1281 
1282 	if ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)) != 0)
1283 		goto abortit;
1284 	dp = VTOI(fdvp);
1285 	ip = VTOI(fvp);
1286 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1287 
1288 	/*
1289 	 * Be sure we are not renaming ".", "..", or an alias of ".". This
1290 	 * leads to a crippled directory tree.  It's pretty tough to do a
1291 	 * "ls" or "pwd" with the "." directory entry missing, and "cd .."
1292 	 * doesn't work if the ".." entry is missing.
1293 	 */
1294 	if (fvp->v_type == VDIR) {
1295 		/*
1296 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
1297 		 */
1298 		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1299 		    dp == ip ||
1300 		    (fcnp->cn_flags & ISDOTDOT) ||
1301 		    (tcnp->cn_flags & ISDOTDOT)) {
1302 			VOP_UNLOCK(fvp);
1303 			error = EINVAL;
1304 			goto abortit;
1305 		}
1306 	}
1307 	VN_KNOTE(fdvp, NOTE_WRITE);	/* XXX right place? */
1308 
1309 	if (!fmp->sess_init) {
1310 		error = ENXIO;
1311 		VOP_UNLOCK(fvp);
1312 		goto abortit;
1313 	}
1314 
1315 	if (fmp->undef_op & UNDEF_RENAME) {
1316 		error = ENOSYS;
1317 		VOP_UNLOCK(fvp);
1318 		goto abortit;
1319 	}
1320 
1321 	fbuf = fb_setup(fcnp->cn_namelen + tcnp->cn_namelen + 2,
1322 	    dp->ufs_ino.i_number, FBT_RENAME, p);
1323 
1324 	memcpy(fbuf->fb_dat, fcnp->cn_nameptr, fcnp->cn_namelen);
1325 	fbuf->fb_dat[fcnp->cn_namelen] = '\0';
1326 	memcpy(fbuf->fb_dat + fcnp->cn_namelen + 1, tcnp->cn_nameptr,
1327 	    tcnp->cn_namelen);
1328 	fbuf->fb_dat[fcnp->cn_namelen + tcnp->cn_namelen + 1] = '\0';
1329 	fbuf->fb_io_ino = VTOI(tdvp)->ufs_ino.i_number;
1330 
1331 	error = fb_queue(fmp->dev, fbuf);
1332 
1333 	if (error) {
1334 		if (error == ENOSYS) {
1335 			fmp->undef_op |= UNDEF_RENAME;
1336 		}
1337 
1338 		fb_delete(fbuf);
1339 		VOP_UNLOCK(fvp);
1340 		goto abortit;
1341 	}
1342 
1343 	fb_delete(fbuf);
1344 	VN_KNOTE(fvp, NOTE_RENAME);
1345 
1346 	VOP_UNLOCK(fvp);
1347 	if (tdvp == tvp)
1348 		vrele(tdvp);
1349 	else
1350 		vput(tdvp);
1351 	if (tvp)
1352 		vput(tvp);
1353 	vrele(fdvp);
1354 	vrele(fvp);
1355 
1356 	return (error);
1357 }
1358 
1359 int
1360 fusefs_mkdir(void *v)
1361 {
1362 	struct vop_mkdir_args *ap = v;
1363 	struct vnode *dvp = ap->a_dvp;
1364 	struct vnode **vpp = ap->a_vpp;
1365 	struct componentname *cnp = ap->a_cnp;
1366 	struct vattr *vap = ap->a_vap;
1367 	struct proc *p = cnp->cn_proc;
1368 	struct vnode *tdp = NULL;
1369 	struct fusefs_node *ip;
1370 	struct fusefs_mnt *fmp;
1371 	struct fusebuf *fbuf;
1372 	int error = 0;
1373 
1374 	ip = VTOI(dvp);
1375 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1376 
1377 
1378 	if (!fmp->sess_init) {
1379 		error = ENXIO;
1380 		goto out;
1381 	}
1382 
1383 	if (fmp->undef_op & UNDEF_MKDIR) {
1384 		error = ENOSYS;
1385 		goto out;
1386 	}
1387 
1388 	fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number,
1389 	    FBT_MKDIR, p);
1390 
1391 	fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode);
1392 	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
1393 	fbuf->fb_dat[cnp->cn_namelen] = '\0';
1394 
1395 	error = fb_queue(fmp->dev, fbuf);
1396 	if (error) {
1397 		if (error == ENOSYS)
1398 			fmp->undef_op |= UNDEF_MKDIR;
1399 
1400 		fb_delete(fbuf);
1401 		goto out;
1402 	}
1403 
1404 	if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
1405 		fb_delete(fbuf);
1406 		goto out;
1407 	}
1408 
1409 	tdp->v_type = IFTOVT(fbuf->fb_io_mode);
1410 
1411 	*vpp = tdp;
1412 	VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
1413 	fb_delete(fbuf);
1414 out:
1415 	vput(dvp);
1416 	return (error);
1417 }
1418 
1419 int
1420 fusefs_rmdir(void *v)
1421 {
1422 	struct vop_rmdir_args *ap = v;
1423 	struct vnode *vp = ap->a_vp;
1424 	struct vnode *dvp = ap->a_dvp;
1425 	struct componentname *cnp = ap->a_cnp;
1426 	struct proc *p = cnp->cn_proc;
1427 	struct fusefs_node *ip, *dp;
1428 	struct fusefs_mnt *fmp;
1429 	struct fusebuf *fbuf;
1430 	int error;
1431 
1432 	ip = VTOI(vp);
1433 	dp = VTOI(dvp);
1434 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1435 
1436 	if (!fmp->sess_init) {
1437 		error = ENXIO;
1438 		goto out;
1439 	}
1440 
1441 	if (fmp->undef_op & UNDEF_RMDIR) {
1442 		error = ENOSYS;
1443 		goto out;
1444 	}
1445 
1446 	VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1447 
1448 	fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number,
1449 	    FBT_RMDIR, p);
1450 	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
1451 	fbuf->fb_dat[cnp->cn_namelen] = '\0';
1452 
1453 	error = fb_queue(fmp->dev, fbuf);
1454 
1455 	if (error) {
1456 		if (error == ENOSYS)
1457 			fmp->undef_op |= UNDEF_RMDIR;
1458 		if (error != ENOTEMPTY)
1459 			VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1460 
1461 		fb_delete(fbuf);
1462 		goto out;
1463 	}
1464 
1465 	vput(dvp);
1466 	dvp = NULL;
1467 
1468 	fb_delete(fbuf);
1469 out:
1470 	if (dvp)
1471 		vput(dvp);
1472 	VN_KNOTE(vp, NOTE_DELETE);
1473 	vput(vp);
1474 	return (error);
1475 }
1476 
1477 int
1478 fusefs_remove(void *v)
1479 {
1480 	struct vop_remove_args *ap = v;
1481 	struct vnode *vp = ap->a_vp;
1482 	struct vnode *dvp = ap->a_dvp;
1483 	struct componentname *cnp = ap->a_cnp;
1484 	struct proc *p = cnp->cn_proc;
1485 	struct fusefs_node *ip;
1486 	struct fusefs_node *dp;
1487 	struct fusefs_mnt *fmp;
1488 	struct fusebuf *fbuf;
1489 	int error = 0;
1490 
1491 	ip = VTOI(vp);
1492 	dp = VTOI(dvp);
1493 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1494 
1495 	if (!fmp->sess_init) {
1496 		error = ENXIO;
1497 		goto out;
1498 	}
1499 
1500 	if (fmp->undef_op & UNDEF_REMOVE) {
1501 		error = ENOSYS;
1502 		goto out;
1503 	}
1504 
1505 	fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number,
1506 	    FBT_UNLINK, p);
1507 	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
1508 	fbuf->fb_dat[cnp->cn_namelen] = '\0';
1509 
1510 	error = fb_queue(fmp->dev, fbuf);
1511 	if (error) {
1512 		if (error == ENOSYS)
1513 			fmp->undef_op |= UNDEF_REMOVE;
1514 
1515 		fb_delete(fbuf);
1516 		goto out;
1517 	}
1518 
1519 	VN_KNOTE(vp, NOTE_DELETE);
1520 	VN_KNOTE(dvp, NOTE_WRITE);
1521 	fb_delete(fbuf);
1522 out:
1523 	if (dvp == vp)
1524 		vrele(vp);
1525 	else
1526 		vput(vp);
1527 	vput(dvp);
1528 	return (error);
1529 }
1530 
1531 int
1532 fusefs_strategy(void *v)
1533 {
1534 	return (0);
1535 }
1536 
1537 int
1538 fusefs_lock(void *v)
1539 {
1540 	struct vop_lock_args *ap = v;
1541 	struct vnode *vp = ap->a_vp;
1542 
1543 	return rrw_enter(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags & LK_RWFLAGS);
1544 }
1545 
1546 int
1547 fusefs_unlock(void *v)
1548 {
1549 	struct vop_unlock_args *ap = v;
1550 	struct vnode *vp = ap->a_vp;
1551 
1552 	rrw_exit(&VTOI(vp)->ufs_ino.i_lock);
1553 	return 0;
1554 }
1555 
1556 int
1557 fusefs_islocked(void *v)
1558 {
1559 	struct vop_islocked_args *ap = v;
1560 
1561 	return rrw_status(&VTOI(ap->a_vp)->ufs_ino.i_lock);
1562 }
1563 
1564 int
1565 fusefs_advlock(void *v)
1566 {
1567 	struct vop_advlock_args *ap = v;
1568 	struct fusefs_node *ip = VTOI(ap->a_vp);
1569 
1570 	return (lf_advlock(&ip->ufs_ino.i_lockf, ip->filesize, ap->a_id,
1571 	    ap->a_op, ap->a_fl, ap->a_flags));
1572 }
1573 
1574 int
1575 fusefs_fsync(void *v)
1576 {
1577 	struct vop_fsync_args *ap = v;
1578 	struct vnode *vp = ap->a_vp;
1579 	struct proc *p = ap->a_p;
1580 	struct fusefs_node *ip;
1581 	struct fusefs_mnt *fmp;
1582 	struct fusefs_filehandle *fufh;
1583 	struct fusebuf *fbuf;
1584 	int type, error = 0;
1585 
1586 	/*
1587 	 * Can't write to directory file handles so no need to fsync.
1588 	 * FUSE has fsyncdir but it doesn't make sense on OpenBSD.
1589 	 */
1590 	if (vp->v_type == VDIR)
1591 		return (0);
1592 
1593 	ip = VTOI(vp);
1594 	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
1595 
1596 	if (!fmp->sess_init)
1597 		return (ENXIO);
1598 
1599 	/* Implementing fsync is optional so don't error. */
1600 	if (fmp->undef_op & UNDEF_FSYNC)
1601 		return (0);
1602 
1603 	/* Sync all writeable file descriptors. */
1604 	for (type = 0; type < FUFH_MAXTYPE; type++) {
1605 		fufh = &(ip->fufh[type]);
1606 		if (fufh->fh_type == FUFH_WRONLY ||
1607 		    fufh->fh_type == FUFH_RDWR) {
1608 
1609 			fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_FSYNC, p);
1610 			fbuf->fb_io_fd = fufh->fh_id;
1611 
1612 			/* Always behave as if ap->a_waitfor = MNT_WAIT. */
1613 			error = fb_queue(fmp->dev, fbuf);
1614 			fb_delete(fbuf);
1615 			if (error)
1616 				break;
1617 		}
1618 	}
1619 
1620 	if (error == ENOSYS) {
1621 		fmp->undef_op |= UNDEF_FSYNC;
1622 
1623 		/* Implementing fsync is optional so don't error. */
1624 		return (0);
1625 	}
1626 
1627 	return (error);
1628 }
1629