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