]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/fuse/fuse_vnops.c
fusefs: fix a just-introduced panic in readdir
[FreeBSD/FreeBSD.git] / sys / fs / fuse / fuse_vnops.c
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  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  *
45  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55  * SUCH DAMAGE.
56  */
57
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
60
61 #include <sys/param.h>
62 #include <sys/module.h>
63 #include <sys/systm.h>
64 #include <sys/errno.h>
65 #include <sys/kernel.h>
66 #include <sys/conf.h>
67 #include <sys/uio.h>
68 #include <sys/malloc.h>
69 #include <sys/queue.h>
70 #include <sys/lock.h>
71 #include <sys/rwlock.h>
72 #include <sys/sx.h>
73 #include <sys/proc.h>
74 #include <sys/mount.h>
75 #include <sys/vnode.h>
76 #include <sys/namei.h>
77 #include <sys/extattr.h>
78 #include <sys/stat.h>
79 #include <sys/unistd.h>
80 #include <sys/filedesc.h>
81 #include <sys/file.h>
82 #include <sys/fcntl.h>
83 #include <sys/dirent.h>
84 #include <sys/bio.h>
85 #include <sys/buf.h>
86 #include <sys/sysctl.h>
87 #include <sys/vmmeter.h>
88
89 #include <vm/vm.h>
90 #include <vm/vm_extern.h>
91 #include <vm/pmap.h>
92 #include <vm/vm_map.h>
93 #include <vm/vm_page.h>
94 #include <vm/vm_param.h>
95 #include <vm/vm_object.h>
96 #include <vm/vm_pager.h>
97 #include <vm/vnode_pager.h>
98 #include <vm/vm_object.h>
99
100 #include "fuse.h"
101 #include "fuse_file.h"
102 #include "fuse_internal.h"
103 #include "fuse_ipc.h"
104 #include "fuse_node.h"
105 #include "fuse_io.h"
106
107 #include <sys/priv.h>
108
109 /* Maximum number of hardlinks to a single FUSE file */
110 #define FUSE_LINK_MAX                      UINT32_MAX
111
112 SDT_PROVIDER_DECLARE(fuse);
113 /* 
114  * Fuse trace probe:
115  * arg0: verbosity.  Higher numbers give more verbose messages
116  * arg1: Textual message
117  */
118 SDT_PROBE_DEFINE2(fuse, , vnops, trace, "int", "char*");
119
120 /* vnode ops */
121 static vop_access_t fuse_vnop_access;
122 static vop_close_t fuse_vnop_close;
123 static vop_create_t fuse_vnop_create;
124 static vop_deleteextattr_t fuse_vnop_deleteextattr;
125 static vop_fdatasync_t fuse_vnop_fdatasync;
126 static vop_fsync_t fuse_vnop_fsync;
127 static vop_getattr_t fuse_vnop_getattr;
128 static vop_getextattr_t fuse_vnop_getextattr;
129 static vop_inactive_t fuse_vnop_inactive;
130 static vop_link_t fuse_vnop_link;
131 static vop_listextattr_t fuse_vnop_listextattr;
132 static vop_lookup_t fuse_vnop_lookup;
133 static vop_mkdir_t fuse_vnop_mkdir;
134 static vop_mknod_t fuse_vnop_mknod;
135 static vop_open_t fuse_vnop_open;
136 static vop_pathconf_t fuse_vnop_pathconf;
137 static vop_read_t fuse_vnop_read;
138 static vop_readdir_t fuse_vnop_readdir;
139 static vop_readlink_t fuse_vnop_readlink;
140 static vop_reclaim_t fuse_vnop_reclaim;
141 static vop_remove_t fuse_vnop_remove;
142 static vop_rename_t fuse_vnop_rename;
143 static vop_rmdir_t fuse_vnop_rmdir;
144 static vop_setattr_t fuse_vnop_setattr;
145 static vop_setextattr_t fuse_vnop_setextattr;
146 static vop_strategy_t fuse_vnop_strategy;
147 static vop_symlink_t fuse_vnop_symlink;
148 static vop_write_t fuse_vnop_write;
149 static vop_getpages_t fuse_vnop_getpages;
150 static vop_putpages_t fuse_vnop_putpages;
151 static vop_print_t fuse_vnop_print;
152
153 struct vop_vector fuse_vnops = {
154         .vop_default = &default_vnodeops,
155         .vop_access = fuse_vnop_access,
156         .vop_close = fuse_vnop_close,
157         .vop_create = fuse_vnop_create,
158         .vop_deleteextattr = fuse_vnop_deleteextattr,
159         .vop_fsync = fuse_vnop_fsync,
160         .vop_fdatasync = fuse_vnop_fdatasync,
161         .vop_getattr = fuse_vnop_getattr,
162         .vop_getextattr = fuse_vnop_getextattr,
163         .vop_inactive = fuse_vnop_inactive,
164         .vop_link = fuse_vnop_link,
165         .vop_listextattr = fuse_vnop_listextattr,
166         .vop_lookup = fuse_vnop_lookup,
167         .vop_mkdir = fuse_vnop_mkdir,
168         .vop_mknod = fuse_vnop_mknod,
169         .vop_open = fuse_vnop_open,
170         .vop_pathconf = fuse_vnop_pathconf,
171         .vop_read = fuse_vnop_read,
172         .vop_readdir = fuse_vnop_readdir,
173         .vop_readlink = fuse_vnop_readlink,
174         .vop_reclaim = fuse_vnop_reclaim,
175         .vop_remove = fuse_vnop_remove,
176         .vop_rename = fuse_vnop_rename,
177         .vop_rmdir = fuse_vnop_rmdir,
178         .vop_setattr = fuse_vnop_setattr,
179         .vop_setextattr = fuse_vnop_setextattr,
180         .vop_strategy = fuse_vnop_strategy,
181         .vop_symlink = fuse_vnop_symlink,
182         .vop_write = fuse_vnop_write,
183         .vop_getpages = fuse_vnop_getpages,
184         .vop_putpages = fuse_vnop_putpages,
185         .vop_print = fuse_vnop_print,
186 };
187
188 static u_long fuse_lookup_cache_hits = 0;
189
190 SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_hits, CTLFLAG_RD,
191     &fuse_lookup_cache_hits, 0, "number of positive cache hits in lookup");
192
193 static u_long fuse_lookup_cache_misses = 0;
194
195 SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_misses, CTLFLAG_RD,
196     &fuse_lookup_cache_misses, 0, "number of cache misses in lookup");
197
198 int     fuse_lookup_cache_enable = 1;
199
200 SYSCTL_INT(_vfs_fusefs, OID_AUTO, lookup_cache_enable, CTLFLAG_RW,
201     &fuse_lookup_cache_enable, 0, "if non-zero, enable lookup cache");
202
203 /*
204  * XXX: This feature is highly experimental and can bring to instabilities,
205  * needs revisiting before to be enabled by default.
206  */
207 static int fuse_reclaim_revoked = 0;
208
209 SYSCTL_INT(_vfs_fusefs, OID_AUTO, reclaim_revoked, CTLFLAG_RW,
210     &fuse_reclaim_revoked, 0, "");
211
212 uma_zone_t fuse_pbuf_zone;
213
214 #define fuse_vm_page_lock(m)            vm_page_lock((m));
215 #define fuse_vm_page_unlock(m)          vm_page_unlock((m));
216 #define fuse_vm_page_lock_queues()      ((void)0)
217 #define fuse_vm_page_unlock_queues()    ((void)0)
218
219 /* Get a filehandle for a directory */
220 static int
221 fuse_filehandle_get_dir(struct vnode *vp, struct fuse_filehandle **fufhp,
222         struct ucred *cred, pid_t pid)
223 {
224         if (fuse_filehandle_get(vp, FUFH_RDONLY, fufhp, cred, pid) == 0)
225                 return 0;
226         return fuse_filehandle_get(vp, FUFH_EXEC, fufhp, cred, pid);
227 }
228
229 /*
230     struct vnop_access_args {
231         struct vnode *a_vp;
232 #if VOP_ACCESS_TAKES_ACCMODE_T
233         accmode_t a_accmode;
234 #else
235         int a_mode;
236 #endif
237         struct ucred *a_cred;
238         struct thread *a_td;
239     };
240 */
241 static int
242 fuse_vnop_access(struct vop_access_args *ap)
243 {
244         struct vnode *vp = ap->a_vp;
245         int accmode = ap->a_accmode;
246         struct ucred *cred = ap->a_cred;
247
248         struct fuse_access_param facp;
249         struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp));
250
251         int err;
252
253         if (fuse_isdeadfs(vp)) {
254                 if (vnode_isvroot(vp)) {
255                         return 0;
256                 }
257                 return ENXIO;
258         }
259         if (!(data->dataflags & FSESS_INITED)) {
260                 if (vnode_isvroot(vp)) {
261                         if (priv_check_cred(cred, PRIV_VFS_ADMIN) ||
262                             (fuse_match_cred(data->daemoncred, cred) == 0)) {
263                                 return 0;
264                         }
265                 }
266                 return EBADF;
267         }
268         if (vnode_islnk(vp)) {
269                 return 0;
270         }
271         bzero(&facp, sizeof(facp));
272
273         err = fuse_internal_access(vp, accmode, &facp, ap->a_td, ap->a_cred);
274         return err;
275 }
276
277 /*
278     struct vnop_close_args {
279         struct vnode *a_vp;
280         int  a_fflag;
281         struct ucred *a_cred;
282         struct thread *a_td;
283     };
284 */
285 static int
286 fuse_vnop_close(struct vop_close_args *ap)
287 {
288         struct vnode *vp = ap->a_vp;
289         struct ucred *cred = ap->a_cred;
290         int fflag = ap->a_fflag;
291         struct thread *td = ap->a_td;
292         pid_t pid = td->td_proc->p_pid;
293
294         if (fuse_isdeadfs(vp)) {
295                 return 0;
296         }
297         if (vnode_isdir(vp)) {
298                 struct fuse_filehandle *fufh;
299
300                 if (fuse_filehandle_get_dir(vp, &fufh, cred, pid) == 0)
301                         fuse_filehandle_close(vp, fufh, NULL, cred);
302                 return 0;
303         }
304         if (fflag & IO_NDELAY) {
305                 return 0;
306         }
307         /* TODO: close the file handle, if we're sure it's no longer used */
308         if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) {
309                 fuse_vnode_savesize(vp, cred, td->td_proc->p_pid);
310         }
311         return 0;
312 }
313
314 static void
315 fdisp_make_mknod_for_fallback(
316         struct fuse_dispatcher *fdip,
317         struct componentname *cnp,
318         struct vnode *dvp,
319         uint64_t parentnid,
320         struct thread *td,
321         struct ucred *cred,
322         mode_t mode,
323         enum fuse_opcode *op)
324 {
325         struct fuse_mknod_in *fmni;
326
327         fdisp_init(fdip, sizeof(*fmni) + cnp->cn_namelen + 1);
328         *op = FUSE_MKNOD;
329         fdisp_make(fdip, *op, vnode_mount(dvp), parentnid, td, cred);
330         fmni = fdip->indata;
331         fmni->mode = mode;
332         fmni->rdev = 0;
333         memcpy((char *)fdip->indata + sizeof(*fmni), cnp->cn_nameptr,
334             cnp->cn_namelen);
335         ((char *)fdip->indata)[sizeof(*fmni) + cnp->cn_namelen] = '\0';
336 }
337 /*
338     struct vnop_create_args {
339         struct vnode *a_dvp;
340         struct vnode **a_vpp;
341         struct componentname *a_cnp;
342         struct vattr *a_vap;
343     };
344 */
345 static int
346 fuse_vnop_create(struct vop_create_args *ap)
347 {
348         struct vnode *dvp = ap->a_dvp;
349         struct vnode **vpp = ap->a_vpp;
350         struct componentname *cnp = ap->a_cnp;
351         struct vattr *vap = ap->a_vap;
352         struct thread *td = cnp->cn_thread;
353         struct ucred *cred = cnp->cn_cred;
354
355         struct fuse_open_in *foi;
356         struct fuse_entry_out *feo;
357         struct fuse_open_out *foo;
358         struct fuse_dispatcher fdi, fdi2;
359         struct fuse_dispatcher *fdip = &fdi;
360         struct fuse_dispatcher *fdip2 = NULL;
361
362         int err;
363
364         struct mount *mp = vnode_mount(dvp);
365         uint64_t parentnid = VTOFUD(dvp)->nid;
366         mode_t mode = MAKEIMODE(vap->va_type, vap->va_mode);
367         enum fuse_opcode op;
368         int flags;
369
370         /* 
371          * VOP_CREATE doesn't tell us the open(2) flags, so we guess.  Only a
372          * writable mode makes sense, and we might as well include readability
373          * too.
374          */
375         flags = O_RDWR;
376
377         if (fuse_isdeadfs(dvp)) {
378                 return ENXIO;
379         }
380         bzero(&fdi, sizeof(fdi));
381
382         if ((vap->va_type != VREG))
383                 return (EINVAL);
384
385         if (!fsess_isimpl(mp, FUSE_CREATE)) {
386                 /* Fallback to FUSE_MKNOD/FUSE_OPEN */
387                 fdisp_make_mknod_for_fallback(fdip, cnp, dvp, parentnid, td,
388                         cred, mode, &op);
389         } else {
390                 /* Use FUSE_CREATE */
391                 op = FUSE_CREATE;
392                 fdisp_init(fdip, sizeof(*foi) + cnp->cn_namelen + 1);
393                 fdisp_make(fdip, op, vnode_mount(dvp), parentnid, td, cred);
394                 foi = fdip->indata;
395                 foi->mode = mode;
396                 foi->flags = O_CREAT | flags;
397                 memcpy((char *)fdip->indata + sizeof(*foi), cnp->cn_nameptr,
398                     cnp->cn_namelen);
399                 ((char *)fdip->indata)[sizeof(*foi) + cnp->cn_namelen] = '\0';
400         }
401
402         err = fdisp_wait_answ(fdip);
403
404         if (err) {
405                 if (err == ENOSYS && op == FUSE_CREATE) {
406                         fsess_set_notimpl(mp, FUSE_CREATE);
407                         fdisp_make_mknod_for_fallback(fdip, cnp, dvp,
408                                 parentnid, td, cred, mode, &op);
409                         err = fdisp_wait_answ(fdip);
410                 }
411                 if (err)
412                         goto out;
413         }
414
415         feo = fdip->answ;
416
417         if ((err = fuse_internal_checkentry(feo, VREG))) {
418                 goto out;
419         }
420
421         if (op == FUSE_CREATE) {
422                 foo = (struct fuse_open_out*)(feo + 1);
423         } else {
424                 /* Issue a separate FUSE_OPEN */
425                 fdip2 = &fdi2;
426                 fdisp_init(fdip2, sizeof(*foi));
427                 fdisp_make(fdip2, FUSE_OPEN, vnode_mount(dvp), feo->nodeid, td,
428                         cred);
429                 foi = fdip2->indata;
430                 foi->mode = mode;
431                 foi->flags = flags;
432                 err = fdisp_wait_answ(fdip2);
433                 if (err)
434                         goto out;
435                 foo = fdip2->answ;
436         }
437         err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, VREG);
438         if (err) {
439                 struct fuse_release_in *fri;
440                 uint64_t nodeid = feo->nodeid;
441                 uint64_t fh_id = foo->fh;
442
443                 fdisp_init(fdip, sizeof(*fri));
444                 fdisp_make(fdip, FUSE_RELEASE, mp, nodeid, td, cred);
445                 fri = fdip->indata;
446                 fri->fh = fh_id;
447                 fri->flags = flags;
448                 fuse_insert_callback(fdip->tick, fuse_internal_forget_callback);
449                 fuse_insert_message(fdip->tick);
450                 goto out;
451         }
452         ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create");
453
454         fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td->td_proc->p_pid, cred,
455                 foo);
456         fuse_vnode_open(*vpp, foo->open_flags, td);
457         cache_purge_negative(dvp);
458
459 out:
460         if (fdip2)
461                 fdisp_destroy(fdip2);
462         fdisp_destroy(fdip);
463         return err;
464 }
465
466 /*
467     struct vnop_fdatasync_args {
468         struct vop_generic_args a_gen;
469         struct vnode * a_vp;
470         struct thread * a_td;
471     };
472 */
473 static int
474 fuse_vnop_fdatasync(struct vop_fdatasync_args *ap)
475 {
476         struct vnode *vp = ap->a_vp;
477         struct thread *td = ap->a_td;
478         int waitfor = MNT_WAIT;
479
480         int err = 0;
481
482         if (fuse_isdeadfs(vp)) {
483                 return 0;
484         }
485         if ((err = vop_stdfdatasync_buf(ap)))
486                 return err;
487
488         return fuse_internal_fsync(vp, td, waitfor, true);
489 }
490
491 /*
492     struct vnop_fsync_args {
493         struct vop_generic_args a_gen;
494         struct vnode * a_vp;
495         int  a_waitfor;
496         struct thread * a_td;
497     };
498 */
499 static int
500 fuse_vnop_fsync(struct vop_fsync_args *ap)
501 {
502         struct vnode *vp = ap->a_vp;
503         struct thread *td = ap->a_td;
504         int waitfor = ap->a_waitfor;
505         int err = 0;
506
507         if (fuse_isdeadfs(vp)) {
508                 return 0;
509         }
510         if ((err = vop_stdfsync(ap)))
511                 return err;
512
513         return fuse_internal_fsync(vp, td, waitfor, false);
514 }
515
516 /*
517     struct vnop_getattr_args {
518         struct vnode *a_vp;
519         struct vattr *a_vap;
520         struct ucred *a_cred;
521         struct thread *a_td;
522     };
523 */
524 static int
525 fuse_vnop_getattr(struct vop_getattr_args *ap)
526 {
527         struct vnode *vp = ap->a_vp;
528         struct vattr *vap = ap->a_vap;
529         struct ucred *cred = ap->a_cred;
530         struct thread *td = curthread;
531         struct fuse_vnode_data *fvdat = VTOFUD(vp);
532         struct fuse_attr_out *fao;
533
534         int err = 0;
535         int dataflags;
536         struct fuse_dispatcher fdi;
537
538         dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags;
539
540         /* Note that we are not bailing out on a dead file system just yet. */
541
542         if (!(dataflags & FSESS_INITED)) {
543                 if (!vnode_isvroot(vp)) {
544                         fdata_set_dead(fuse_get_mpdata(vnode_mount(vp)));
545                         err = ENOTCONN;
546                         return err;
547                 } else {
548                         goto fake;
549                 }
550         }
551         fdisp_init(&fdi, 0);
552         if ((err = fdisp_simple_putget_vp(&fdi, FUSE_GETATTR, vp, td, cred))) {
553                 if ((err == ENOTCONN) && vnode_isvroot(vp)) {
554                         /* see comment in fuse_vfsop_statfs() */
555                         fdisp_destroy(&fdi);
556                         goto fake;
557                 }
558                 if (err == ENOENT) {
559                         fuse_internal_vnode_disappear(vp);
560                 }
561                 goto out;
562         }
563
564         fao = (struct fuse_attr_out *)fdi.answ;
565         fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid,
566                 fao->attr_valid_nsec, vap);
567         if (vap->va_type != vnode_vtype(vp)) {
568                 fuse_internal_vnode_disappear(vp);
569                 err = ENOENT;
570                 goto out;
571         }
572         if ((fvdat->flag & FN_SIZECHANGE) != 0)
573                 vap->va_size = fvdat->filesize;
574
575         if (vnode_isreg(vp) && (fvdat->flag & FN_SIZECHANGE) == 0) {
576                 /*
577                  * This is for those cases when the file size changed without us
578                  * knowing, and we want to catch up.
579                  */
580                 off_t new_filesize = ((struct fuse_attr_out *)
581                                       fdi.answ)->attr.size;
582
583                 if (fvdat->filesize != new_filesize) {
584                         fuse_vnode_setsize(vp, cred, new_filesize);
585                         fvdat->flag &= ~FN_SIZECHANGE;
586                 }
587         }
588
589 out:
590         fdisp_destroy(&fdi);
591         return err;
592
593 fake:
594         bzero(vap, sizeof(*vap));
595         vap->va_type = vnode_vtype(vp);
596
597         return 0;
598 }
599
600 /*
601     struct vnop_inactive_args {
602         struct vnode *a_vp;
603         struct thread *a_td;
604     };
605 */
606 static int
607 fuse_vnop_inactive(struct vop_inactive_args *ap)
608 {
609         struct vnode *vp = ap->a_vp;
610         struct thread *td = ap->a_td;
611
612         struct fuse_vnode_data *fvdat = VTOFUD(vp);
613         struct fuse_filehandle *fufh, *fufh_tmp;
614
615         int need_flush = 1;
616
617         LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) {
618                 if (need_flush && vp->v_type == VREG) {
619                         if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) {
620                                 fuse_vnode_savesize(vp, NULL, 0);
621                         }
622                         if (fuse_data_cache_invalidate ||
623                             (fvdat->flag & FN_REVOKED) != 0)
624                                 fuse_io_invalbuf(vp, td);
625                         else
626                                 fuse_io_flushbuf(vp, MNT_WAIT, td);
627                         need_flush = 0;
628                 }
629                 fuse_filehandle_close(vp, fufh, td, NULL);
630         }
631
632         if ((fvdat->flag & FN_REVOKED) != 0 && fuse_reclaim_revoked) {
633                 vrecycle(vp);
634         }
635         return 0;
636 }
637
638 /*
639     struct vnop_link_args {
640         struct vnode *a_tdvp;
641         struct vnode *a_vp;
642         struct componentname *a_cnp;
643     };
644 */
645 static int
646 fuse_vnop_link(struct vop_link_args *ap)
647 {
648         struct vnode *vp = ap->a_vp;
649         struct vnode *tdvp = ap->a_tdvp;
650         struct componentname *cnp = ap->a_cnp;
651
652         struct vattr *vap = VTOVA(vp);
653
654         struct fuse_dispatcher fdi;
655         struct fuse_entry_out *feo;
656         struct fuse_link_in fli;
657
658         int err;
659
660         if (fuse_isdeadfs(vp)) {
661                 return ENXIO;
662         }
663         if (vnode_mount(tdvp) != vnode_mount(vp)) {
664                 return EXDEV;
665         }
666
667         /*
668          * This is a seatbelt check to protect naive userspace filesystems from
669          * themselves and the limitations of the FUSE IPC protocol.  If a
670          * filesystem does not allow attribute caching, assume it is capable of
671          * validating that nlink does not overflow.
672          */
673         if (vap != NULL && vap->va_nlink >= FUSE_LINK_MAX)
674                 return EMLINK;
675         fli.oldnodeid = VTOI(vp);
676
677         fdisp_init(&fdi, 0);
678         fuse_internal_newentry_makerequest(vnode_mount(tdvp), VTOI(tdvp), cnp,
679             FUSE_LINK, &fli, sizeof(fli), &fdi);
680         if ((err = fdisp_wait_answ(&fdi))) {
681                 goto out;
682         }
683         feo = fdi.answ;
684
685         err = fuse_internal_checkentry(feo, vnode_vtype(vp));
686 out:
687         fdisp_destroy(&fdi);
688         return err;
689 }
690
691 /*
692     struct vnop_lookup_args {
693         struct vnodeop_desc *a_desc;
694         struct vnode *a_dvp;
695         struct vnode **a_vpp;
696         struct componentname *a_cnp;
697     };
698 */
699 int
700 fuse_vnop_lookup(struct vop_lookup_args *ap)
701 {
702         struct vnode *dvp = ap->a_dvp;
703         struct vnode **vpp = ap->a_vpp;
704         struct componentname *cnp = ap->a_cnp;
705         struct thread *td = cnp->cn_thread;
706         struct ucred *cred = cnp->cn_cred;
707
708         int nameiop = cnp->cn_nameiop;
709         int flags = cnp->cn_flags;
710         int wantparent = flags & (LOCKPARENT | WANTPARENT);
711         int islastcn = flags & ISLASTCN;
712         struct mount *mp = vnode_mount(dvp);
713
714         int err = 0;
715         int lookup_err = 0;
716         struct vnode *vp = NULL;
717
718         struct fuse_dispatcher fdi;
719         enum fuse_opcode op;
720
721         uint64_t nid;
722         struct fuse_access_param facp;
723
724         if (fuse_isdeadfs(dvp)) {
725                 *vpp = NULL;
726                 return ENXIO;
727         }
728         if (!vnode_isdir(dvp)) {
729                 return ENOTDIR;
730         }
731         if (islastcn && vfs_isrdonly(mp) && (nameiop != LOOKUP)) {
732                 return EROFS;
733         }
734         /*
735          * We do access check prior to doing anything else only in the case
736          * when we are at fs root (we'd like to say, "we are at the first
737          * component", but that's not exactly the same... nevermind).
738          * See further comments at further access checks.
739          */
740
741         bzero(&facp, sizeof(facp));
742         if (vnode_isvroot(dvp)) {       /* early permission check hack */
743                 if ((err = fuse_internal_access(dvp, VEXEC, &facp, td, cred))) {
744                         return err;
745                 }
746         }
747         if (flags & ISDOTDOT) {
748                 nid = VTOFUD(dvp)->parent_nid;
749                 if (nid == 0) {
750                         return ENOENT;
751                 }
752                 fdisp_init(&fdi, 0);
753                 op = FUSE_GETATTR;
754                 goto calldaemon;
755         } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
756                 nid = VTOI(dvp);
757                 fdisp_init(&fdi, 0);
758                 op = FUSE_GETATTR;
759                 goto calldaemon;
760         } else if (fuse_lookup_cache_enable) {
761                 err = cache_lookup(dvp, vpp, cnp, NULL, NULL);
762                 switch (err) {
763
764                 case -1:                /* positive match */
765                         atomic_add_acq_long(&fuse_lookup_cache_hits, 1);
766                         return 0;
767
768                 case 0:         /* no match in cache */
769                         atomic_add_acq_long(&fuse_lookup_cache_misses, 1);
770                         break;
771
772                 case ENOENT:            /* negative match */
773                         /* fall through */
774                 default:
775                         return err;
776                 }
777         }
778         nid = VTOI(dvp);
779         fdisp_init(&fdi, cnp->cn_namelen + 1);
780         op = FUSE_LOOKUP;
781
782 calldaemon:
783         fdisp_make(&fdi, op, mp, nid, td, cred);
784
785         if (op == FUSE_LOOKUP) {
786                 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen);
787                 ((char *)fdi.indata)[cnp->cn_namelen] = '\0';
788         }
789         lookup_err = fdisp_wait_answ(&fdi);
790
791         if ((op == FUSE_LOOKUP) && !lookup_err) {       /* lookup call succeeded */
792                 nid = ((struct fuse_entry_out *)fdi.answ)->nodeid;
793                 if (!nid) {
794                         /*
795                          * zero nodeid is the same as "not found",
796                          * but it's also cacheable (which we keep
797                          * keep on doing not as of writing this)
798                          */
799                         fdi.answ_stat = ENOENT;
800                         lookup_err = ENOENT;
801                 } else if (nid == FUSE_ROOT_ID) {
802                         lookup_err = EINVAL;
803                 }
804         }
805         if (lookup_err &&
806             (!fdi.answ_stat || lookup_err != ENOENT || op != FUSE_LOOKUP)) {
807                 fdisp_destroy(&fdi);
808                 return lookup_err;
809         }
810         /* lookup_err, if non-zero, must be ENOENT at this point */
811
812         if (lookup_err) {
813
814                 if ((nameiop == CREATE || nameiop == RENAME) && islastcn
815                      /* && directory dvp has not been removed */ ) {
816
817                         if (vfs_isrdonly(mp)) {
818                                 err = EROFS;
819                                 goto out;
820                         }
821 #if 0 /* THINK_ABOUT_THIS */
822                         if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) {
823                                 goto out;
824                         }
825 #endif
826
827                         /*
828                          * Possibly record the position of a slot in the
829                          * directory large enough for the new component name.
830                          * This can be recorded in the vnode private data for
831                          * dvp. Set the SAVENAME flag to hold onto the
832                          * pathname for use later in VOP_CREATE or VOP_RENAME.
833                          */
834                         cnp->cn_flags |= SAVENAME;
835
836                         err = EJUSTRETURN;
837                         goto out;
838                 }
839                 /* Consider inserting name into cache. */
840
841                 /*
842                  * No we can't use negative caching, as the fs
843                  * changes are out of our control.
844                  * False positives' falseness turns out just as things
845                  * go by, but false negatives' falseness doesn't.
846                  * (and aiding the caching mechanism with extra control
847                  * mechanisms comes quite close to beating the whole purpose
848                  * caching...)
849                  */
850 #if 0
851                 if ((cnp->cn_flags & MAKEENTRY) != 0) {
852                         SDT_PROBE2(fuse, , vnops, trace, 1,
853                                 "inserting NULL into cache");
854                         cache_enter(dvp, NULL, cnp);
855                 }
856 #endif
857                 err = ENOENT;
858                 goto out;
859
860         } else {
861
862                 /* !lookup_err */
863
864                 struct fuse_entry_out *feo = NULL;
865                 struct fuse_attr *fattr = NULL;
866
867                 if (op == FUSE_GETATTR) {
868                         fattr = &((struct fuse_attr_out *)fdi.answ)->attr;
869                 } else {
870                         feo = (struct fuse_entry_out *)fdi.answ;
871                         fattr = &(feo->attr);
872                 }
873
874                 /*
875                  * If deleting, and at end of pathname, return parameters
876                  * which can be used to remove file.  If the wantparent flag
877                  * isn't set, we return only the directory, otherwise we go on
878                  * and lock the inode, being careful with ".".
879                  */
880                 if (nameiop == DELETE && islastcn) {
881                         /*
882                          * Check for write access on directory.
883                          */
884                         facp.xuid = fattr->uid;
885                         facp.facc_flags |= FACCESS_STICKY;
886                         err = fuse_internal_access(dvp, VWRITE, &facp, td, cred);
887                         facp.facc_flags &= ~FACCESS_XQUERIES;
888
889                         if (err) {
890                                 goto out;
891                         }
892                         if (nid == VTOI(dvp)) {
893                                 vref(dvp);
894                                 *vpp = dvp;
895                         } else {
896                                 err = fuse_vnode_get(dvp->v_mount, feo, nid,
897                                     dvp, &vp, cnp, IFTOVT(fattr->mode));
898                                 if (err)
899                                         goto out;
900                                 *vpp = vp;
901                         }
902
903                         /*
904                          * Save the name for use in VOP_RMDIR and VOP_REMOVE
905                          * later.
906                          */
907                         cnp->cn_flags |= SAVENAME;
908                         goto out;
909
910                 }
911                 /*
912                  * If rewriting (RENAME), return the inode and the
913                  * information required to rewrite the present directory
914                  * Must get inode of directory entry to verify it's a
915                  * regular file, or empty directory.
916                  */
917                 if (nameiop == RENAME && wantparent && islastcn) {
918
919 #if 0 /* THINK_ABOUT_THIS */
920                         if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) {
921                                 goto out;
922                         }
923 #endif
924
925                         /*
926                          * Check for "."
927                          */
928                         if (nid == VTOI(dvp)) {
929                                 err = EISDIR;
930                                 goto out;
931                         }
932                         err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
933                             &vp, cnp, IFTOVT(fattr->mode));
934                         if (err) {
935                                 goto out;
936                         }
937                         *vpp = vp;
938                         /*
939                          * Save the name for use in VOP_RENAME later.
940                          */
941                         cnp->cn_flags |= SAVENAME;
942
943                         goto out;
944                 }
945                 if (flags & ISDOTDOT) {
946                         struct mount *mp;
947                         int ltype;
948
949                         /*
950                          * Expanded copy of vn_vget_ino() so that
951                          * fuse_vnode_get() can be used.
952                          */
953                         mp = dvp->v_mount;
954                         ltype = VOP_ISLOCKED(dvp);
955                         err = vfs_busy(mp, MBF_NOWAIT);
956                         if (err != 0) {
957                                 vfs_ref(mp);
958                                 VOP_UNLOCK(dvp, 0);
959                                 err = vfs_busy(mp, 0);
960                                 vn_lock(dvp, ltype | LK_RETRY);
961                                 vfs_rel(mp);
962                                 if (err)
963                                         goto out;
964                                 if ((dvp->v_iflag & VI_DOOMED) != 0) {
965                                         err = ENOENT;
966                                         vfs_unbusy(mp);
967                                         goto out;
968                                 }
969                         }
970                         VOP_UNLOCK(dvp, 0);
971                         err = fuse_vnode_get(vnode_mount(dvp), feo, nid, NULL,
972                             &vp, cnp, IFTOVT(fattr->mode));
973                         vfs_unbusy(mp);
974                         vn_lock(dvp, ltype | LK_RETRY);
975                         if ((dvp->v_iflag & VI_DOOMED) != 0) {
976                                 if (err == 0)
977                                         vput(vp);
978                                 err = ENOENT;
979                         }
980                         if (err)
981                                 goto out;
982                         *vpp = vp;
983                 } else if (nid == VTOI(dvp)) {
984                         vref(dvp);
985                         *vpp = dvp;
986                 } else {
987                         struct fuse_vnode_data *fvdat;
988
989                         err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
990                             &vp, cnp, IFTOVT(fattr->mode));
991                         if (err) {
992                                 goto out;
993                         }
994                         fuse_vnode_setparent(vp, dvp);
995
996                         /*
997                          * In the case where we are looking up a FUSE node
998                          * represented by an existing cached vnode, and the
999                          * true size reported by FUSE_LOOKUP doesn't match
1000                          * the vnode's cached size, fix the vnode cache to
1001                          * match the real object size.
1002                          *
1003                          * This can occur via FUSE distributed filesystems,
1004                          * irregular files, etc.
1005                          */
1006                         fvdat = VTOFUD(vp);
1007                         if (vnode_isreg(vp) &&
1008                             fattr->size != fvdat->filesize) {
1009                                 /*
1010                                  * The FN_SIZECHANGE flag reflects a dirty
1011                                  * append.  If userspace lets us know our cache
1012                                  * is invalid, that write was lost.  (Dirty
1013                                  * writes that do not cause append are also
1014                                  * lost, but we don't detect them here.)
1015                                  *
1016                                  * XXX: Maybe disable WB caching on this mount.
1017                                  */
1018                                 if (fvdat->flag & FN_SIZECHANGE)
1019                                         printf("%s: WB cache incoherent on "
1020                                             "%s!\n", __func__,
1021                                             vnode_mount(vp)->mnt_stat.f_mntonname);
1022
1023                                 (void)fuse_vnode_setsize(vp, cred, fattr->size);
1024                                 fvdat->flag &= ~FN_SIZECHANGE;
1025                         }
1026                         *vpp = vp;
1027                 }
1028
1029                 if (op == FUSE_GETATTR) {
1030                         struct fuse_attr_out *fao =
1031                                 (struct fuse_attr_out*)fdi.answ;
1032                         fuse_internal_cache_attrs(*vpp,
1033                                 &fao->attr, fao->attr_valid,
1034                                 fao->attr_valid_nsec, NULL);
1035                 } else {
1036                         struct fuse_entry_out *feo =
1037                                 (struct fuse_entry_out*)fdi.answ;
1038                         fuse_internal_cache_attrs(*vpp,
1039                                 &feo->attr, feo->attr_valid,
1040                                 feo->attr_valid_nsec, NULL);
1041                 }
1042
1043                 /* Insert name into cache if appropriate. */
1044
1045                 /*
1046                  * Nooo, caching is evil. With caching, we can't avoid stale
1047                  * information taking over the playground (cached info is not
1048                  * just positive/negative, it does have qualitative aspects,
1049                  * too). And a (VOP/FUSE)_GETATTR is always thrown anyway, when
1050                  * walking down along cached path components, and that's not
1051                  * any cheaper than FUSE_LOOKUP. This might change with
1052                  * implementing kernel side attr caching, but... In Linux,
1053                  * lookup results are not cached, and the daemon is bombarded
1054                  * with FUSE_LOOKUPS on and on. This shows that by design, the
1055                  * daemon is expected to handle frequent lookup queries
1056                  * efficiently, do its caching in userspace, and so on.
1057                  *
1058                  * So just leave the name cache alone.
1059                  */
1060
1061                 /*
1062                  * Well, now I know, Linux caches lookups, but with a
1063                  * timeout... So it's the same thing as attribute caching:
1064                  * we can deal with it when implement timeouts.
1065                  */
1066 #if 0
1067                 if (cnp->cn_flags & MAKEENTRY) {
1068                         cache_enter(dvp, *vpp, cnp);
1069                 }
1070 #endif
1071         }
1072 out:
1073         if (!lookup_err) {
1074
1075                 /* No lookup error; need to clean up. */
1076
1077                 if (err) {              /* Found inode; exit with no vnode. */
1078                         if (op == FUSE_LOOKUP) {
1079                                 fuse_internal_forget_send(vnode_mount(dvp), td, cred,
1080                                     nid, 1);
1081                         }
1082                         fdisp_destroy(&fdi);
1083                         return err;
1084                 } else {
1085 #ifndef NO_EARLY_PERM_CHECK_HACK
1086                         if (!islastcn) {
1087                                 /*
1088                                  * We have the attributes of the next item
1089                                  * *now*, and it's a fact, and we do not
1090                                  * have to do extra work for it (ie, beg the
1091                                  * daemon), and it neither depends on such
1092                                  * accidental things like attr caching. So
1093                                  * the big idea: check credentials *now*,
1094                                  * not at the beginning of the next call to
1095                                  * lookup.
1096                                  * 
1097                                  * The first item of the lookup chain (fs root)
1098                                  * won't be checked then here, of course, as
1099                                  * its never "the next". But go and see that
1100                                  * the root is taken care about at the very
1101                                  * beginning of this function.
1102                                  * 
1103                                  * Now, given we want to do the access check
1104                                  * this way, one might ask: so then why not
1105                                  * do the access check just after fetching
1106                                  * the inode and its attributes from the
1107                                  * daemon? Why bother with producing the
1108                                  * corresponding vnode at all if something
1109                                  * is not OK? We know what's the deal as
1110                                  * soon as we get those attrs... There is
1111                                  * one bit of info though not given us by
1112                                  * the daemon: whether his response is
1113                                  * authoritative or not... His response should
1114                                  * be ignored if something is mounted over
1115                                  * the dir in question. But that can be
1116                                  * known only by having the vnode...
1117                                  */
1118                                 int tmpvtype = vnode_vtype(*vpp);
1119
1120                                 bzero(&facp, sizeof(facp));
1121                                 /*the early perm check hack */
1122                                     facp.facc_flags |= FACCESS_VA_VALID;
1123
1124                                 if ((tmpvtype != VDIR) && (tmpvtype != VLNK)) {
1125                                         err = ENOTDIR;
1126                                 }
1127                                 if (!err && !vnode_mountedhere(*vpp)) {
1128                                         err = fuse_internal_access(*vpp, VEXEC, &facp, td, cred);
1129                                 }
1130                                 if (err) {
1131                                         if (tmpvtype == VLNK)
1132                                                 SDT_PROBE2(fuse, , vnops, trace,
1133                                                     1, "weird, permission "
1134                                                     "error with a symlink?");
1135                                         vput(*vpp);
1136                                         *vpp = NULL;
1137                                 }
1138                         }
1139 #endif
1140                 }
1141         }
1142         fdisp_destroy(&fdi);
1143
1144         return err;
1145 }
1146
1147 /*
1148     struct vnop_mkdir_args {
1149         struct vnode *a_dvp;
1150         struct vnode **a_vpp;
1151         struct componentname *a_cnp;
1152         struct vattr *a_vap;
1153     };
1154 */
1155 static int
1156 fuse_vnop_mkdir(struct vop_mkdir_args *ap)
1157 {
1158         struct vnode *dvp = ap->a_dvp;
1159         struct vnode **vpp = ap->a_vpp;
1160         struct componentname *cnp = ap->a_cnp;
1161         struct vattr *vap = ap->a_vap;
1162
1163         struct fuse_mkdir_in fmdi;
1164
1165         if (fuse_isdeadfs(dvp)) {
1166                 return ENXIO;
1167         }
1168         fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);
1169
1170         return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi,
1171             sizeof(fmdi), VDIR));
1172 }
1173
1174 /*
1175     struct vnop_mknod_args {
1176         struct vnode *a_dvp;
1177         struct vnode **a_vpp;
1178         struct componentname *a_cnp;
1179         struct vattr *a_vap;
1180     };
1181 */
1182 static int
1183 fuse_vnop_mknod(struct vop_mknod_args *ap)
1184 {
1185
1186         struct vnode *dvp = ap->a_dvp;
1187         struct vnode **vpp = ap->a_vpp;
1188         struct componentname *cnp = ap->a_cnp;
1189         struct vattr *vap = ap->a_vap;
1190         struct fuse_mknod_in fmni;
1191
1192         if (fuse_isdeadfs(dvp))
1193                 return ENXIO;
1194
1195         fmni.mode = MAKEIMODE(vap->va_type, vap->va_mode);
1196         fmni.rdev = vap->va_rdev;
1197         return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKNOD, &fmni,
1198             sizeof(fmni), vap->va_type));
1199 }
1200
1201 /*
1202     struct vnop_open_args {
1203         struct vnode *a_vp;
1204         int  a_mode;
1205         struct ucred *a_cred;
1206         struct thread *a_td;
1207         int a_fdidx; / struct file *a_fp;
1208     };
1209 */
1210 static int
1211 fuse_vnop_open(struct vop_open_args *ap)
1212 {
1213         struct vnode *vp = ap->a_vp;
1214         int a_mode = ap->a_mode;
1215         struct thread *td = ap->a_td;
1216         struct ucred *cred = ap->a_cred;
1217         pid_t pid = td->td_proc->p_pid;
1218         struct fuse_vnode_data *fvdat;
1219
1220         if (fuse_isdeadfs(vp))
1221                 return ENXIO;
1222         if (vp->v_type == VCHR || vp->v_type == VBLK || vp->v_type == VFIFO)
1223                 return (EOPNOTSUPP);
1224         if ((a_mode & (FREAD | FWRITE | FEXEC)) == 0)
1225                 return EINVAL;
1226
1227         fvdat = VTOFUD(vp);
1228
1229         if (fuse_filehandle_validrw(vp, a_mode, cred, pid)) {
1230                 fuse_vnode_open(vp, 0, td);
1231                 return 0;
1232         }
1233
1234         return fuse_filehandle_open(vp, a_mode, NULL, td, cred);
1235 }
1236
1237 static int
1238 fuse_vnop_pathconf(struct vop_pathconf_args *ap)
1239 {
1240
1241         switch (ap->a_name) {
1242         case _PC_FILESIZEBITS:
1243                 *ap->a_retval = 64;
1244                 return (0);
1245         case _PC_NAME_MAX:
1246                 *ap->a_retval = NAME_MAX;
1247                 return (0);
1248         case _PC_LINK_MAX:
1249                 *ap->a_retval = MIN(LONG_MAX, FUSE_LINK_MAX);
1250                 return (0);
1251         case _PC_SYMLINK_MAX:
1252                 *ap->a_retval = MAXPATHLEN;
1253                 return (0);
1254         case _PC_NO_TRUNC:
1255                 *ap->a_retval = 1;
1256                 return (0);
1257         default:
1258                 return (vop_stdpathconf(ap));
1259         }
1260 }
1261
1262 /*
1263     struct vnop_read_args {
1264         struct vnode *a_vp;
1265         struct uio *a_uio;
1266         int  a_ioflag;
1267         struct ucred *a_cred;
1268     };
1269 */
1270 static int
1271 fuse_vnop_read(struct vop_read_args *ap)
1272 {
1273         struct vnode *vp = ap->a_vp;
1274         struct uio *uio = ap->a_uio;
1275         int ioflag = ap->a_ioflag;
1276         struct ucred *cred = ap->a_cred;
1277         pid_t pid = curthread->td_proc->p_pid;
1278
1279         if (fuse_isdeadfs(vp)) {
1280                 return ENXIO;
1281         }
1282
1283         if (VTOFUD(vp)->flag & FN_DIRECTIO) {
1284                 ioflag |= IO_DIRECT;
1285         }
1286
1287         return fuse_io_dispatch(vp, uio, ioflag, cred, pid);
1288 }
1289
1290 /*
1291     struct vnop_readdir_args {
1292         struct vnode *a_vp;
1293         struct uio *a_uio;
1294         struct ucred *a_cred;
1295         int *a_eofflag;
1296         int *ncookies;
1297         u_long **a_cookies;
1298     };
1299 */
1300 static int
1301 fuse_vnop_readdir(struct vop_readdir_args *ap)
1302 {
1303         struct vnode *vp = ap->a_vp;
1304         struct uio *uio = ap->a_uio;
1305         struct ucred *cred = ap->a_cred;
1306         struct fuse_filehandle *fufh = NULL;
1307         struct fuse_iov cookediov;
1308         int err = 0;
1309         int freefufh = 0;
1310         pid_t pid = curthread->td_proc->p_pid;
1311
1312         if (fuse_isdeadfs(vp)) {
1313                 return ENXIO;
1314         }
1315         if (                            /* XXXIP ((uio_iovcnt(uio) > 1)) || */
1316             (uio_resid(uio) < sizeof(struct dirent))) {
1317                 return EINVAL;
1318         }
1319
1320         if ((err = fuse_filehandle_get_dir(vp, &fufh, cred, pid)) != 0) {
1321                 SDT_PROBE2(fuse, , vnops, trace, 1,
1322                         "calling readdir() before open()");
1323                 /* 
1324                  * This was seen to happen in getdirentries as used by
1325                  * shells/fish, but I can't reproduce it.
1326                  */
1327                 err = fuse_filehandle_open(vp, FREAD, &fufh, NULL, cred);
1328                 freefufh = 1;
1329         }
1330         if (err) {
1331                 return (err);
1332         }
1333 #define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1)
1334         fiov_init(&cookediov, DIRCOOKEDSIZE);
1335
1336         err = fuse_internal_readdir(vp, uio, fufh, &cookediov);
1337
1338         fiov_teardown(&cookediov);
1339         if (freefufh)
1340                 fuse_filehandle_close(vp, fufh, NULL, cred);
1341
1342         return err;
1343 }
1344
1345 /*
1346     struct vnop_readlink_args {
1347         struct vnode *a_vp;
1348         struct uio *a_uio;
1349         struct ucred *a_cred;
1350     };
1351 */
1352 static int
1353 fuse_vnop_readlink(struct vop_readlink_args *ap)
1354 {
1355         struct vnode *vp = ap->a_vp;
1356         struct uio *uio = ap->a_uio;
1357         struct ucred *cred = ap->a_cred;
1358
1359         struct fuse_dispatcher fdi;
1360         int err;
1361
1362         if (fuse_isdeadfs(vp)) {
1363                 return ENXIO;
1364         }
1365         if (!vnode_islnk(vp)) {
1366                 return EINVAL;
1367         }
1368         fdisp_init(&fdi, 0);
1369         err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred);
1370         if (err) {
1371                 goto out;
1372         }
1373         if (((char *)fdi.answ)[0] == '/' &&
1374             fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_PUSH_SYMLINKS_IN) {
1375                 char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname;
1376
1377                 err = uiomove(mpth, strlen(mpth), uio);
1378         }
1379         if (!err) {
1380                 err = uiomove(fdi.answ, fdi.iosize, uio);
1381         }
1382 out:
1383         fdisp_destroy(&fdi);
1384         return err;
1385 }
1386
1387 /*
1388     struct vnop_reclaim_args {
1389         struct vnode *a_vp;
1390         struct thread *a_td;
1391     };
1392 */
1393 static int
1394 fuse_vnop_reclaim(struct vop_reclaim_args *ap)
1395 {
1396         struct vnode *vp = ap->a_vp;
1397         struct thread *td = ap->a_td;
1398         struct fuse_vnode_data *fvdat = VTOFUD(vp);
1399         struct fuse_filehandle *fufh, *fufh_tmp;
1400
1401         if (!fvdat) {
1402                 panic("FUSE: no vnode data during recycling");
1403         }
1404         LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) {
1405                 printf("FUSE: vnode being reclaimed with open fufh "
1406                         "(type=%#x)", fufh->fufh_type);
1407                 fuse_filehandle_close(vp, fufh, td, NULL);
1408         }
1409
1410         if ((!fuse_isdeadfs(vp)) && (fvdat->nlookup)) {
1411                 fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp),
1412                     fvdat->nlookup);
1413         }
1414         fuse_vnode_setparent(vp, NULL);
1415         cache_purge(vp);
1416         vfs_hash_remove(vp);
1417         vnode_destroy_vobject(vp);
1418         fuse_vnode_destroy(vp);
1419
1420         return 0;
1421 }
1422
1423 /*
1424     struct vnop_remove_args {
1425         struct vnode *a_dvp;
1426         struct vnode *a_vp;
1427         struct componentname *a_cnp;
1428     };
1429 */
1430 static int
1431 fuse_vnop_remove(struct vop_remove_args *ap)
1432 {
1433         struct vnode *dvp = ap->a_dvp;
1434         struct vnode *vp = ap->a_vp;
1435         struct componentname *cnp = ap->a_cnp;
1436
1437         int err;
1438
1439         if (fuse_isdeadfs(vp)) {
1440                 return ENXIO;
1441         }
1442         if (vnode_isdir(vp)) {
1443                 return EPERM;
1444         }
1445         cache_purge(vp);
1446
1447         err = fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK);
1448
1449         if (err == 0)
1450                 fuse_internal_vnode_disappear(vp);
1451         return err;
1452 }
1453
1454 /*
1455     struct vnop_rename_args {
1456         struct vnode *a_fdvp;
1457         struct vnode *a_fvp;
1458         struct componentname *a_fcnp;
1459         struct vnode *a_tdvp;
1460         struct vnode *a_tvp;
1461         struct componentname *a_tcnp;
1462     };
1463 */
1464 static int
1465 fuse_vnop_rename(struct vop_rename_args *ap)
1466 {
1467         struct vnode *fdvp = ap->a_fdvp;
1468         struct vnode *fvp = ap->a_fvp;
1469         struct componentname *fcnp = ap->a_fcnp;
1470         struct vnode *tdvp = ap->a_tdvp;
1471         struct vnode *tvp = ap->a_tvp;
1472         struct componentname *tcnp = ap->a_tcnp;
1473         struct fuse_data *data;
1474
1475         int err = 0;
1476
1477         if (fuse_isdeadfs(fdvp)) {
1478                 return ENXIO;
1479         }
1480         if (fvp->v_mount != tdvp->v_mount ||
1481             (tvp && fvp->v_mount != tvp->v_mount)) {
1482                 SDT_PROBE2(fuse, , vnops, trace, 1, "cross-device rename");
1483                 err = EXDEV;
1484                 goto out;
1485         }
1486         cache_purge(fvp);
1487
1488         /*
1489          * FUSE library is expected to check if target directory is not
1490          * under the source directory in the file system tree.
1491          * Linux performs this check at VFS level.
1492          */
1493         data = fuse_get_mpdata(vnode_mount(tdvp));
1494         sx_xlock(&data->rename_lock);
1495         err = fuse_internal_rename(fdvp, fcnp, tdvp, tcnp);
1496         if (err == 0) {
1497                 if (tdvp != fdvp)
1498                         fuse_vnode_setparent(fvp, tdvp);
1499                 if (tvp != NULL)
1500                         fuse_vnode_setparent(tvp, NULL);
1501         }
1502         sx_unlock(&data->rename_lock);
1503
1504         if (tvp != NULL && tvp != fvp) {
1505                 cache_purge(tvp);
1506         }
1507         if (vnode_isdir(fvp)) {
1508                 if ((tvp != NULL) && vnode_isdir(tvp)) {
1509                         cache_purge(tdvp);
1510                 }
1511                 cache_purge(fdvp);
1512         }
1513 out:
1514         if (tdvp == tvp) {
1515                 vrele(tdvp);
1516         } else {
1517                 vput(tdvp);
1518         }
1519         if (tvp != NULL) {
1520                 vput(tvp);
1521         }
1522         vrele(fdvp);
1523         vrele(fvp);
1524
1525         return err;
1526 }
1527
1528 /*
1529     struct vnop_rmdir_args {
1530             struct vnode *a_dvp;
1531             struct vnode *a_vp;
1532             struct componentname *a_cnp;
1533     } *ap;
1534 */
1535 static int
1536 fuse_vnop_rmdir(struct vop_rmdir_args *ap)
1537 {
1538         struct vnode *dvp = ap->a_dvp;
1539         struct vnode *vp = ap->a_vp;
1540
1541         int err;
1542
1543         if (fuse_isdeadfs(vp)) {
1544                 return ENXIO;
1545         }
1546         if (VTOFUD(vp) == VTOFUD(dvp)) {
1547                 return EINVAL;
1548         }
1549         err = fuse_internal_remove(dvp, vp, ap->a_cnp, FUSE_RMDIR);
1550
1551         if (err == 0)
1552                 fuse_internal_vnode_disappear(vp);
1553         return err;
1554 }
1555
1556 /*
1557     struct vnop_setattr_args {
1558         struct vnode *a_vp;
1559         struct vattr *a_vap;
1560         struct ucred *a_cred;
1561         struct thread *a_td;
1562     };
1563 */
1564 static int
1565 fuse_vnop_setattr(struct vop_setattr_args *ap)
1566 {
1567         struct vnode *vp = ap->a_vp;
1568         struct vattr *vap = ap->a_vap;
1569         struct ucred *cred = ap->a_cred;
1570         struct thread *td = curthread;
1571         struct fuse_dispatcher fdi;
1572         struct fuse_setattr_in *fsai;
1573         struct fuse_access_param facp;
1574         pid_t pid = td->td_proc->p_pid;
1575
1576         int err = 0;
1577         enum vtype vtyp;
1578         int sizechanged = 0;
1579         uint64_t newsize = 0;
1580
1581         if (fuse_isdeadfs(vp)) {
1582                 return ENXIO;
1583         }
1584         fdisp_init(&fdi, sizeof(*fsai));
1585         fdisp_make_vp(&fdi, FUSE_SETATTR, vp, td, cred);
1586         fsai = fdi.indata;
1587         fsai->valid = 0;
1588
1589         bzero(&facp, sizeof(facp));
1590
1591         facp.xuid = vap->va_uid;
1592         facp.xgid = vap->va_gid;
1593
1594         if (vap->va_uid != (uid_t)VNOVAL) {
1595                 facp.facc_flags |= FACCESS_CHOWN;
1596                 fsai->uid = vap->va_uid;
1597                 fsai->valid |= FATTR_UID;
1598         }
1599         if (vap->va_gid != (gid_t)VNOVAL) {
1600                 facp.facc_flags |= FACCESS_CHOWN;
1601                 fsai->gid = vap->va_gid;
1602                 fsai->valid |= FATTR_GID;
1603         }
1604         if (vap->va_size != VNOVAL) {
1605
1606                 struct fuse_filehandle *fufh = NULL;
1607
1608                 /*Truncate to a new value. */
1609                     fsai->size = vap->va_size;
1610                 sizechanged = 1;
1611                 newsize = vap->va_size;
1612                 fsai->valid |= FATTR_SIZE;
1613
1614                 fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh, cred, pid);
1615                 if (fufh) {
1616                         fsai->fh = fufh->fh_id;
1617                         fsai->valid |= FATTR_FH;
1618                 }
1619         }
1620         if (vap->va_atime.tv_sec != VNOVAL) {
1621                 fsai->atime = vap->va_atime.tv_sec;
1622                 fsai->atimensec = vap->va_atime.tv_nsec;
1623                 fsai->valid |= FATTR_ATIME;
1624         }
1625         if (vap->va_mtime.tv_sec != VNOVAL) {
1626                 fsai->mtime = vap->va_mtime.tv_sec;
1627                 fsai->mtimensec = vap->va_mtime.tv_nsec;
1628                 fsai->valid |= FATTR_MTIME;
1629         }
1630         if (vap->va_mode != (mode_t)VNOVAL) {
1631                 fsai->mode = vap->va_mode & ALLPERMS;
1632                 fsai->valid |= FATTR_MODE;
1633         }
1634         if (!fsai->valid) {
1635                 goto out;
1636         }
1637         vtyp = vnode_vtype(vp);
1638
1639         if (fsai->valid & FATTR_SIZE && vtyp == VDIR) {
1640                 err = EISDIR;
1641                 goto out;
1642         }
1643         if (vfs_isrdonly(vnode_mount(vp)) && (fsai->valid & ~FATTR_SIZE || vtyp == VREG)) {
1644                 err = EROFS;
1645                 goto out;
1646         }
1647
1648         if ((err = fdisp_wait_answ(&fdi)))
1649                 goto out;
1650         vtyp = IFTOVT(((struct fuse_attr_out *)fdi.answ)->attr.mode);
1651
1652         if (vnode_vtype(vp) != vtyp) {
1653                 if (vnode_vtype(vp) == VNON && vtyp != VNON) {
1654                         SDT_PROBE2(fuse, , vnops, trace, 1, "FUSE: Dang! "
1655                                 "vnode_vtype is VNON and vtype isn't.");
1656                 } else {
1657                         /*
1658                          * STALE vnode, ditch
1659                          *
1660                          * The vnode has changed its type "behind our back".
1661                          * There's nothing really we can do, so let us just
1662                          * force an internal revocation and tell the caller to
1663                          * try again, if interested.
1664                          */
1665                         fuse_internal_vnode_disappear(vp);
1666                         err = EAGAIN;
1667                 }
1668         }
1669         if (err == 0) {
1670                 struct fuse_attr_out *fao = (struct fuse_attr_out*)fdi.answ;
1671                 fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid,
1672                         fao->attr_valid_nsec, NULL);
1673         }
1674
1675 out:
1676         fdisp_destroy(&fdi);
1677         if (!err && sizechanged) {
1678                 fuse_vnode_setsize(vp, cred, newsize);
1679                 VTOFUD(vp)->flag &= ~FN_SIZECHANGE;
1680         }
1681         return err;
1682 }
1683
1684 /*
1685     struct vnop_strategy_args {
1686         struct vnode *a_vp;
1687         struct buf *a_bp;
1688     };
1689 */
1690 static int
1691 fuse_vnop_strategy(struct vop_strategy_args *ap)
1692 {
1693         struct vnode *vp = ap->a_vp;
1694         struct buf *bp = ap->a_bp;
1695
1696         if (!vp || fuse_isdeadfs(vp)) {
1697                 bp->b_ioflags |= BIO_ERROR;
1698                 bp->b_error = ENXIO;
1699                 bufdone(bp);
1700                 return 0;
1701         }
1702         if (bp->b_iocmd == BIO_WRITE) {
1703                 int err;
1704
1705                 err = fuse_vnode_refreshsize(vp, NOCRED);
1706                 if (err) {
1707                         bp->b_ioflags |= BIO_ERROR;
1708                         bp->b_error = err;
1709                         bufdone(bp);
1710                         return 0;
1711                 }
1712         }
1713
1714         /*
1715          * VOP_STRATEGY always returns zero and signals error via bp->b_ioflags.
1716          * fuse_io_strategy sets bp's error fields
1717          */
1718         (void)fuse_io_strategy(vp, bp);
1719
1720         return 0;
1721 }
1722
1723
1724 /*
1725     struct vnop_symlink_args {
1726         struct vnode *a_dvp;
1727         struct vnode **a_vpp;
1728         struct componentname *a_cnp;
1729         struct vattr *a_vap;
1730         char *a_target;
1731     };
1732 */
1733 static int
1734 fuse_vnop_symlink(struct vop_symlink_args *ap)
1735 {
1736         struct vnode *dvp = ap->a_dvp;
1737         struct vnode **vpp = ap->a_vpp;
1738         struct componentname *cnp = ap->a_cnp;
1739         const char *target = ap->a_target;
1740
1741         struct fuse_dispatcher fdi;
1742
1743         int err;
1744         size_t len;
1745
1746         if (fuse_isdeadfs(dvp)) {
1747                 return ENXIO;
1748         }
1749         /*
1750          * Unlike the other creator type calls, here we have to create a message
1751          * where the name of the new entry comes first, and the data describing
1752          * the entry comes second.
1753          * Hence we can't rely on our handy fuse_internal_newentry() routine,
1754          * but put together the message manually and just call the core part.
1755          */
1756
1757         len = strlen(target) + 1;
1758         fdisp_init(&fdi, len + cnp->cn_namelen + 1);
1759         fdisp_make_vp(&fdi, FUSE_SYMLINK, dvp, curthread, NULL);
1760
1761         memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen);
1762         ((char *)fdi.indata)[cnp->cn_namelen] = '\0';
1763         memcpy((char *)fdi.indata + cnp->cn_namelen + 1, target, len);
1764
1765         err = fuse_internal_newentry_core(dvp, vpp, cnp, VLNK, &fdi);
1766         fdisp_destroy(&fdi);
1767         return err;
1768 }
1769
1770 /*
1771     struct vnop_write_args {
1772         struct vnode *a_vp;
1773         struct uio *a_uio;
1774         int  a_ioflag;
1775         struct ucred *a_cred;
1776     };
1777 */
1778 static int
1779 fuse_vnop_write(struct vop_write_args *ap)
1780 {
1781         struct vnode *vp = ap->a_vp;
1782         struct uio *uio = ap->a_uio;
1783         int ioflag = ap->a_ioflag;
1784         struct ucred *cred = ap->a_cred;
1785         pid_t pid = curthread->td_proc->p_pid;
1786         int err;
1787
1788         if (fuse_isdeadfs(vp)) {
1789                 return ENXIO;
1790         }
1791         err = fuse_vnode_refreshsize(vp, cred);
1792         if (err)
1793                 return err;
1794
1795         if (VTOFUD(vp)->flag & FN_DIRECTIO) {
1796                 ioflag |= IO_DIRECT;
1797         }
1798
1799         return fuse_io_dispatch(vp, uio, ioflag, cred, pid);
1800 }
1801
1802 SDT_PROBE_DEFINE1(fuse, , vnops, vnop_getpages_error, "int");
1803 /*
1804     struct vnop_getpages_args {
1805         struct vnode *a_vp;
1806         vm_page_t *a_m;
1807         int a_count;
1808         int a_reqpage;
1809     };
1810 */
1811 static int
1812 fuse_vnop_getpages(struct vop_getpages_args *ap)
1813 {
1814         int i, error, nextoff, size, toff, count, npages;
1815         struct uio uio;
1816         struct iovec iov;
1817         vm_offset_t kva;
1818         struct buf *bp;
1819         struct vnode *vp;
1820         struct thread *td;
1821         struct ucred *cred;
1822         vm_page_t *pages;
1823         pid_t pid = curthread->td_proc->p_pid;
1824
1825         vp = ap->a_vp;
1826         KASSERT(vp->v_object, ("objectless vp passed to getpages"));
1827         td = curthread;                 /* XXX */
1828         cred = curthread->td_ucred;     /* XXX */
1829         pages = ap->a_m;
1830         npages = ap->a_count;
1831
1832         if (!fsess_opt_mmap(vnode_mount(vp))) {
1833                 SDT_PROBE2(fuse, , vnops, trace, 1,
1834                         "called on non-cacheable vnode??\n");
1835                 return (VM_PAGER_ERROR);
1836         }
1837
1838         /*
1839          * If the last page is partially valid, just return it and allow
1840          * the pager to zero-out the blanks.  Partially valid pages can
1841          * only occur at the file EOF.
1842          *
1843          * XXXGL: is that true for FUSE, which is a local filesystem,
1844          * but still somewhat disconnected from the kernel?
1845          */
1846         VM_OBJECT_WLOCK(vp->v_object);
1847         if (pages[npages - 1]->valid != 0 && --npages == 0)
1848                 goto out;
1849         VM_OBJECT_WUNLOCK(vp->v_object);
1850
1851         /*
1852          * We use only the kva address for the buffer, but this is extremely
1853          * convenient and fast.
1854          */
1855         bp = uma_zalloc(fuse_pbuf_zone, M_WAITOK);
1856
1857         kva = (vm_offset_t)bp->b_data;
1858         pmap_qenter(kva, pages, npages);
1859         VM_CNT_INC(v_vnodein);
1860         VM_CNT_ADD(v_vnodepgsin, npages);
1861
1862         count = npages << PAGE_SHIFT;
1863         iov.iov_base = (caddr_t)kva;
1864         iov.iov_len = count;
1865         uio.uio_iov = &iov;
1866         uio.uio_iovcnt = 1;
1867         uio.uio_offset = IDX_TO_OFF(pages[0]->pindex);
1868         uio.uio_resid = count;
1869         uio.uio_segflg = UIO_SYSSPACE;
1870         uio.uio_rw = UIO_READ;
1871         uio.uio_td = td;
1872
1873         error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred, pid);
1874         pmap_qremove(kva, npages);
1875
1876         uma_zfree(fuse_pbuf_zone, bp);
1877
1878         if (error && (uio.uio_resid == count)) {
1879                 SDT_PROBE1(fuse, , vnops, vnop_getpages_error, error);
1880                 return VM_PAGER_ERROR;
1881         }
1882         /*
1883          * Calculate the number of bytes read and validate only that number
1884          * of bytes.  Note that due to pending writes, size may be 0.  This
1885          * does not mean that the remaining data is invalid!
1886          */
1887
1888         size = count - uio.uio_resid;
1889         VM_OBJECT_WLOCK(vp->v_object);
1890         fuse_vm_page_lock_queues();
1891         for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
1892                 vm_page_t m;
1893
1894                 nextoff = toff + PAGE_SIZE;
1895                 m = pages[i];
1896
1897                 if (nextoff <= size) {
1898                         /*
1899                          * Read operation filled an entire page
1900                          */
1901                         m->valid = VM_PAGE_BITS_ALL;
1902                         KASSERT(m->dirty == 0,
1903                             ("fuse_getpages: page %p is dirty", m));
1904                 } else if (size > toff) {
1905                         /*
1906                          * Read operation filled a partial page.
1907                          */
1908                         m->valid = 0;
1909                         vm_page_set_valid_range(m, 0, size - toff);
1910                         KASSERT(m->dirty == 0,
1911                             ("fuse_getpages: page %p is dirty", m));
1912                 } else {
1913                         /*
1914                          * Read operation was short.  If no error occurred
1915                          * we may have hit a zero-fill section.   We simply
1916                          * leave valid set to 0.
1917                          */
1918                         ;
1919                 }
1920         }
1921         fuse_vm_page_unlock_queues();
1922 out:
1923         VM_OBJECT_WUNLOCK(vp->v_object);
1924         if (ap->a_rbehind)
1925                 *ap->a_rbehind = 0;
1926         if (ap->a_rahead)
1927                 *ap->a_rahead = 0;
1928         return (VM_PAGER_OK);
1929 }
1930
1931 /*
1932     struct vnop_putpages_args {
1933         struct vnode *a_vp;
1934         vm_page_t *a_m;
1935         int a_count;
1936         int a_sync;
1937         int *a_rtvals;
1938         vm_ooffset_t a_offset;
1939     };
1940 */
1941 static int
1942 fuse_vnop_putpages(struct vop_putpages_args *ap)
1943 {
1944         struct uio uio;
1945         struct iovec iov;
1946         vm_offset_t kva;
1947         struct buf *bp;
1948         int i, error, npages, count;
1949         off_t offset;
1950         int *rtvals;
1951         struct vnode *vp;
1952         struct thread *td;
1953         struct ucred *cred;
1954         vm_page_t *pages;
1955         vm_ooffset_t fsize;
1956         pid_t pid = curthread->td_proc->p_pid;
1957
1958         vp = ap->a_vp;
1959         KASSERT(vp->v_object, ("objectless vp passed to putpages"));
1960         fsize = vp->v_object->un_pager.vnp.vnp_size;
1961         td = curthread;                 /* XXX */
1962         cred = curthread->td_ucred;     /* XXX */
1963         pages = ap->a_m;
1964         count = ap->a_count;
1965         rtvals = ap->a_rtvals;
1966         npages = btoc(count);
1967         offset = IDX_TO_OFF(pages[0]->pindex);
1968
1969         if (!fsess_opt_mmap(vnode_mount(vp))) {
1970                 SDT_PROBE2(fuse, , vnops, trace, 1,
1971                         "called on non-cacheable vnode??\n");
1972         }
1973         for (i = 0; i < npages; i++)
1974                 rtvals[i] = VM_PAGER_AGAIN;
1975
1976         /*
1977          * When putting pages, do not extend file past EOF.
1978          */
1979
1980         if (offset + count > fsize) {
1981                 count = fsize - offset;
1982                 if (count < 0)
1983                         count = 0;
1984         }
1985         /*
1986          * We use only the kva address for the buffer, but this is extremely
1987          * convenient and fast.
1988          */
1989         bp = uma_zalloc(fuse_pbuf_zone, M_WAITOK);
1990
1991         kva = (vm_offset_t)bp->b_data;
1992         pmap_qenter(kva, pages, npages);
1993         VM_CNT_INC(v_vnodeout);
1994         VM_CNT_ADD(v_vnodepgsout, count);
1995
1996         iov.iov_base = (caddr_t)kva;
1997         iov.iov_len = count;
1998         uio.uio_iov = &iov;
1999         uio.uio_iovcnt = 1;
2000         uio.uio_offset = offset;
2001         uio.uio_resid = count;
2002         uio.uio_segflg = UIO_SYSSPACE;
2003         uio.uio_rw = UIO_WRITE;
2004         uio.uio_td = td;
2005
2006         error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred, pid);
2007
2008         pmap_qremove(kva, npages);
2009         uma_zfree(fuse_pbuf_zone, bp);
2010
2011         if (!error) {
2012                 int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
2013
2014                 for (i = 0; i < nwritten; i++) {
2015                         rtvals[i] = VM_PAGER_OK;
2016                         VM_OBJECT_WLOCK(pages[i]->object);
2017                         vm_page_undirty(pages[i]);
2018                         VM_OBJECT_WUNLOCK(pages[i]->object);
2019                 }
2020         }
2021         return rtvals[0];
2022 }
2023
2024 static const char extattr_namespace_separator = '.';
2025
2026 /*
2027     struct vop_getextattr_args {
2028         struct vop_generic_args a_gen;
2029         struct vnode *a_vp;
2030         int a_attrnamespace;
2031         const char *a_name;
2032         struct uio *a_uio;
2033         size_t *a_size;
2034         struct ucred *a_cred;
2035         struct thread *a_td;
2036     };
2037 */
2038 static int
2039 fuse_vnop_getextattr(struct vop_getextattr_args *ap)
2040 {
2041         struct vnode *vp = ap->a_vp;
2042         struct uio *uio = ap->a_uio;
2043         struct fuse_dispatcher fdi;
2044         struct fuse_getxattr_in *get_xattr_in;
2045         struct fuse_getxattr_out *get_xattr_out;
2046         struct mount *mp = vnode_mount(vp);
2047         struct thread *td = ap->a_td;
2048         struct ucred *cred = ap->a_cred;
2049         char *prefix;
2050         char *attr_str;
2051         size_t len;
2052         int err;
2053
2054         if (fuse_isdeadfs(vp))
2055                 return (ENXIO);
2056
2057         /* Default to looking for user attributes. */
2058         if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2059                 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2060         else
2061                 prefix = EXTATTR_NAMESPACE_USER_STRING;
2062
2063         len = strlen(prefix) + sizeof(extattr_namespace_separator) +
2064             strlen(ap->a_name) + 1;
2065
2066         fdisp_init(&fdi, len + sizeof(*get_xattr_in));
2067         fdisp_make_vp(&fdi, FUSE_GETXATTR, vp, td, cred);
2068
2069         get_xattr_in = fdi.indata;
2070         /*
2071          * Check to see whether we're querying the available size or
2072          * issuing the actual request.  If we pass in 0, we get back struct
2073          * fuse_getxattr_out.  If we pass in a non-zero size, we get back
2074          * that much data, without the struct fuse_getxattr_out header.
2075          */
2076         if (uio == NULL)
2077                 get_xattr_in->size = 0;
2078         else
2079                 get_xattr_in->size = uio->uio_resid;
2080
2081         attr_str = (char *)fdi.indata + sizeof(*get_xattr_in);
2082         snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator,
2083             ap->a_name);
2084
2085         err = fdisp_wait_answ(&fdi);
2086         if (err != 0) {
2087                 if (err == ENOSYS)
2088                         fsess_set_notimpl(mp, FUSE_GETXATTR);
2089                 goto out;
2090         }
2091
2092         get_xattr_out = fdi.answ;
2093
2094         if (ap->a_size != NULL)
2095                 *ap->a_size = get_xattr_out->size;
2096
2097         if (uio != NULL)
2098                 err = uiomove(fdi.answ, fdi.iosize, uio);
2099
2100 out:
2101         fdisp_destroy(&fdi);
2102         return (err);
2103 }
2104
2105 /*
2106     struct vop_setextattr_args {
2107         struct vop_generic_args a_gen;
2108         struct vnode *a_vp;
2109         int a_attrnamespace;
2110         const char *a_name;
2111         struct uio *a_uio;
2112         struct ucred *a_cred;
2113         struct thread *a_td;
2114     };
2115 */
2116 static int
2117 fuse_vnop_setextattr(struct vop_setextattr_args *ap)
2118 {
2119         struct vnode *vp = ap->a_vp;
2120         struct uio *uio = ap->a_uio;
2121         struct fuse_dispatcher fdi;
2122         struct fuse_setxattr_in *set_xattr_in;
2123         struct mount *mp = vnode_mount(vp);
2124         struct thread *td = ap->a_td;
2125         struct ucred *cred = ap->a_cred;
2126         char *prefix;
2127         size_t len;
2128         char *attr_str;
2129         int err;
2130         
2131         if (fuse_isdeadfs(vp))
2132                 return (ENXIO);
2133
2134         /* Default to looking for user attributes. */
2135         if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2136                 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2137         else
2138                 prefix = EXTATTR_NAMESPACE_USER_STRING;
2139
2140         len = strlen(prefix) + sizeof(extattr_namespace_separator) +
2141             strlen(ap->a_name) + 1;
2142
2143         fdisp_init(&fdi, len + sizeof(*set_xattr_in) + uio->uio_resid);
2144         fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, td, cred);
2145
2146         set_xattr_in = fdi.indata;
2147         set_xattr_in->size = uio->uio_resid;
2148
2149         attr_str = (char *)fdi.indata + sizeof(*set_xattr_in);
2150         snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator,
2151             ap->a_name);
2152
2153         err = uiomove((char *)fdi.indata + sizeof(*set_xattr_in) + len,
2154             uio->uio_resid, uio);
2155         if (err != 0) {
2156                 goto out;
2157         }
2158
2159         err = fdisp_wait_answ(&fdi);
2160
2161         if (err != 0) {
2162                 if (err == ENOSYS)
2163                         fsess_set_notimpl(mp, FUSE_SETXATTR);
2164                 goto out;
2165         }
2166
2167 out:
2168         fdisp_destroy(&fdi);
2169         return (err);
2170 }
2171
2172 /*
2173  * The Linux / FUSE extended attribute list is simply a collection of
2174  * NUL-terminated strings.  The FreeBSD extended attribute list is a single
2175  * byte length followed by a non-NUL terminated string.  So, this allows
2176  * conversion of the Linux / FUSE format to the FreeBSD format in place.
2177  * Linux attribute names are reported with the namespace as a prefix (e.g.
2178  * "user.attribute_name"), but in FreeBSD they are reported without the
2179  * namespace prefix (e.g. "attribute_name").  So, we're going from:
2180  *
2181  * user.attr_name1\0user.attr_name2\0
2182  *
2183  * to:
2184  *
2185  * <num>attr_name1<num>attr_name2
2186  *
2187  * Where "<num>" is a single byte number of characters in the attribute name.
2188  * 
2189  * Args:
2190  * prefix - exattr namespace prefix string
2191  * list, list_len - input list with namespace prefixes
2192  * bsd_list, bsd_list_len - output list compatible with bsd vfs
2193  */
2194 static int
2195 fuse_xattrlist_convert(char *prefix, const char *list, int list_len,
2196     char *bsd_list, int *bsd_list_len)
2197 {
2198         int len, pos, dist_to_next, prefix_len;
2199
2200         pos = 0;
2201         *bsd_list_len = 0;
2202         prefix_len = strlen(prefix);
2203
2204         while (pos < list_len && list[pos] != '\0') {
2205                 dist_to_next = strlen(&list[pos]) + 1;
2206                 if (bcmp(&list[pos], prefix, prefix_len) == 0 &&
2207                     list[pos + prefix_len] == extattr_namespace_separator) {
2208                         len = dist_to_next -
2209                             (prefix_len + sizeof(extattr_namespace_separator)) - 1;
2210                         if (len >= EXTATTR_MAXNAMELEN)
2211                                 return (ENAMETOOLONG);
2212
2213                         bsd_list[*bsd_list_len] = len;
2214                         memcpy(&bsd_list[*bsd_list_len + 1],
2215                             &list[pos + prefix_len +
2216                             sizeof(extattr_namespace_separator)], len);
2217
2218                         *bsd_list_len += len + 1;
2219                 }
2220
2221                 pos += dist_to_next;
2222         }
2223
2224         return (0);
2225 }
2226
2227 /*
2228     struct vop_listextattr_args {
2229         struct vop_generic_args a_gen;
2230         struct vnode *a_vp;
2231         int a_attrnamespace;
2232         struct uio *a_uio;
2233         size_t *a_size;
2234         struct ucred *a_cred;
2235         struct thread *a_td;
2236     };
2237 */
2238 static int
2239 fuse_vnop_listextattr(struct vop_listextattr_args *ap)
2240 {
2241         struct vnode *vp = ap->a_vp;
2242         struct uio *uio = ap->a_uio;
2243         struct fuse_dispatcher fdi;
2244         struct fuse_listxattr_in *list_xattr_in;
2245         struct fuse_listxattr_out *list_xattr_out;
2246         struct mount *mp = vnode_mount(vp);
2247         struct thread *td = ap->a_td;
2248         struct ucred *cred = ap->a_cred;
2249         size_t len;
2250         char *prefix;
2251         char *attr_str;
2252         char *bsd_list = NULL;
2253         char *linux_list;
2254         int bsd_list_len;
2255         int linux_list_len;
2256         int err;
2257
2258         if (fuse_isdeadfs(vp))
2259                 return (ENXIO);
2260
2261         /*
2262          * Add space for a NUL and the period separator if enabled.
2263          * Default to looking for user attributes.
2264          */
2265         if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2266                 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2267         else
2268                 prefix = EXTATTR_NAMESPACE_USER_STRING;
2269
2270         len = strlen(prefix) + sizeof(extattr_namespace_separator) + 1;
2271
2272         fdisp_init(&fdi, sizeof(*list_xattr_in) + len);
2273         fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred);
2274
2275         /*
2276          * Retrieve Linux / FUSE compatible list size.
2277          */
2278         list_xattr_in = fdi.indata;
2279         list_xattr_in->size = 0;
2280         attr_str = (char *)fdi.indata + sizeof(*list_xattr_in);
2281         snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator);
2282
2283         err = fdisp_wait_answ(&fdi);
2284         if (err != 0) {
2285                 if (err == ENOSYS)
2286                         fsess_set_notimpl(mp, FUSE_LISTXATTR);
2287                 goto out;
2288         }
2289
2290         list_xattr_out = fdi.answ;
2291         linux_list_len = list_xattr_out->size;
2292         if (linux_list_len == 0) {
2293                 if (ap->a_size != NULL)
2294                         *ap->a_size = linux_list_len;
2295                 goto out;
2296         }
2297
2298         /*
2299          * Retrieve Linux / FUSE compatible list values.
2300          */
2301         fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred);
2302         list_xattr_in = fdi.indata;
2303         list_xattr_in->size = linux_list_len + sizeof(*list_xattr_out);
2304         attr_str = (char *)fdi.indata + sizeof(*list_xattr_in);
2305         snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator);
2306
2307         err = fdisp_wait_answ(&fdi);
2308         if (err != 0)
2309                 goto out;
2310
2311         linux_list = fdi.answ;
2312         linux_list_len = fdi.iosize;
2313
2314         /*
2315          * Retrieve the BSD compatible list values.
2316          * The Linux / FUSE attribute list format isn't the same
2317          * as FreeBSD's format. So we need to transform it into
2318          * FreeBSD's format before giving it to the user.
2319          */
2320         bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK);
2321         err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len,
2322             bsd_list, &bsd_list_len);
2323         if (err != 0)
2324                 goto out;
2325
2326         if (ap->a_size != NULL)
2327                 *ap->a_size = bsd_list_len;
2328
2329         if (uio != NULL)
2330                 err = uiomove(bsd_list, bsd_list_len, uio);
2331
2332 out:
2333         free(bsd_list, M_TEMP);
2334         fdisp_destroy(&fdi);
2335         return (err);
2336 }
2337
2338 /*
2339     struct vop_deleteextattr_args {
2340         struct vop_generic_args a_gen;
2341         struct vnode *a_vp;
2342         int a_attrnamespace;
2343         const char *a_name;
2344         struct ucred *a_cred;
2345         struct thread *a_td;
2346     };
2347 */
2348 static int
2349 fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap)
2350 {
2351         struct vnode *vp = ap->a_vp;
2352         struct fuse_dispatcher fdi;
2353         struct mount *mp = vnode_mount(vp);
2354         struct thread *td = ap->a_td;
2355         struct ucred *cred = ap->a_cred;
2356         char *prefix;
2357         size_t len;
2358         char *attr_str;
2359         int err;
2360
2361         if (fuse_isdeadfs(vp))
2362                 return (ENXIO);
2363
2364         /* Default to looking for user attributes. */
2365         if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
2366                 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
2367         else
2368                 prefix = EXTATTR_NAMESPACE_USER_STRING;
2369
2370         len = strlen(prefix) + sizeof(extattr_namespace_separator) +
2371             strlen(ap->a_name) + 1;
2372
2373         fdisp_init(&fdi, len);
2374         fdisp_make_vp(&fdi, FUSE_REMOVEXATTR, vp, td, cred);
2375
2376         attr_str = fdi.indata;
2377         snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator,
2378             ap->a_name);
2379
2380         err = fdisp_wait_answ(&fdi);
2381         if (err != 0) {
2382                 if (err == ENOSYS)
2383                         fsess_set_notimpl(mp, FUSE_REMOVEXATTR);
2384         }
2385
2386         fdisp_destroy(&fdi);
2387         return (err);
2388 }
2389
2390 /*
2391     struct vnop_print_args {
2392         struct vnode *a_vp;
2393     };
2394 */
2395 static int
2396 fuse_vnop_print(struct vop_print_args *ap)
2397 {
2398         struct fuse_vnode_data *fvdat = VTOFUD(ap->a_vp);
2399
2400         printf("nodeid: %ju, parent nodeid: %ju, nlookup: %ju, flag: %#x\n",
2401             (uintmax_t)VTOILLU(ap->a_vp), (uintmax_t)fvdat->parent_nid,
2402             (uintmax_t)fvdat->nlookup,
2403             fvdat->flag);
2404
2405         return 0;
2406 }