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