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