Quantcast

Fuse (and sshfs) support for OpenBSD

classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
Hi tech@

I send you this mail because a few months ago I tried to dabble with fuse
filesystem and OpenBSD. After some time working on this subject I have
succeeded to create something that works. It is not even near to be perfect
but with some changes and adaptions I think it could do the job.

In order to use these patches you will need to follow this procedure:

* apply the ports patch :
    root # cd /usr/ports
    root # ftp http://www.pmbsd.org/patch-fuse-ports
    root # patch -p0 < patch-fuse-ports

* apply the src patch
    root # cd /usr/src
    root # ftp http://www.pmbsd.org/patch-fuse-src
    root # patch -p0 < patch-fuse-src

* upgrade your system mount.h
    root # cp /usr/src/sys/sys/mount.h /usr/include/sys/mount.h

* compile all mount and umount binaries
    root # cd /usr/src/sbin/mount && make && make install
    root # cd /usr/src/sbin/mount_ffs && make && make install
    root # cd /usr/src/sbin/mount_fusefs && make && make install (there are
warning for a missing manpage)
      ...
    root # cd /usr/src/sbin/umount && make && make install

* build a new kernel
    root # cd /usr/src/sys/arch/i386/conf
    root # config GENERIC
    root # cd ../compile/GENERIC
    root # make && make install

* update MAKEDEV script and launch it to create the fuse device
    root # cd /dev
    root # ftp http://www.pmbsd.org/patch-fuse-MAKEDEV
    root # patch MAKEDEV < patch-fuse-MAKEDEV
    root # ./MAKEDEV
    root # ./MAKEDEV fuse

* install devel/fuse and sysutils/sshfs-fuse packages
   root # cd /usr/ports/devel/fuse && make && make install
   root # cd /usr/ports/sysutils/sshfs-fuse && make && make install

* reboot and try sshfs
   root # reboot
   root # sshfs [hidden email]:/home/syl/code /mnt
   root # ls /mnt


As I said before, this is not perfect... There are some outstanding
features to implement and bugs or architectural mistakes to solve...

There is some work to do to implement these missing vnops and vfs features :

  * vptof
  * fhtovp
  * checkexp
  * sysctl
  * strategy
  * fsync
  * symlink
  * rename vnop
  * you could only mount one filesystem at once.

I think some security improvement could be done on these patches like :
- fix some panics and tsleep hole that could produce DoS...
- allow the use of fuse with a securelevel equal to -1...
- other security stuff that I'm surely missing :)

I will not explain all the fuse protocol in this mail but if you want
information on how it works I will answer your questions in a private mail.

If you have any questions about these patches or want me to change or
rework something in this code I will be happy to do it.

Thanks for your time,

Cheers,

--
Sylvestre Gallon
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Antoine Jacoutot-7
On Tue, Mar 05, 2013 at 01:43:24PM +0100, Sylvestre Gallon wrote:
> Hi tech@
>
> I send you this mail because a few months ago I tried to dabble with fuse
> filesystem and OpenBSD. After some time working on this subject I have
> succeeded to create something that works. It is not even near to be perfect
> but with some changes and adaptions I think it could do the job.

Before anyone flame you for whatever reason, let me say that I am *very* happy that some work in done in this area.
I'll try and play with this and see what comes out of it; may take a little bit of time though.


> In order to use these patches you will need to follow this procedure:
>
> * apply the ports patch :
>     root # cd /usr/ports
>     root # ftp http://www.pmbsd.org/patch-fuse-ports
>     root # patch -p0 < patch-fuse-ports
>
> * apply the src patch
>     root # cd /usr/src
>     root # ftp http://www.pmbsd.org/patch-fuse-src
>     root # patch -p0 < patch-fuse-src
>
> * upgrade your system mount.h
>     root # cp /usr/src/sys/sys/mount.h /usr/include/sys/mount.h
>
> * compile all mount and umount binaries
>     root # cd /usr/src/sbin/mount && make && make install
>     root # cd /usr/src/sbin/mount_ffs && make && make install
>     root # cd /usr/src/sbin/mount_fusefs && make && make install (there are
> warning for a missing manpage)
>       ...
>     root # cd /usr/src/sbin/umount && make && make install
>
> * build a new kernel
>     root # cd /usr/src/sys/arch/i386/conf
>     root # config GENERIC
>     root # cd ../compile/GENERIC
>     root # make && make install
>
> * update MAKEDEV script and launch it to create the fuse device
>     root # cd /dev
>     root # ftp http://www.pmbsd.org/patch-fuse-MAKEDEV
>     root # patch MAKEDEV < patch-fuse-MAKEDEV
>     root # ./MAKEDEV
>     root # ./MAKEDEV fuse
>
> * install devel/fuse and sysutils/sshfs-fuse packages
>    root # cd /usr/ports/devel/fuse && make && make install
>    root # cd /usr/ports/sysutils/sshfs-fuse && make && make install
>
> * reboot and try sshfs
>    root # reboot
>    root # sshfs [hidden email]:/home/syl/code /mnt
>    root # ls /mnt
>
>
> As I said before, this is not perfect... There are some outstanding
> features to implement and bugs or architectural mistakes to solve...
>
> There is some work to do to implement these missing vnops and vfs features :
>
>   * vptof
>   * fhtovp
>   * checkexp
>   * sysctl
>   * strategy
>   * fsync
>   * symlink
>   * rename vnop
>   * you could only mount one filesystem at once.
>
> I think some security improvement could be done on these patches like :
> - fix some panics and tsleep hole that could produce DoS...
> - allow the use of fuse with a securelevel equal to -1...
> - other security stuff that I'm surely missing :)
>
> I will not explain all the fuse protocol in this mail but if you want
> information on how it works I will answer your questions in a private mail.
>
> If you have any questions about these patches or want me to change or
> rework something in this code I will be happy to do it.
>
> Thanks for your time,
>
> Cheers,
>
> --
> Sylvestre Gallon

--
Antoine

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Gilles Chehade-7
On Tue, Mar 05, 2013 at 01:49:20PM +0100, Antoine Jacoutot wrote:

> On Tue, Mar 05, 2013 at 01:43:24PM +0100, Sylvestre Gallon wrote:
> > Hi tech@
> >
> > I send you this mail because a few months ago I tried to dabble with fuse
> > filesystem and OpenBSD. After some time working on this subject I have
> > succeeded to create something that works. It is not even near to be perfect
> > but with some changes and adaptions I think it could do the job.
>
> Before anyone flame you for whatever reason, let me say that I am *very* happy that some work in done in this area.
> I'll try and play with this and see what comes out of it; may take a little bit of time though.
>

Yup, same here

--
Gilles Chehade

https://www.poolp.org                                          @poolpOrg

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Bob Beck-3
In reply to this post by Sylvestre Gallon
Sylvestre, one of the problems with fuse itself is that it's GPL
licensed, and not appropriate
for inclusion in base. If you've got interets and talent in this area,
you might want to consider
having a peek at puffs (and refuse) from netbsd which has a workable
license and could
be included in base.   I would definitely help if you're interested...

-Bob


On Tue, Mar 5, 2013 at 5:43 AM, Sylvestre Gallon <[hidden email]> wrote:

> Hi tech@
>
> I send you this mail because a few months ago I tried to dabble with fuse
> filesystem and OpenBSD. After some time working on this subject I have
> succeeded to create something that works. It is not even near to be perfect
> but with some changes and adaptions I think it could do the job.
>
> In order to use these patches you will need to follow this procedure:
>
> * apply the ports patch :
>     root # cd /usr/ports
>     root # ftp http://www.pmbsd.org/patch-fuse-ports
>     root # patch -p0 < patch-fuse-ports
>
> * apply the src patch
>     root # cd /usr/src
>     root # ftp http://www.pmbsd.org/patch-fuse-src
>     root # patch -p0 < patch-fuse-src
>
> * upgrade your system mount.h
>     root # cp /usr/src/sys/sys/mount.h /usr/include/sys/mount.h
>
> * compile all mount and umount binaries
>     root # cd /usr/src/sbin/mount && make && make install
>     root # cd /usr/src/sbin/mount_ffs && make && make install
>     root # cd /usr/src/sbin/mount_fusefs && make && make install (there are
> warning for a missing manpage)
>       ...
>     root # cd /usr/src/sbin/umount && make && make install
>
> * build a new kernel
>     root # cd /usr/src/sys/arch/i386/conf
>     root # config GENERIC
>     root # cd ../compile/GENERIC
>     root # make && make install
>
> * update MAKEDEV script and launch it to create the fuse device
>     root # cd /dev
>     root # ftp http://www.pmbsd.org/patch-fuse-MAKEDEV
>     root # patch MAKEDEV < patch-fuse-MAKEDEV
>     root # ./MAKEDEV
>     root # ./MAKEDEV fuse
>
> * install devel/fuse and sysutils/sshfs-fuse packages
>    root # cd /usr/ports/devel/fuse && make && make install
>    root # cd /usr/ports/sysutils/sshfs-fuse && make && make install
>
> * reboot and try sshfs
>    root # reboot
>    root # sshfs [hidden email]:/home/syl/code /mnt
>    root # ls /mnt
>
>
> As I said before, this is not perfect... There are some outstanding
> features to implement and bugs or architectural mistakes to solve...
>
> There is some work to do to implement these missing vnops and vfs features :
>
>   * vptof
>   * fhtovp
>   * checkexp
>   * sysctl
>   * strategy
>   * fsync
>   * symlink
>   * rename vnop
>   * you could only mount one filesystem at once.
>
> I think some security improvement could be done on these patches like :
> - fix some panics and tsleep hole that could produce DoS...
> - allow the use of fuse with a securelevel equal to -1...
> - other security stuff that I'm surely missing :)
>
> I will not explain all the fuse protocol in this mail but if you want
> information on how it works I will answer your questions in a private mail.
>
> If you have any questions about these patches or want me to change or
> rework something in this code I will be happy to do it.
>
> Thanks for your time,
>
> Cheers,
>
> --
> Sylvestre Gallon

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Jiri B-2
In reply to this post by Gilles Chehade-7
On Tue, Mar 05, 2013 at 02:11:41PM +0100, Gilles Chehade wrote:

> On Tue, Mar 05, 2013 at 01:49:20PM +0100, Antoine Jacoutot wrote:
> > On Tue, Mar 05, 2013 at 01:43:24PM +0100, Sylvestre Gallon wrote:
> > > Hi tech@
> > >
> > > I send you this mail because a few months ago I tried to dabble with fuse
> > > filesystem and OpenBSD. After some time working on this subject I have
> > > succeeded to create something that works. It is not even near to be perfect
> > > but with some changes and adaptions I think it could do the job.
> >
> > Before anyone flame you for whatever reason, let me say that I am *very* happy that some work in done in this area.
> > I'll try and play with this and see what comes out of it; may take a little bit of time though.
> >
>
> Yup, same here

Yes, it would be nice to have libguestfs which uses FUSE
working on OpenBSD so one could modify qemu/kvm OpenBSD images
directly ;)

jirib

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Martin Pieuchot-2
In reply to this post by Bob Beck-3
On 05/03/13(Tue) 06:44, Bob Beck wrote:
> Sylvestre, one of the problems with fuse itself is that it's GPL
> licensed, and not appropriate for inclusion in base. If you've got
> interets and talent in this area,  you might want to consider
> having a peek at puffs (and refuse) from netbsd which has a workable
> license and could be included in base.
> I would definitely help if you're interested...

It looks to me that Sylvestre wrote it's own ISC-licensed implementation.

Sylvestre that's a lot of work, and a lot of new code :) I'd suggest you
to send your diff inline (maybe splitting the userland and kernel parts)
so that people can comment on them.

M.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
In reply to this post by Bob Beck-3
On Tue, Mar 5, 2013 at 2:44 PM, Bob Beck <[hidden email]> wrote:

> Sylvestre, one of the problems with fuse itself is that it's GPL
> licensed, and not appropriate
> for inclusion in base. If you've got interets and talent in this area,
> you might want to consider
> having a peek at puffs (and refuse) from netbsd which has a workable
> license and could
> be included in base.   I would definitely help if you're interested...
>
> -Bob
>
>
Bob,

I am not quite sure but I think that only libfuse and sshfs are GPL
licenced. The patches for those two items are only present in ports.

All the code present in src is ISC licenced. The kernel communicate with
libfuse througth a device (ie /dev/fuse) and only share a header with the
libfuse (fuse_kernel.h) which is BSD licenced. FreeBSD used the same way to
implement it. (I do not know if it is a good example)

Anyway, It could be fun to have a peek at puffs/refuse and have your help :)

Cheers,

--
Sylvestre Gallon
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
In reply to this post by Martin Pieuchot-2
On Tue, Mar 5, 2013 at 3:12 PM, Martin Pieuchot <[hidden email]> wrote:
> It looks to me that Sylvestre wrote it's own ISC-licensed implementation.
>
> Sylvestre that's a lot of work, and a lot of new code :) I'd suggest you
> to send your diff inline (maybe splitting the userland and kernel parts)
> so that people can comment on them.
>
> M.

Martin,

You will find inline the kernel patch

Index: arch/i386/i386/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/conf.c,v
retrieving revision 1.141
diff -u -p -u -p -r1.141 conf.c
--- arch/i386/i386/conf.c    23 Aug 2012 06:12:49 -0000    1.141
+++ arch/i386/i386/conf.c    5 Mar 2013 15:16:08 -0000
@@ -185,6 +185,7 @@ cdev_decl(pci);
 #include "amdmsr.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct cdevsw    cdevsw[] =
 {
@@ -293,6 +294,7 @@ struct cdevsw    cdevsw[] =
     cdev_vscsi_init(NVSCSI,vscsi),    /* 90: vscsi */
     cdev_disk_init(1,diskmap),    /* 91: disk mapper */
     cdev_pppx_init(NPPPX,pppx),     /* 92: pppx */
+    cdev_fuse_init(NFUSE, fuse),    /* 93: fuse */
 };
 int    nchrdev = nitems(cdevsw);

Index: conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/conf/GENERIC,v
retrieving revision 1.194
diff -u -p -u -p -r1.194 GENERIC
--- conf/GENERIC    1 Mar 2013 21:06:04 -0000    1.194
+++ conf/GENERIC    5 Mar 2013 15:16:08 -0000
@@ -45,6 +45,7 @@ option        NFSSERVER    # Network File System
 option        CD9660        # ISO 9660 + Rock Ridge file system
 option        UDF        # UDF (DVD) file system
 option        MSDOSFS        # MS-DOS file system
+option        FUSE        # Userland file system
 option        FIFO        # FIFOs; RECOMMENDED

 option        SOCKET_SPLICE    # Socket Splicing for TCP
@@ -73,6 +74,8 @@ scsibus*    at softraid?

 vscsi0        at root        # Userland backed Virtual SCSI
 scsibus*    at vscsi?
+
+pseudo-device    fuse        # filesystem in user land

 pseudo-device    pf        # packet filter
 pseudo-device    pflog        # pf log if
Index: conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.540
diff -u -p -u -p -r1.540 files
--- conf/files    21 Jan 2013 11:17:48 -0000    1.540
+++ conf/files    5 Mar 2013 15:16:09 -0000
@@ -544,6 +544,15 @@ pseudo-device systrace
 pseudo-device ksyms
 file    dev/ksyms.c            ksyms needs-flag

+pseudo-device fuse
+file    miscfs/fuse/fuse_device.c    fuse    needs-flag
+file    miscfs/fuse/fuse_file.c        fuse
+file    miscfs/fuse/fuse_lookup.c    fuse
+file    miscfs/fuse/fuse_node.c        fuse
+file    miscfs/fuse/fuse_vfsops.c    fuse
+file    miscfs/fuse/fuse_vnops.c    fuse
+file    miscfs/fuse/fuse_subr.c        fuse
+
 pseudo-device pf: ifnet
 file    net/pf.c            pf    needs-flag
 file    net/pf_norm.c            pf
Index: kern/vfs_init.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_init.c,v
retrieving revision 1.30
diff -u -p -u -p -r1.30 vfs_init.c
--- kern/vfs_init.c    23 Aug 2012 06:12:49 -0000    1.30
+++ kern/vfs_init.c    5 Mar 2013 15:16:09 -0000
@@ -85,6 +85,10 @@ extern  const struct vfsops ntfs_vfsops;
 extern  const struct vfsops udf_vfsops;
 #endif

+#ifdef FUSE
+extern const struct vfsops fusefs_vfsops;
+#endif
+
 /* Set up the filesystem operations for vnodes. */
 static struct vfsconf vfsconflist[] = {
 #ifdef FFS
@@ -121,6 +125,10 @@ static struct vfsconf vfsconflist[] = {

 #ifdef UDF
     { &udf_vfsops, MOUNT_UDF, 13, 0, MNT_LOCAL, NULL },
+#endif
+
+#ifdef FUSE
+    { &fusefs_vfsops, MOUNT_FUSEFS, 42, 0, MNT_LOCAL, NULL }, /* put
42 as type, I don't know witch number I can use*/
 #endif
 };

Index: miscfs/fuse/fuse_device.c
===================================================================
RCS file: miscfs/fuse/fuse_device.c
diff -N miscfs/fuse/fuse_device.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_device.c    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/poll.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/fcntl.h>
+#include <sys/vnode.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+struct fuse_dev {
+    int opened;
+    int end;
+};
+
+#define FUSE_OPEN 1
+#define FUSE_CLOSE 0
+#define FUSE_DONE 2
+
+static struct fuse_dev *fuse_devs[MAX_FUSE_DEV];
+
+void             fuseattach(int);
+int             fuseopen(dev_t, int, int, struct proc *);
+int             fuseclose(dev_t, int, int, struct proc *);
+int             fuseioctl(dev_t, u_long, caddr_t, int, struct proc *);
+int             fuseread(dev_t, struct uio *, int);
+int             fusewrite(dev_t, struct uio *, int);
+int             fusepoll(dev_t, int, struct proc *);
+
+struct fuse_msg_head fmq_in;
+struct fuse_msg_head fmq_wait;
+
+#ifdef FUSE_DEV_DEBUG
+static void
+dump_buff(char *buff, int len)
+{
+    char text[17];
+    int i;
+
+    bzero(text, 17);
+    for (i = 0; i < len ; i++) {
+
+        if (i != 0 && (i % 16) == 0) {
+            printf(": %s\n", text);
+            bzero(text, 17);
+        }
+
+        printf("%.2x ", buff[i] & 0xff);
+
+        if (buff[i] > ' ' && buff[i] < '~')
+            text[i%16] = buff[i] & 0xff;
+        else
+            text[i%16] = '.';
+    }
+
+    if ((i % 16) != 0) {
+        while ((i % 16) != 0) {
+            printf("   ");
+            i++;
+        }
+    }
+    printf(": %s\n", text);
+}
+#endif
+
+void
+fuseattach(int num)
+{
+#ifdef FUSE_DEV_DEBUG
+    printf("fuse0 at root\n");
+#endif
+}
+
+int
+fuseopen(dev_t dev, int flags, int fmt, struct proc * p)
+{
+    if (minor(dev) >= MAX_FUSE_DEV &&
+        fuse_devs[minor(dev)]->opened != FUSE_CLOSE)
+        return (ENXIO);
+
+#ifdef FUSE_DEV_DEBUG
+    printf("open dev %i\n", minor(dev));
+#endif
+
+    fuse_devs[minor(dev)] = malloc(sizeof(*fuse_devs[minor(dev)]),
+                       M_FUSEFS, M_WAITOK | M_ZERO);
+    fuse_devs[minor(dev)]->opened = FUSE_OPEN;
+
+    return (0);
+}
+
+int
+fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
+{
+    if (minor(dev) >= MAX_FUSE_DEV)
+        return (ENXIO);
+
+#ifdef FUSE_DEV_DEBUG
+    printf("close dev %i\n", minor(dev));
+#endif
+
+    fuse_devs[minor(dev)]->opened = FUSE_CLOSE;
+    free(fuse_devs[minor(dev)], M_FUSEFS);
+    fuse_devs[minor(dev)] = NULL;
+    return (0);
+}
+
+int
+fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
+{
+    int error = 0;
+
+    switch (cmd) {
+    default:
+        printf("bad ioctl number %d\n", cmd);
+        return ENODEV;
+    }
+
+    return error;
+}
+
+int
+fuseread(dev_t dev, struct uio *uio, int ioflag)
+{
+    int error = 0;
+    struct fuse_msg *msg;
+
+#ifdef FUSE_DEV_DEBUG
+    printf("read 0x%x\n", dev);
+#endif
+
+    if (fuse_devs[minor(dev)]->opened != FUSE_OPEN) {
+        return ENODEV;
+    }
+
+again:
+    if (TAILQ_EMPTY(&fmq_in)) {
+
+        if (ioflag & O_NONBLOCK) {
+            return (EAGAIN);
+        }
+
+        error = tsleep(&fmq_in, PWAIT, "fuse read", 0);
+
+        if (error)
+            return error;
+    }
+    if (TAILQ_EMPTY(&fmq_in))
+        goto again;
+
+    if (!TAILQ_EMPTY(&fmq_in)) {
+        msg = TAILQ_FIRST(&fmq_in);
+
+        if (msg->hdr->opcode == FUSE_DESTROY) {
+#ifdef FUSE_DEV_DEBUG
+            printf("catch done\n");
+#endif
+            fuse_devs[minor(dev)]->opened = FUSE_DONE;
+        }
+
+        error = uiomove(msg->hdr, sizeof(struct fuse_in_header), uio);
+
+#ifdef FUSE_DEV_DEBUG
+        printf("hdr r:\n");
+        dump_buff((char *)msg->hdr, sizeof(struct fuse_in_header));
+#endif
+
+        if (msg->len > 0) {
+            error = uiomove(msg->data, msg->len, uio);
+#ifdef FUSE_DEV_DEBUG
+            printf("data r:\n");
+            dump_buff(msg->data, msg->len);
+#endif
+        }
+
+#ifdef FUSE_DEV_DEBUG
+        printf("msg send : %i\n", msg->len);
+#endif
+
+        if (error)
+            return error;
+
+        /*
+          * msg moves from a tailq to another
+          */
+        TAILQ_REMOVE(&fmq_in, msg, node);
+        TAILQ_INSERT_TAIL(&fmq_wait, msg, node);
+    }
+
+    return error;
+}
+
+int
+fusewrite(dev_t dev, struct uio *uio, int ioflag)
+{
+    struct fuse_out_header hdr;
+    struct fuse_msg *msg;
+    int error = 0;
+    int catched = 0;
+    int len;
+    void *data;
+
+#ifdef FUSE_DEV_DEBUG
+    printf("write %x bytes\n", uio->uio_resid);
+#endif
+
+    if (uio->uio_resid < sizeof(struct fuse_out_header)) {
+        printf("uio goes wrong\n");
+        return (EINVAL);
+    }
+
+    /*
+     * get out header
+     */
+
+    if ((error = uiomove(&hdr, sizeof(struct fuse_out_header), uio)) != 0){
+        printf("uiomove failed\n");
+        return (error);
+    }
+#ifdef FUSE_DEV_DEBUG
+    printf("hdr w:\n");
+    dump_buff((char *)&hdr, sizeof(struct fuse_out_header));
+#endif
+    /*
+     * check header validity
+     */
+    if (uio->uio_resid + sizeof(struct fuse_out_header) != hdr.len ||
+        (uio->uio_resid && hdr.error) || TAILQ_EMPTY(&fmq_wait) ) {
+        printf("corrupted fuse header or queue empty\n");
+        return (EINVAL);
+    }
+
+    /* fuse errno are negative */
+    if (hdr.error)
+        hdr.error = -(hdr.error);
+
+    TAILQ_FOREACH(msg, &fmq_wait, node) {
+        if (msg->hdr->unique == hdr.unique) {
+#ifdef FUSE_DEV_DEBUG
+            printf("catch unique %i\n", msg->hdr->unique);
+#endif
+            catched = 1;
+            break;
+        }
+    }
+
+    if (catched) {
+        if (uio->uio_resid > 0) {
+            len = uio->uio_resid;
+            data = malloc(len, M_FUSEFS, M_WAITOK);
+            error = uiomove(data, len, uio);
+
+#ifdef FUSE_DEV_DEBUG
+            printf("data w:\n");
+            dump_buff(data, len);
+#endif
+
+        } else {
+            data = NULL;
+        }
+
+#ifdef FUSE_DEV_DEBUG
+        printf("call callback\n");
+#endif
+
+        if (!error)
+            msg->cb(msg, &hdr, data);
+
+        TAILQ_REMOVE(&fmq_wait, msg, node);
+
+        if (msg->type == msg_buff_async) {
+              free(msg->hdr, M_FUSEFS);
+            free(msg, M_FUSEFS);
+
+            if (data)
+                free(data, M_FUSEFS);
+        }
+
+    } else {
+        error = EINVAL;
+    }
+
+    return error;
+}
+
+int
+fusepoll(dev_t dev, int events, struct proc *p)
+{
+    int revents = 0;
+
+#ifdef FUSE_DEV_DEBUG
+    printf("fuse poll\n");
+#endif
+
+    if (events & (POLLIN | POLLRDNORM)) {
+        if (!TAILQ_EMPTY(&fmq_in))
+            revents |= events & (POLLIN | POLLRDNORM);
+    }
+
+    if (events & (POLLOUT | POLLWRNORM))
+        revents |= events & (POLLOUT | POLLWRNORM);
+
+    return (revents);
+}
Index: miscfs/fuse/fuse_file.c
===================================================================
RCS file: miscfs/fuse/fuse_file.c
diff -N miscfs/fuse/fuse_file.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_file.c    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+int
+fuse_file_open(struct fuse_mnt *fmp, struct fuse_node *ip,
+           enum fufh_type fufh_type, int flags, int isdir)
+{
+    struct fuse_open_out *open_out;
+    struct fuse_open_in open_in;
+    struct fuse_in_header hdr;
+    struct fuse_msg msg;
+    int error;
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.data = &open_in;
+    msg.len = sizeof(open_in);
+    msg.cb = &fuse_sync_resp;
+    msg.fmp = fmp;
+    msg.type = msg_buff;
+
+    open_in.flags = flags;
+    open_in.mode = 0;
+    msg.rep.buff.data_rcv = NULL;
+    msg.rep.buff.len = sizeof(*open_out);
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, ((isdir)?FUSE_OPENDIR:FUSE_OPEN),
+             ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse open", 0);
+
+    if (error)
+        return error;
+
+    open_out = (struct fuse_open_out *)msg.rep.buff.data_rcv;
+
+    ip->fufh[fufh_type].fh_id = open_out->fh;
+    ip->fufh[fufh_type].fh_type = fufh_type;
+
+    free(open_out, M_FUSEFS);
+
+    return 0;
+}
+
+int
+fuse_file_close(struct fuse_mnt *fmp, struct fuse_node * ip,
+        enum fufh_type  fufh_type, int flags, int isdir)
+{
+    struct fuse_release_in rel;
+    struct fuse_in_header hdr;
+    struct fuse_msg msg;
+    int error;
+
+    bzero(&msg, sizeof(msg));
+    bzero(&rel, sizeof(rel));
+    msg.hdr = &hdr;
+    msg.data = &rel;
+    msg.len = sizeof(rel);
+    msg.cb = &fuse_sync_it;
+    msg.fmp = fmp;
+    msg.type = msg_intr;
+
+    rel.fh  = ip->fufh[fufh_type].fh_id;
+    rel.flags = flags;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len,
((isdir)?FUSE_RELEASEDIR:FUSE_RELEASE),
+             ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse close", 0);
+
+    if (error)
+        return error;
+
+    error = msg.rep.it_res;
+    if (error)
+        printf("error %d\n", error);
+
+    ip->fufh[fufh_type].fh_id = (uint64_t)-1;
+    ip->fufh[fufh_type].fh_type = FUFH_INVALID;
+
+    return (error);
+}
Index: miscfs/fuse/fuse_kernel.h
===================================================================
RCS file: miscfs/fuse/fuse_kernel.h
diff -N miscfs/fuse/fuse_kernel.h
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_kernel.h    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,233 @@
+/*
+    Copyright (C) 2012-2013 Sylvestre Gallon <[hidden email]>
+    Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+#ifndef __FUSE_KERNEL_H__
+#define __FUSE_KERNEL_H__
+
+#define FUSE_KERNEL_VERSION 7
+#define FUSE_KERNEL_MINOR_VERSION 8
+
+/** The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+struct fuse_kstatfs {
+    uint64_t blocks;
+    uint64_t bfree;
+    uint64_t bavail;
+    uint64_t files;
+    uint64_t ffree;
+    uint32_t bsize;
+    uint32_t namelen;
+    uint32_t frsize;
+    uint32_t padding;
+    uint32_t spare[6];
+};
+
+enum fuse_opcode {
+    FUSE_LOOKUP =        1,
+    FUSE_FORGET =        2,  /* no reply */
+    FUSE_GETATTR =        3,
+    FUSE_SETATTR =        4,
+    FUSE_READLINK =        5,
+    FUSE_SYMLINK =        6,
+    FUSE_MKNOD =        8,
+    FUSE_MKDIR =        9,
+    FUSE_UNLINK =        10,
+    FUSE_RMDIR =        11,
+    FUSE_RENAME =        12,
+    FUSE_LINK =        13,
+    FUSE_OPEN =        14,
+    FUSE_READ =        15,
+    FUSE_WRITE =        16,
+    FUSE_STATFS =        17,
+    FUSE_RELEASE =        18,
+    FUSE_FSYNC =        20,
+    FUSE_SETXATTR =        21,
+    FUSE_GETXATTR =        22,
+    FUSE_LISTXATTR =    23,
+    FUSE_REMOVEXATTR =    24,
+    FUSE_FLUSH =        25,
+    FUSE_INIT =        26,
+    FUSE_OPENDIR =        27,
+    FUSE_READDIR =        28,
+    FUSE_RELEASEDIR =    29,
+    FUSE_FSYNCDIR =        30,
+    FUSE_GETLK =        31,
+    FUSE_SETLK =        32,
+    FUSE_SETLKW =        33,
+    FUSE_ACCESS =        34,
+    FUSE_CREATE =        35,
+    FUSE_INTERRUPT =    36,
+    FUSE_BMAP =        37,
+    FUSE_DESTROY =        38,
+};
+
+struct fuse_in_header {
+    uint32_t len;
+    uint32_t opcode;
+    uint64_t unique;
+    uint64_t nodeid;
+    uint32_t uid;
+    uint32_t gid;
+    uint32_t pid;
+    uint32_t padding;
+};
+
+struct fuse_init_in {
+    uint32_t major;
+    uint32_t minor;
+    uint32_t max_readahead;
+    uint32_t flags;
+};
+
+struct fuse_out_header {
+    uint32_t len;
+    uint32_t error;
+    uint64_t unique;
+};
+
+struct fuse_init_out {
+    uint32_t major;
+    uint32_t minor;
+    uint32_t max_readahead;
+    uint32_t flags;
+    uint32_t unused;
+    uint32_t max_write;
+};
+
+struct fuse_statfs_out {
+    struct fuse_kstatfs st;
+};
+
+struct fuse_attr {
+    uint64_t ino;
+    uint64_t size;
+    uint64_t blocks;
+    uint64_t atime;
+    uint64_t mtime;
+    uint64_t ctime;
+    uint32_t atimensec;
+    uint32_t mtimensec;
+    uint32_t ctimensec;
+    uint32_t mode;
+    uint32_t nlink;
+    uint32_t uid;
+    uint32_t gid;
+    uint32_t rdev;
+};
+
+struct fuse_attr_in {
+    uint32_t getattr_flags;
+    uint32_t dummy;
+    uint32_t fh;
+};
+
+struct fuse_attr_out {
+    uint64_t attr_valid;
+    uint32_t attr_valid_nsec;
+    uint32_t dummy;
+    struct fuse_attr attr;
+};
+
+struct fuse_access_in {
+    uint32_t mask;
+    uint32_t padding;
+};
+
+struct fuse_open_in {
+    uint32_t flags;
+    uint32_t mode;
+};
+
+struct fuse_open_out {
+    uint64_t fh;
+    uint32_t open_flags;
+    uint32_t padding;
+};
+
+struct fuse_release_in {
+    uint64_t fh;
+    uint32_t flags;
+    uint32_t release_flags;
+    uint64_t lock_owner;
+};
+
+struct fuse_read_in {
+    uint64_t fh;
+    uint64_t offset;
+    uint32_t size;
+    uint32_t padding;
+};
+
+struct fuse_dirent {
+    uint64_t ino;
+    uint64_t off;
+    uint32_t namelen;
+    uint32_t type;
+    char name[0];
+};
+
+struct pseudo_dirent {
+    uint32_t d_namlen;
+};
+
+struct fuse_entry_out {
+    uint64_t nodeid;
+    uint64_t generation;
+
+    uint64_t entry_valid;    /* Cache timeout for the name */
+    uint64_t attr_valid;    /* Cache timeout for the attributes */
+    uint32_t entry_valid_nsec;
+    uint32_t attr_valid_nsec;
+    struct fuse_attr attr;
+};
+
+struct fuse_mkdir_in {
+    uint32_t mode;
+    uint32_t padding;
+};
+
+struct fuse_link_in {
+    uint64_t oldnodeid;
+};
+
+struct fuse_write_in {
+    uint64_t fh;
+    uint64_t offset;
+    uint32_t size;
+    uint32_t write_flags;
+};
+
+struct fuse_write_out {
+    uint32_t size;
+    uint32_t padding;
+};
+
+#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
+#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
+#define FUSE_DIRENT_SIZE(d) \
+    FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
+
+#endif /* __FUSEFS_H__ */
Index: miscfs/fuse/fuse_lookup.c
===================================================================
RCS file: miscfs/fuse/fuse_lookup.c
diff -N miscfs/fuse/fuse_lookup.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_lookup.c    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/dirent.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+extern int fusefs_lookup(void *);
+
+int
+fusefs_lookup(void *v)
+{
+    struct vop_lookup_args *ap = v;
+    struct vnode *vdp;    /* vnode for directory being searched */
+    struct fuse_node *dp;    /* inode for directory being searched */
+    struct fuse_mnt *fmp;    /* file system that directory is in */
+    int lockparent;        /* 1 => lockparent flag is set */
+    struct vnode *tdp;    /* returned by VOP_VGET */
+    struct fuse_in_header hdr;
+    struct fuse_msg msg;
+    struct vnode **vpp = ap->a_vpp;
+    struct componentname *cnp = ap->a_cnp;
+    struct ucred *cred = cnp->cn_cred;
+    struct fuse_entry_out *feo = NULL;
+    int flags;
+    int nameiop = cnp->cn_nameiop;
+    /*struct proc *p = cnp->cn_proc;*/
+    int error = 0;
+    uint64_t nid;
+
+    flags = cnp->cn_flags;
+    *vpp = NULL;
+    vdp = ap->a_dvp;
+    dp = VTOI(vdp);
+    fmp = dp->i_mnt;
+    lockparent = flags & LOCKPARENT;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("lookup path %s\n", cnp->cn_pnbuf);
+    printf("lookup file %s\n", cnp->cn_nameptr);
+#endif
+
+    if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0)
+        return (error);
+
+    if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
+        (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+        return (EROFS);
+
+    if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
+        return (error);
+
+    /* if we get ".." */
+    if (flags & ISDOTDOT) {
+        nid = dp->parent;
+        if (nid == 0) {
+            return ENOENT;
+        }
+    } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
/* if we get "." */
+        nid = dp->i_number;
+    } else { /* if we get a real entry */
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = cnp->cn_namelen + 1;
+
+        msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+        memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+        ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+        msg.type = msg_buff;
+        msg.rep.buff.len = 0;
+        msg.rep.buff.data_rcv = NULL;
+        msg.cb = &fuse_sync_resp;
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_LOOKUP,
dp->i_number, curproc);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        error = tsleep(&msg, PWAIT, "fuse lookup", 0);
+
+        if (error)
+            return (error);
+
+        if (msg.error) {
+            if ((nameiop == CREATE || nameiop == RENAME) && (flags &
ISLASTCN) ) {
+                if (vdp->v_mount->mnt_flag & MNT_RDONLY)
+                    return EROFS;
+
+                cnp->cn_flags |= SAVENAME;
+
+                if (!lockparent) {
+                    VOP_UNLOCK(vdp, 0, curproc);
+                    cnp->cn_flags |= PDIRUNLOCK;
+                }
+
+                error = EJUSTRETURN;
+                goto out;
+            }
+
+            error = ENOENT;
+            goto out;
+        }
+
+        feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+        nid = feo->nodeid;
+    }
+
+    if (nameiop == DELETE && (flags & ISLASTCN)) {
+        /*
+         * Write access to directory required to delete files.
+         */
+        if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0)
+            return (error);
+
+        cnp->cn_flags |= SAVENAME;
+    }
+
+    if (flags & ISDOTDOT) {
+        printf("lookup for ..\n");
+        VOP_UNLOCK(vdp, 0, curproc);    /* race to get the inode */
+        cnp->cn_flags |= PDIRUNLOCK;
+
+        error = VFS_VGET(fmp->mp, nid, &tdp);
+
+        if (error) {
+            if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, curproc) == 0)
+                cnp->cn_flags &= ~PDIRUNLOCK;
+
+            return (error);
+        }
+
+        if (lockparent && (flags & ISLASTCN)) {
+            if ((error = vn_lock(vdp, LK_EXCLUSIVE, curproc))) {
+                vput(tdp);
+                return (error);
+            }
+            cnp->cn_flags &= ~PDIRUNLOCK;
+        }
+        *vpp = tdp;
+
+    } else if (nid == dp->i_number) {
+        vref(vdp);
+        *vpp = vdp;
+        error = 0;
+    } else {
+        error = VFS_VGET(fmp->mp, nid, &tdp);
+
+        if (!error) {
+            tdp->v_type = IFTOVT(feo->attr.mode);
+            VTOI(tdp)->vtype = tdp->v_type;
+        }
+
+        fuse_internal_attr_fat2vat(fmp->mp, &feo->attr,
&(VTOI(tdp)->cached_attrs));
+        free(feo, M_FUSEFS);
+
+        if (error)
+            return (error);
+
+        if (vdp != NULL && vdp->v_type == VDIR) {
+            VTOI(tdp)->parent = dp->i_number;
+        }
+        if (!lockparent || !(flags & ISLASTCN)) {
+            VOP_UNLOCK(vdp, 0, curproc);
+            cnp->cn_flags |= PDIRUNLOCK;
+        }
+
+        *vpp = tdp;
+    }
+
+out:
+    if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE && nameiop != DELETE )
+        cache_enter(vdp, *vpp, cnp);
+
+    return (error);
+}
Index: miscfs/fuse/fuse_node.c
===================================================================
RCS file: miscfs/fuse/fuse_node.c
diff -N miscfs/fuse/fuse_node.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_node.c    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+LIST_HEAD(ihashhead, fuse_node) *fhashtbl;
+u_long    fhash;        /* size of hash table - 1 */
+#define    INOHASH(fd, inum)    (&fhashtbl[((fd) + (inum)) & fhash])
+
+void
+fusefs_ihashinit(void)
+{
+    fhashtbl = hashinit(desiredvnodes, M_FUSEFS, M_WAITOK, &fhash);
+}
+
+
+/*
+ * Use the fd/inum pair to find the incore inode, and return a pointer
+ * to it. If it is in core, but locked, wait for it.
+ */
+struct vnode *
+fusefs_ihashget(int fd, ino_t inum)
+{
+    struct proc *p = curproc;
+    struct fuse_node *ip;
+    struct vnode *vp;
+loop:
+    /* XXXLOCKING lock hash list */
+    LIST_FOREACH(ip, INOHASH(fd, inum), i_hash) {
+        if (inum == ip->i_number && fd == ip->i_fd) {
+            vp = ITOV(ip);
+            /* XXXLOCKING unlock hash list? */
+            if (vget(vp, LK_EXCLUSIVE, p))
+                goto loop;
+            return (vp);
+         }
+    }
+    /* XXXLOCKING unlock hash list? */
+    return (NULL);
+}
+
+int
+fusefs_ihashins(struct fuse_node *ip)
+{
+    struct fuse_node *curip;
+    struct ihashhead *ipp;
+    int fd = ip->i_fd;
+    ino_t inum = ip->i_number;
+
+    /* lock the inode, then put it on the appropriate hash list */
+    lockmgr(&ip->i_lock, LK_EXCLUSIVE, NULL);
+
+    /* XXXLOCKING lock hash list */
+
+    LIST_FOREACH(curip, INOHASH(fd, inum), i_hash) {
+        if (inum == curip->i_number && fd == curip->i_fd) {
+            /* XXXLOCKING unlock hash list? */
+            lockmgr(&ip->i_lock, LK_RELEASE, NULL);
+            return (EEXIST);
+        }
+    }
+
+    ipp = INOHASH(fd, inum);
+    LIST_INSERT_HEAD(ipp, ip, i_hash);
+    /* XXXLOCKING unlock hash list? */
+
+    return (0);
+}
+/*
+ * Remove the inode from the hash table.
+ */
+void
+fusefs_ihashrem(struct fuse_node *ip)
+{
+    /* XXXLOCKING lock hash list */
+
+    if (ip->i_hash.le_prev == NULL)
+        return;
+
+    LIST_REMOVE(ip, i_hash);
+#ifdef DIAGNOSTIC
+    ip->i_hash.le_next = NULL;
+    ip->i_hash.le_prev = NULL;
+#endif
+    /* XXXLOCKING unlock hash list? */
+}
Index: miscfs/fuse/fuse_node.h
===================================================================
RCS file: miscfs/fuse/fuse_node.h
diff -N miscfs/fuse/fuse_node.h
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_node.h    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FUSE_NODE_H__
+#define __FUSE_NODE_H__
+
+enum fufh_type {
+    FUFH_INVALID = -1,
+    FUFH_RDONLY  = 0,
+    FUFH_WRONLY  = 1,
+    FUFH_RDWR    = 2,
+    FUFH_MAXTYPE = 3,
+};
+
+struct fuse_filehandle {
+    uint64_t fh_id;
+    enum fufh_type fh_type;
+};
+
+struct fuse_node {
+    LIST_ENTRY(fuse_node) i_hash;     /* Hash chain */
+    struct vnode *i_vnode;        /* vnode associated with this inode */
+    struct lockf *i_lockf;        /* Head of byte-level lock list. */
+    struct lock i_lock;            /* node lock */
+    ino_t i_number;            /* the identity of the inode */
+    int i_fd;                /* fd of fuse session */
+
+    struct fuse_mnt *i_mnt;        /* filesystem associated with this inode */
+    uint64_t parent;
+
+    /** I/O **/
+    struct     fuse_filehandle fufh[FUFH_MAXTYPE];
+
+    /** flags **/
+    uint32_t   flag;
+
+    /** meta **/
+    struct vattr      cached_attrs;
+    off_t             filesize;
+    uint64_t          nlookup;
+    enum vtype        vtype;
+};
+
+extern struct fuse_node **fusehashtbl;
+extern u_long fusehash;
+
+void fusefs_ihashinit(void);
+struct vnode *fusefs_ihashget(int, ino_t);
+int fusefs_ihashins(struct fuse_node *ip);
+void fusefs_ihashrem(struct fuse_node *ip);
+#define ITOV(ip) ((ip)->i_vnode)
+#define VTOI(vp) ((struct fuse_node *)(vp)->v_data)
+
+#endif /* __FUSE_NODE_H__ */
Index: miscfs/fuse/fuse_subr.c
===================================================================
RCS file: miscfs/fuse/fuse_subr.c
diff -N miscfs/fuse/fuse_subr.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_subr.c    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+void
+fuse_make_in(struct mount *mp, struct fuse_in_header *hdr, int len,
+         enum fuse_opcode op, ino_t ino, struct proc *p)
+{
+    struct fuse_mnt *fmp;
+
+    fmp = VFSTOFUSEFS(mp);
+
+    fmp->unique++;
+
+    hdr->len = sizeof(*hdr) + len;
+    hdr->opcode = op;
+    hdr->nodeid = ino;
+    hdr->unique = fmp->unique;
+#ifdef FUSE_DEBUG_MSG
+    printf("creat unique %i\n", hdr->unique);
+#endif
+
+    if (!p) {
+      hdr->pid = curproc->p_pid;
+      hdr->uid = 0;
+      hdr->gid = 0;
+    } else {
+      hdr->pid = p->p_pid;
+      hdr->uid = p->p_cred->p_ruid;
+      hdr->gid = p->p_cred->p_rgid;
+    }
+}
+
+void
+fuse_init_resp(struct fuse_msg *msg, struct fuse_out_header *hdr, void *data)
+{
+    struct fuse_init_out *out = data;
+
+#ifdef FUSE_DEBUG_MSG
+    printf("async init unique %i\n", msg->hdr->unique);
+    printf("init_out flags %i\n", out->flags);
+    printf("init_out major %i\n", out->major);
+    printf("init_out minor %i\n", out->minor);
+    printf("init_out max_readahead %i\n", out->max_readahead);
+    printf("init_out max_write %i\n", out->max_write);
+    printf("init_out unused %i\n", out->unused);
+#endif
+
+    msg->fmp->sess_init = 1;
+    msg->fmp->max_write = out->max_readahead;
+}
+
+void
+fuse_sync_resp(struct fuse_msg *msg, struct fuse_out_header *hdr, void *data)
+{
+    size_t len;
+
+#ifdef FUSE_DEBUG_MSG
+    printf("buf unique %i\n", msg->hdr->unique);
+#endif
+
+    if (msg->type != msg_buff)
+        printf("bad msg type\n");
+
+    if (data != NULL && msg->rep.buff.len != 0) {
+        len = hdr->len - sizeof(*hdr);
+        if (msg->rep.buff.len != len) {
+            printf("fusefs: packet size error on opcode %i\n",
msg->hdr->opcode);
+        }
+
+        if (msg->rep.buff.len > len)
+            printf("buff unused byte : 0x%x\n", msg->rep.buff.len - len);
+
+        msg->rep.buff.data_rcv = malloc(msg->rep.buff.len,  M_FUSEFS,
M_WAITOK | M_ZERO);
+        memcpy(msg->rep.buff.data_rcv, data, msg->rep.buff.len);
+
+        wakeup(msg);
+
+    } else if (data != NULL) {
+        len = hdr->len - sizeof(*hdr);
+        msg->rep.buff.data_rcv = malloc(len,  M_FUSEFS, M_WAITOK | M_ZERO);
+        memcpy(msg->rep.buff.data_rcv, data, len);
+        msg->rep.buff.len = len;
+
+        wakeup(msg);
+    } else if (hdr->error) {
+        msg->error = hdr->error;
+#ifdef FUSE_DEBUG_MSG
+        printf("error %i\n", msg->error);
+#endif
+        wakeup(msg);
+    } else {
+        msg->error = -1;
+#ifdef FUSE_DEBUG_MSG
+        printf("ack for msg\n");
+#endif
+        wakeup(msg);
+    }
+}
+
+void
+fuse_sync_it(struct fuse_msg *msg, struct fuse_out_header *hdr, void *data)
+{
+#ifdef FUSE_DEBUG_MSG
+    printf("it unique %i\n", msg->hdr->unique);
+#endif
+
+    if (msg->type != msg_intr)
+        printf("bad msg type\n");
+
+    if (data != NULL)
+        printf("normally data should be Null\n");
+
+    msg->rep.it_res = hdr->error;
+#ifdef FUSE_DEBUG_MSG
+    printf("errno = %d\n");
+#endif
+
+    wakeup(msg);
+}
Index: miscfs/fuse/fuse_vfsops.c
===================================================================
RCS file: miscfs/fuse/fuse_vfsops.c
diff -N miscfs/fuse/fuse_vfsops.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_vfsops.c    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/lock.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+static int    fusefs_mount(struct mount *mp, const char *path, void *data,
+                 struct nameidata *ndp, struct proc *p);
+static int    fusefs_start(struct mount *mp, int flags, struct proc *p);
+static int    fusefs_unmount(struct mount *mp, int mntflags, struct proc *p);
+static int    fusefs_root(struct mount *mp, struct vnode **vpp);
+static int    fusefs_quotactl(struct mount *mp, int cmds, uid_t uid,
+                caddr_t arg, struct proc *p);
+static int    fusefs_statfs(struct mount *mp, struct statfs *sbp,
+                  struct proc *p);
+static int    fusefs_sync(struct mount *mp, int waitfor, struct ucred *cred,
+                struct proc *p);
+static int    fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp);
+static int    fusefs_fhtovp(struct mount *mp, struct fid *fhp,
+                  struct vnode **vpp);
+static int    fusefs_vptofh(struct vnode *vp, struct fid *fhp);
+static int    fusefs_init(struct vfsconf *);
+static int    fusefs_sysctl(int *, u_int, void *, size_t *, void *,
+                  size_t, struct proc *);
+static int    fusefs_checkexp(struct mount *mp, struct mbuf *nam,
+                int *extflagsp, struct ucred **credanonp);
+
+const struct vfsops fusefs_vfsops = {
+    fusefs_mount,
+    fusefs_start,
+    fusefs_unmount,
+    fusefs_root,
+    fusefs_quotactl,
+    fusefs_statfs,
+    fusefs_sync,
+    fusefs_vget,
+    fusefs_fhtovp,
+    fusefs_vptofh,
+    fusefs_init,
+    fusefs_sysctl,
+    fusefs_checkexp
+};
+
+int
+fusefs_mount(struct mount *mp, const char *path, void *data,
+         struct nameidata *ndp, struct proc *p)
+{
+    struct fuse_mnt *fmp;
+    struct fuse_msg *msg;
+    struct fuse_init_in *init;
+    struct fusefs_args args;
+    int error;
+
+#ifdef FUSE_DEBUG_VFS
+    printf("mount\n");
+#endif
+
+    if (mp->mnt_flag & MNT_UPDATE)
+        return (EOPNOTSUPP);
+
+    error = copyin(data, &args, sizeof(struct fusefs_args));
+    if (error)
+        return error;
+
+#ifdef FUSE_DEBUG_VFS
+    printf("fd = %d\n", args.fd);
+#endif
+
+    fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO);
+    fmp->mp = mp;
+    fmp->sess_init = 0;
+    fmp->unique = 0;
+    fmp->fd = args.fd;
+    mp->mnt_data = (qaddr_t)fmp;
+
+    mp->mnt_flag |= MNT_LOCAL;
+    vfs_getnewfsid(mp);
+
+    bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
+    strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
+    bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
+    bcopy("fusefs", mp->mnt_stat.f_mntfromname, sizeof("fusefs"));
+
+    msg = malloc(sizeof(struct fuse_msg), M_FUSEFS, M_WAITOK | M_ZERO);
+    msg->hdr = malloc(sizeof(struct fuse_in_header), M_FUSEFS,
M_WAITOK | M_ZERO);
+    init = malloc(sizeof(struct fuse_init_in), M_FUSEFS, M_WAITOK | M_ZERO);
+
+    init->major = FUSE_KERNEL_VERSION;
+    init->minor = FUSE_KERNEL_MINOR_VERSION;
+    init->max_readahead = 4096 * 16;
+    init->flags = 0;
+    msg->data = init;
+    msg->len = sizeof(*init);
+    msg->cb = &fuse_init_resp;
+    msg->fmp = fmp;
+    msg->type = msg_buff_async;
+
+    fuse_make_in(mp, msg->hdr, msg->len, FUSE_INIT, 0, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, msg, node);
+    wakeup(&fmq_in);
+
+    return (0);
+}
+
+int
+fusefs_start(struct mount *mp, int flags, struct proc *p)
+{
+#ifdef FUSE_DEBUG_VFS
+    printf("start\n");
+#endif
+    return (0);
+}
+
+int
+fusefs_unmount(struct mount *mp, int mntflags, struct proc *p)
+{
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    extern int doforce;
+    struct fuse_msg *m;
+    int flags = 0;
+    int error;
+
+    fmp = VFSTOFUSEFS(mp);
+
+    if (!fmp->sess_init)
+        return 0;
+
+    fmp->sess_init = 0;
+
+#ifdef FUSE_DEBUG_VFS
+    printf("unmount\n");
+#endif
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = 0;
+    msg.type = msg_intr;
+    msg.data = NULL;
+    msg.cb = &fuse_sync_it;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_DESTROY, 0, curproc);
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse unmount", 0);
+
+    if (error)
+        return (error);
+
+    error = msg.rep.it_res;
+
+    if (error)
+        printf("error from fuse\n");
+
+    /* clear FIFO IN*/
+    while ((m = TAILQ_FIRST(&fmq_in))) {
+        printf("warning some msg where not processed....\n");
+    }
+
+    /* clear FIFO WAIT*/
+    while ((m = TAILQ_FIRST(&fmq_wait))) {
+        printf("warning some msg where not processed....\n");
+    }
+
+    if (mntflags & MNT_FORCE) {
+        /* fusefs can never be rootfs so don't check for it */
+        if (!doforce)
+            return (EINVAL);
+        flags |= FORCECLOSE;
+    }
+
+    if ((error = vflush(mp, 0, flags)))
+        return (error);
+
+    free(fmp, M_FUSEFS);
+
+    return (error);
+}
+
+int
+fusefs_root(struct mount *mp, struct vnode **vpp)
+{
+    struct vnode *nvp;
+    struct fuse_node *ip;
+    int error;
+
+#ifdef FUSE_DEBUG_VFS
+    printf("root\n");
+#endif
+
+    if ((error = VFS_VGET(mp, (ino_t)FUSE_ROOTINO, &nvp)) != 0)
+        return (error);
+
+    ip = VTOI(nvp);
+    nvp->v_type = VDIR;
+    ip->vtype = VDIR;
+
+    *vpp = nvp;
+    return (0);
+}
+
+int fusefs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
+            struct proc *p)
+{
+#ifdef FUSE_DEBUG_VFS
+    printf("quotactl\n");
+#endif
+
+    return (0);
+}
+
+int fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
+{
+      struct fuse_statfs_out *stat;
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error;
+
+#ifdef FUSE_DEBUG_VFS
+    printf("statfs\n");
+#endif
+
+    fmp = VFSTOFUSEFS(mp);
+
+    if (fmp->sess_init) {
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = 0;
+        msg.data = NULL;
+        msg.rep.buff.data_rcv = NULL;
+        msg.rep.buff.len = sizeof(*stat);
+        msg.cb = &fuse_sync_resp;
+        msg.type = msg_buff;
+
+        fuse_make_in(mp, msg.hdr, msg.len, FUSE_STATFS, FUSE_ROOT_ID, NULL);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        error = tsleep(&msg, PWAIT, "fuse stat", 0);
+        if (error) {
+            if (msg.rep.buff.data_rcv)
+                free(msg.rep.buff.data_rcv, M_FUSEFS);
+            return error;
+        }
+
+        stat = (struct fuse_statfs_out *)msg.rep.buff.data_rcv;
+
+#ifdef FUSE_DEBUG_VFS
+        printf("statfs a: %i\n", stat->st.bavail);
+        printf("statfs a: %i\n", stat->st.bfree);
+        printf("statfs a: %i\n", stat->st.blocks);
+        printf("statfs a: %i\n", stat->st.bsize);
+        printf("statfs a: %i\n", stat->st.ffree);
+        printf("statfs a: %i\n", stat->st.files);
+        printf("statfs a: %i\n", stat->st.frsize);
+        printf("statfs a: %i\n", stat->st.namelen);
+        printf("statfs a: %i\n", stat->st.padding);
+#endif
+
+        sbp->f_bavail = stat->st.bavail;
+        sbp->f_bfree = stat->st.bfree;
+        sbp->f_blocks = stat->st.blocks;
+        sbp->f_ffree = stat->st.ffree;
+        sbp->f_files = stat->st.files;
+        sbp->f_bsize = stat->st.frsize;
+        sbp->f_namemax = stat->st.namelen;
+
+        free(stat, M_FUSEFS);
+    } else {
+        sbp->f_bavail = 0;
+        sbp->f_bfree = 0;
+        sbp->f_blocks = 0;
+        sbp->f_ffree = 0;
+        sbp->f_files = 0;
+        sbp->f_bsize = 0;
+        sbp->f_namemax = 0;
+    }
+
+
+    return (0);
+}
+
+int fusefs_sync(struct mount *mp, int waitfor, struct ucred *cred,
+        struct proc *p)
+{
+#ifdef FUSE_DEBUG_VFS
+    printf("sync\n");
+#endif
+
+    return (0);
+}
+
+int fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
+{
+    struct fuse_mnt *fmp;
+    struct fuse_node *ip;
+    struct vnode *nvp;
+    int i;
+    int error;
+
+#ifdef FUSE_DEBUG_VFS
+    printf("vget\n");
+#endif
+retry:
+    fmp = VFSTOFUSEFS(mp);
+    /*
+     * check if vnode is in hash.
+     */
+    if ((*vpp = fusefs_ihashget(fmp->fd, ino)) != NULLVP)
+        return (0);
+
+    /*
+     * if not create it
+     */
+    if ((error = getnewvnode(VT_FUSEFS, mp, &fusefs_vops, &nvp)) != 0) {
+        printf("getnewvnode error\n");
+        *vpp = NULLVP;
+        return (error);
+    }
+
+    ip = malloc(sizeof(*ip), M_FUSEFS, M_WAITOK | M_ZERO);
+    lockinit(&ip->i_lock, PINOD, "fuseinode", 0, 0);
+    nvp->v_data = ip;
+    ip->i_vnode = nvp;
+    ip->i_fd = fmp->fd;
+    ip->i_number = ino;
+    ip->parent = 0;
+
+    for (i = 0; i < FUFH_MAXTYPE; i++)
+        ip->fufh[i].fh_type = FUFH_INVALID;
+
+    error = fusefs_ihashins(ip);
+    if (error) {
+        vrele(nvp);
+
+        if (error == EEXIST)
+            goto retry;
+
+        return (error);
+    }
+
+    ip->i_mnt = fmp;
+
+    if (ino == FUSE_ROOTINO)
+        nvp->v_flag |= VROOT;
+
+    *vpp = nvp;
+
+    return (0);
+}
+
+int fusefs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
+{
+#ifdef FUSE_DEBUG_VFS
+    printf("fhtovp\n");
+#endif
+
+    return (0);
+}
+
+int fusefs_vptofh(struct vnode *vp, struct fid *fhp)
+{
+ #ifdef FUSE_DEBUG_VFS
+    printf("vptofh\n");
+#endif
+
+    return (0);
+}
+
+int fusefs_init(struct vfsconf *vfc)
+{
+#ifdef FUSE_DEBUG_VFS
+    printf("init\n");
+#endif
+
+    TAILQ_INIT(&fmq_in);
+    TAILQ_INIT(&fmq_wait);
+
+    fusefs_ihashinit();
+    return (0);
+}
+
+int fusefs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldplen,
+          void *newp, size_t newlen, struct proc *p)
+{
+#ifdef FUSE_DEBUG_VFS
+    printf("sysctl\n");
+#endif
+
+    return (0);
+}
+
+int fusefs_checkexp(struct mount *mp, struct mbuf *nam, int *extflagsp,
+            struct ucred **credanonp)
+{
+#ifdef FUSE_DEBUG_VFS
+    printf("checkexp\n");
+#endif
+
+    return (0);
+}
Index: miscfs/fuse/fuse_vnops.c
===================================================================
RCS file: miscfs/fuse/fuse_vnops.c
diff -N miscfs/fuse/fuse_vnops.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_vnops.c    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,1341 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/dirent.h>
+#include <sys/specdev.h>
+#include <sys/poll.h>
+#include <sys/lockf.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+/*
+ * Prototypes for fusefs vnode ops
+ */
+extern int fusefs_lookup(void *);
+int    fusefs_open(void *);
+int    fusefs_close(void *);
+int    fusefs_access(void *);
+int    fusefs_getattr(void *);
+int    fusefs_setattr(void *);
+int    fusefs_ioctl(void *);
+int    fusefs_link(void *);
+int    fusefs_symlink(void *);
+int    fusefs_readdir(void *);
+int    fusefs_readlink(void *);
+int    fusefs_inactive(void *);
+int    fusefs_reclaim(void *);
+int    fusefs_print(void *);
+int    fusefs_create(void *);
+int    fusefs_mknod(void *);
+int    fusefs_read(void *);
+int    fusefs_write(void *);
+int    fusefs_poll(void *);
+int    fusefs_fsync(void *);
+int    fusefs_remove(void *);
+int    fusefs_rename(void *);
+int    fusefs_mkdir(void *);
+int    fusefs_rmdir(void *);
+int    fusefs_strategy(void *);
+int    fusefs_lock(void *);
+int    fusefs_unlock(void *);
+int    fusefs_islocked(void *);
+int    fusefs_advlock(void *);
+int    readdir_process_data(void *buff, int len, struct uio *uio);
+
+struct vops fusefs_vops = {
+    .vop_lookup    = fusefs_lookup,
+    .vop_create    = fusefs_create,
+    .vop_mknod    = fusefs_mknod,
+    .vop_open    = fusefs_open,
+    .vop_close    = fusefs_close,
+    .vop_access    = fusefs_access,
+    .vop_getattr    = fusefs_getattr,
+    .vop_setattr    = fusefs_setattr,
+    .vop_read    = fusefs_read,
+    .vop_write    = fusefs_write,
+    .vop_ioctl    = fusefs_ioctl,
+    .vop_poll    = fusefs_poll,
+    .vop_fsync    = fusefs_fsync,
+    .vop_remove    = fusefs_remove,
+    .vop_link    = fusefs_link,
+    .vop_rename    = fusefs_rename,
+    .vop_mkdir    = fusefs_mkdir,
+    .vop_rmdir    = fusefs_rmdir,
+    .vop_symlink    = fusefs_symlink,
+    .vop_readdir    = fusefs_readdir,
+    .vop_readlink    = fusefs_readlink,
+    .vop_abortop    = vop_generic_abortop,
+    .vop_inactive    = fusefs_inactive,
+    .vop_reclaim    = fusefs_reclaim,
+    .vop_lock    = fusefs_lock,
+    .vop_unlock    = fusefs_unlock,
+    .vop_bmap    = vop_generic_bmap,
+    .vop_strategy    = fusefs_strategy,
+    .vop_print    = fusefs_print,
+    .vop_islocked    = fusefs_islocked,
+    .vop_pathconf    = spec_pathconf,
+    .vop_advlock    = fusefs_advlock,
+};
+
+
+void
+fuse_internal_attr_fat2vat(struct mount *mp,
+                           struct fuse_attr *fat,
+                           struct vattr *vap)
+{
+    vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
+    vap->va_fileid = fat->ino;/* XXX cast from 64 bits to 32 */
+    vap->va_mode = fat->mode & ~S_IFMT;
+    vap->va_nlink = fat->nlink;
+    vap->va_uid = fat->uid;
+    vap->va_gid = fat->gid;
+    vap->va_rdev = fat->rdev;
+    vap->va_size = fat->size;
+    vap->va_atime.tv_sec = fat->atime;
+    vap->va_atime.tv_nsec = fat->atimensec;
+    vap->va_mtime.tv_sec = fat->mtime;
+    vap->va_mtime.tv_nsec = fat->mtimensec;
+    vap->va_ctime.tv_sec = fat->ctime;
+    vap->va_ctime.tv_nsec = fat->ctimensec;
+    vap->va_blocksize = PAGE_SIZE;
+    vap->va_type = IFTOVT(fat->mode);
+
+#if (S_BLKSIZE == 512)
+    /* Optimize this case */
+    vap->va_bytes = fat->blocks << 9;
+#else
+    vap->va_bytes = fat->blocks * S_BLKSIZE;
+#endif
+
+}
+
+int
+fusefs_open(void *v)
+{
+    struct vop_open_args *ap;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    enum fufh_type fufh_type;
+    int flags;
+    int error;
+    int isdir;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_open\n");
+#endif
+    ap = v;
+    ip = VTOI(ap->a_vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        return (0);
+    }
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("inode = %i mode=0x%x\n", ip->i_number, ap->a_mode);
+#endif
+    isdir = 0;
+    if (ip->vtype == VDIR) {
+        fufh_type = FUFH_RDONLY;
+        flags = O_RDONLY;
+        isdir = 1;
+    } else {
+        if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) {
+            fufh_type = FUFH_RDWR;
+            flags = O_RDWR;
+        }
+        else if (ap->a_mode  & (FWRITE)) {
+            fufh_type = FUFH_WRONLY;
+            flags = O_WRONLY;
+        }
+        else if (ap->a_mode & (FREAD)) {
+            fufh_type = FUFH_RDONLY;
+            flags = O_RDONLY;
+        }
+    }
+
+    /* already open i think all is ok */
+    if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+        return 0;
+
+    error = fuse_file_open(fmp, ip, fufh_type, flags, isdir);
+
+    if (error)
+        return (error);
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("file open fd : %i\n", ip->fufh[fufh_type].fh_id);
+#endif
+    return (error);
+}
+
+int
+fusefs_close(void *v)
+{
+    struct vop_close_args *ap;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    enum fufh_type fufh_type;
+    int isdir, flags, i;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_close\n");
+#endif
+
+    ap = v;
+    ip = VTOI(ap->a_vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        return (0);
+    }
+
+    isdir = 0;
+    if (ip->vtype == VDIR) {
+        fufh_type = FUFH_RDONLY;
+        isdir = 1;
+
+        if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+            return fuse_file_close(fmp, ip, fufh_type, O_RDONLY, isdir);
+    } else {
+        if (ap->a_fflag & IO_NDELAY) {
+            return (0);
+        }
+
+        if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE)) {
+            fufh_type = FUFH_RDWR;
+            flags = O_RDWR;
+        }
+        else if (ap->a_fflag  & (FWRITE)) {
+            fufh_type = FUFH_WRONLY;
+            flags = O_WRONLY;
+        }
+        else if (ap->a_fflag & (FREAD)) {
+            fufh_type = FUFH_RDONLY;
+            flags = O_RDONLY;
+        }
+    }
+
+    /*
+     * if fh not valid lookup for another valid fh in vnode.
+     * panic if there's not fh valid
+     */
+    if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) {
+        for (i = 0; i < FUFH_MAXTYPE; i++)
+            if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+                break;
+        return (0);
+    }
+
+    return (0);
+}
+
+int
+fusefs_access(void *v)
+{
+    struct fuse_access_in access;
+    struct vop_access_args *ap;
+    struct fuse_in_header hdr;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    uint32_t mask = 0;
+    int error = 0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_access\n");
+#endif
+    ap = v;
+    ip = VTOI(ap->a_vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_ACCESS))
+        goto system_check;
+
+    if (ap->a_vp->v_type == VLNK)
+        goto system_check;
+
+    if (ap->a_vp->v_type == VREG && (ap->a_mode & VWRITE & VEXEC))
+        goto system_check;
+
+    if ((ap->a_mode & VWRITE) && (fmp->mp->mnt_flag & MNT_RDONLY))
+        return(EACCES);
+
+    if ((ap->a_mode & VWRITE) != 0) {
+        mask |= 0x2;
+    }
+    if ((ap->a_mode & VREAD) != 0) {
+        mask |= 0x4;
+    }
+    if ((ap->a_mode & VEXEC) != 0) {
+        mask |= 0x1;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    access.mask = mask;
+    msg.data = &access;
+    msg.len = sizeof(access);
+    msg.cb = &fuse_sync_it;
+    msg.fmp = fmp;
+    msg.type = msg_intr;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_ACCESS,
ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse access", 0);
+
+    if (error)
+        return error;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("it with value %x\n", msg.rep.it_res);
+#endif
+    error = msg.rep.it_res;
+
+    if (error == ENOSYS) {
+        fmp->undef_op |= UNDEF_ACCESS;
+        goto system_check;
+    }
+
+    return (error);
+
+system_check:
+#ifdef FUSE_DEBUG_VNOP
+    printf("Use kernel access\n");
+#endif
+    return (vaccess(ap->a_vp->v_type, ip->cached_attrs.va_mode & ALLPERMS,
+        ip->cached_attrs.va_uid, ip->cached_attrs.va_gid, ap->a_mode,
ap->a_cred));
+}
+
+int
+fusefs_getattr(void *v)
+{
+      struct vop_getattr_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_mnt *fmp;
+    struct vattr *vap = ap->a_vap;
+    struct fuse_in_header hdr;
+    struct fuse_attr_out *fat;
+    struct fuse_node *ip;
+    struct fuse_msg msg;
+    int error = 0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_getattr\n");
+#endif
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        goto fake;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = 0;
+    msg.data = NULL;
+    msg.rep.buff.len = sizeof(*fat);
+    msg.rep.buff.data_rcv = NULL;
+    msg.type = msg_buff;
+    msg.cb = &fuse_sync_resp;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_GETATTR,
ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse getattr", 0);
+
+    if (error) {
+        if (msg.rep.buff.data_rcv != NULL)
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+        return (error);
+    }
+
+    fat = (struct fuse_attr_out *)msg.rep.buff.data_rcv;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("ino: %d\n", fat->attr.ino);
+    printf("size: %d\n", fat->attr.size);
+    printf("blocks: %d\n", fat->attr.blocks);
+    printf("atime: %d\n", fat->attr.atime);
+    printf("mtime: %d\n", fat->attr.mtime);
+    printf("ctime: %d\n", fat->attr.ctime);
+    printf("atimensec: %d\n", fat->attr.atimensec);
+    printf("mtimensec: %d\n", fat->attr.mtimensec);
+    printf("ctimensec: %d\n", fat->attr.ctimensec);
+    printf("mode: %d\n", fat->attr.mode);
+    printf("nlink: %d\n", fat->attr.nlink);
+    printf("uid: %d\n", fat->attr.uid);
+    printf("gid: %d\n", fat->attr.gid);
+    printf("rdev: %d\n", fat->attr.rdev);
+#endif
+
+    fuse_internal_attr_fat2vat(fmp->mp, &fat->attr, vap);
+
+    memcpy(&ip->cached_attrs, vap, sizeof(*vap));
+    free(fat, M_FUSEFS);
+
+    return (error);
+fake:
+    bzero(vap, sizeof(*vap));
+    vap->va_type = vp->v_type;
+    return (0);
+}
+
+int
+fusefs_setattr(void *v)
+{
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_setattr\n");
+#endif
+    return (0);
+}
+
+int
+fusefs_ioctl(void *v)
+{
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_ioctl\n");
+#endif
+    return (ENOTTY);
+}
+
+int
+fusefs_link(void *v)
+{
+    struct vop_link_args *ap = v;
+    struct vnode *dvp = ap->a_dvp;
+    struct vnode *vp = ap->a_vp;
+    struct componentname *cnp = ap->a_cnp;
+    struct fuse_in_header hdr;
+    struct fuse_entry_out *feo;
+    struct fuse_link_in fli;
+    struct fuse_mnt *fmp;
+    struct fuse_node *ip;
+    struct fuse_msg msg;
+    int error = 0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_link\n");
+#endif
+
+    if (vp->v_type == VDIR) {
+        VOP_ABORTOP(dvp, cnp);
+        error = EISDIR;
+        goto out2;
+    }
+    if (dvp->v_mount != vp->v_mount) {
+        VOP_ABORTOP(dvp, cnp);
+        error = EXDEV;
+        goto out2;
+    }
+    if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, curproc))) {
+        VOP_ABORTOP(dvp, cnp);
+        goto out2;
+    }
+
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_LINK))
+        goto out1;
+
+    fli.oldnodeid = ip->i_number;
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = sizeof(fli);
+    msg.data = &fli;
+    msg.rep.buff.len = sizeof(struct fuse_entry_out);
+    msg.rep.buff.data_rcv = NULL;
+    msg.type = msg_buff;
+    msg.cb = &fuse_sync_resp;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_LINK, ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse link", 0);
+
+    if (error) {
+        if (msg.rep.buff.data_rcv != NULL)
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+        goto out1;
+    }
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_LINK;
+        }
+
+        goto out1;
+    }
+
+    feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+    free(feo, M_FUSEFS);
+
+out1:
+    if (dvp != vp)
+        VOP_UNLOCK(vp, 0, curproc);
+out2:
+    vput(dvp);
+    return (error);
+}
+
+int
+fusefs_symlink(void *v)
+{
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_symlink\n");
+#endif
+    return (0);
+}
+
+#define GENERIC_DIRSIZ(dp) \
+    ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+
+int
+readdir_process_data(void *buff, int len, struct uio *uio)
+{
+    struct fuse_dirent *fdir;
+    struct dirent dir;
+    int bytesavail;
+    int flen, error = 0;
+
+    if (len < FUSE_NAME_OFFSET) {
+        return 0;
+    }
+
+    while ( len > 0) {
+        if ( len < sizeof(*fdir)) {
+            error = 0;
+            break;
+        }
+
+        fdir = (struct fuse_dirent *)buff;
+        flen = FUSE_DIRENT_SIZE(fdir);
+
+        if (!fdir->namelen || fdir->namelen > MAXNAMLEN || len < flen) {
+            error = EINVAL;
+            break;
+        }
+
+        bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *) &fdir->namelen);
+        if (bytesavail > uio->uio_resid) {
+            error = 0;
+            break;
+        }
+
+        bzero(&dir, sizeof(dir));
+        dir.d_fileno = fdir->ino;
+        dir.d_reclen = bytesavail;
+        dir.d_type = fdir->type;
+        dir.d_namlen = fdir->namelen;
+        bcopy(fdir->name, dir.d_name, fdir->namelen);
+
+        uiomove(&dir, bytesavail , uio);
+        len -= flen;
+        /* ugly pointer arithmetic must find something else ...*/
+        buff = (void *)(((char *) buff) + flen);
+        uio->uio_offset = fdir->off;
+    }
+
+    return (error);
+}
+
+int
+fusefs_readdir(void *v)
+{
+    struct vop_readdir_args *ap = v;
+    struct fuse_read_in read;
+    struct fuse_in_header hdr;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    struct vnode *vp;
+    struct uio *uio;
+    int error = 0;
+
+    vp = ap->a_vp;
+    uio = ap->a_uio;
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        return (0);
+    }
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_readdir\n");
+    printf("uio resid 0x%x\n", uio->uio_resid);
+#endif
+    if (uio->uio_resid == 0)
+        return (error);
+
+    while (uio->uio_resid > 0) {
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = sizeof(read);
+        msg.type = msg_buff;
+
+        msg.rep.buff.len= 0;
+        msg.rep.buff.data_rcv = NULL;
+        msg.data = &read;
+        msg.cb = &fuse_sync_resp;
+
+        if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) {
+              printf("dir not open\n");
+              /* TODO open the file */
+              return (error);
+        }
+        read.fh = ip->fufh[FUFH_RDONLY].fh_id;
+        read.offset = uio->uio_offset;
+        read.size = MIN(uio->uio_resid, PAGE_SIZE);
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READDIR,
ip->i_number, curproc);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        error = tsleep(&msg, PWAIT, "fuse getattr", 0);
+
+        if (error) {
+            if (msg.rep.buff.len != 0)
+                free(msg.rep.buff.data_rcv, M_FUSEFS);
+            return (error);
+        }
+
+        if (msg.error == -1) {
+            //ack for end of readdir
+            break;
+        }
+
+        if ((error = readdir_process_data(msg.rep.buff.data_rcv,
msg.rep.buff.len, uio))) {
+            if (msg.rep.buff.len != 0)
+                free(msg.rep.buff.data_rcv, M_FUSEFS);
+            break;
+        }
+
+        if (msg.rep.buff.len != 0)
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+    }
+
+    return (error);
+}
+
+int
+fusefs_inactive(void *v)
+{
+    struct vop_inactive_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct proc *p = ap->a_p;
+    register struct fuse_node *ip = VTOI(vp);
+    int error = 0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_inactive\n");
+#endif
+
+    ip->flag = 0;
+    VOP_UNLOCK(vp, 0, p);
+
+    /* not sure if it is ok to do like that ...*/
+    if (ip->cached_attrs.va_mode == 0)
+        vrecycle(vp, p);
+
+    return (error);
+}
+
+int
+fusefs_readlink(void *v)
+{
+      struct vop_readlink_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_in_header hdr;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    struct    uio *uio;
+    int error = 0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_readlink\n");
+#endif
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+    uio = ap->a_uio;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_READLINK)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = 0;
+    msg.data = NULL;
+    msg.type = msg_buff;
+    msg.rep.buff.len = 0;
+    msg.rep.buff.data_rcv = NULL;
+    msg.cb = &fuse_sync_resp;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READLINK,
ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse readlink", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_READLINK;
+        }
+        goto out;
+    }
+
+    error = uiomove(msg.rep.buff.data_rcv, msg.rep.buff.len, uio);
+
+out:
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+    return (error);
+}
+
+int
+fusefs_reclaim(void *v)
+{
+    struct vop_reclaim_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_node *ip = VTOI(vp);
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_reclaim\n");
+#endif
+    /*
+     * Purge old data structures associated with the inode.
+     */
+    ip->parent = 0;
+
+    /*
+     * Remove the inode from its hash chain.
+     */
+    fusefs_ihashrem(ip);
+    cache_purge(vp);
+
+    /*close file if exist
+    if (ip->i_fd) {
+        vrele(ip->i_devvp);
+        ip->i_devvp = 0;
+    }*/
+
+    free(ip, M_FUSEFS);
+    vp->v_data = NULL;
+    return (0);
+}
+
+int
+fusefs_print(void *v)
+{
+    struct vop_print_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_node *ip = VTOI(vp);
+
+    /*
+     * Complete the information given by vprint().
+     */
+    printf("tag VT_FUSE, hash id %u ", ip->i_number);
+    lockmgr_printinfo(&ip->i_lock);
+    printf("\n");
+    return (0);
+}
+
+int
+fusefs_create(void *v)
+{
+    struct vop_create_args *ap = v;
+    struct componentname *cnp = ap->a_cnp;
+    struct vnode **vpp = ap->a_vpp;
+    struct vnode *dvp = ap->a_dvp;
+    struct vattr *vap = ap->a_vap;
+    struct fuse_entry_out *feo;
+    struct fuse_in_header hdr;
+    struct vnode *tdp = NULL;
+    struct fuse_open_in foi;
+    struct fuse_mnt *fmp;
+    struct fuse_node *ip;
+    struct fuse_msg msg;
+    int error = 0;
+    mode_t mode;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_create(cnp %08x, vap %08x\n", cnp, vap);
+#endif
+    ip = VTOI(dvp);
+    fmp = ip->i_mnt;
+    mode = MAKEIMODE(vap->va_type, vap->va_mode);
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_CREATE)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = sizeof(foi) + cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_buff;
+    msg.rep.buff.len = sizeof(struct fuse_entry_out) + sizeof(struct
fuse_open_out);
+    msg.rep.buff.data_rcv = NULL;
+    msg.cb = &fuse_sync_resp;
+
+    foi.mode = mode;
+    foi.flags = O_CREAT | O_RDWR;
+
+    memcpy(msg.data, &foi, sizeof(foi));
+    memcpy((char *)msg.data + sizeof(foi), cnp->cn_nameptr, cnp->cn_namelen);
+    ((char *)msg.data)[sizeof(foi) + cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_CREATE,
ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse create", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_CREATE;
+        }
+        goto out;
+    }
+
+    feo = msg.rep.buff.data_rcv;
+    if ((error = VFS_VGET(fmp->mp, feo->nodeid, &tdp)))
+        goto out;
+
+    tdp->v_type = IFTOVT(feo->attr.mode);
+    VTOI(tdp)->vtype = tdp->v_type;
+
+    if (dvp != NULL && dvp->v_type == VDIR)
+        VTOI(tdp)->parent = ip->i_number;
+
+    *vpp = tdp;
+    VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+
+out:
+    vput(ap->a_dvp);
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+
+    return (error);
+}
+
+int
+fusefs_mknod(void *v)
+{
+    struct vop_mknod_args *ap = v;
+
+    VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+    vput(ap->a_dvp);
+    return (EINVAL);
+}
+
+int
+fusefs_read(void *v)
+{
+    struct vop_read_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct uio *uio = ap->a_uio;
+    struct fuse_in_header hdr;
+    struct fuse_read_in fri;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error=0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_read\n");
+#endif
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+#ifdef FUSE_DEBUG_VNOP
+    printf("read inode=%i, offset=%p, resid=%p\n", ip->i_mnt,
+           uio->uio_offset, uio->uio_resid);
+#endif
+
+    if (uio->uio_resid == 0)
+        return (error);
+    if (uio->uio_offset < 0)
+        return (EINVAL);
+
+    while (uio->uio_resid > 0) {
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = sizeof(fri);
+        msg.data = &fri;
+        msg.type = msg_buff;
+        msg.rep.buff.len = 0;
+        msg.rep.buff.data_rcv = NULL;
+        msg.cb = &fuse_sync_resp;
+
+        fri.fh = ip->fufh[FUFH_RDONLY].fh_id;
+        fri.offset = uio->uio_offset;
+        fri.size = MIN(uio->uio_resid, fmp->max_write);
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READ,
ip->i_number, curproc);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        if ((error = tsleep(&msg, PWAIT, "fuse read", 0)))
+            break;
+
+        if ((error = uiomove(msg.rep.buff.data_rcv, MIN(fri.size,
msg.rep.buff.len), uio))) {
+            break;
+        }
+
+        if (msg.rep.buff.len < fri.size)
+            break;
+
+        if (msg.rep.buff.data_rcv) {
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+            msg.rep.buff.data_rcv = NULL;
+        }
+    }
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+    return (error);
+}
+
+int
+fusefs_write(void *v)
+{
+    struct vop_write_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct uio *uio = ap->a_uio;
+    struct fuse_in_header hdr;
+    struct fuse_write_in fwi;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    size_t len, diff;
+    int error=0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_write\n");
+#endif
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+#ifdef FUSE_DEBUG_VNOP
+    printf("write inode=%i, offset=%x, resid=%x\n", ip->i_mnt,
+           uio->uio_offset, uio->uio_resid);
+#endif
+
+    if (!uio->uio_resid)
+        return (error);
+
+    while (uio->uio_resid > 0) {
+        len = MIN(uio->uio_resid, fmp->max_write);
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = sizeof(fwi) + len;
+        msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+        msg.type = msg_buff;
+        msg.rep.buff.len = sizeof(struct fuse_write_out);
+        msg.rep.buff.data_rcv = NULL;
+        msg.cb = &fuse_sync_resp;
+
+        fwi.fh = ip->fufh[FUFH_WRONLY].fh_id;
+        fwi.offset = uio->uio_offset;
+        fwi.size = len;
+
+        memcpy(msg.data, &fwi, sizeof(fwi));
+        if ((error = uiomove((char *)msg.data + sizeof(fwi), len, uio)))
+            break;
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_WRITE,
ip->i_number, curproc);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        if ((error = tsleep(&msg, PWAIT, "fuse write", 0)))
+            break;
+
+        diff = len - ((struct fuse_write_out *)msg.rep.buff.data_rcv)->size;
+        if (diff < 0) {
+            error = EINVAL;
+            break;
+        }
+
+        uio->uio_resid += diff;
+        uio->uio_offset -= diff;
+
+        if (msg.rep.buff.data_rcv) {
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+            msg.rep.buff.data_rcv = NULL;
+        }
+    }
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+    return (error);
+}
+
+int
+fusefs_poll(void *v)
+{
+    struct vop_poll_args *ap = v;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_poll\n");
+#endif
+
+    /*
+     * We should really check to see if I/O is possible.
+     */
+    return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
+}
+
+int
+fusefs_fsync(void *v)
+{
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_fsync\n");
+#endif
+    return 0;
+}
+
+int
+fusefs_rename(void *v)
+{
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_rename\n");
+#endif
+    return 0;
+}
+
+int
+fusefs_mkdir(void *v)
+{
+    struct vop_mkdir_args *ap = v;
+    struct vnode *dvp = ap->a_dvp;
+    struct vnode **vpp = ap->a_vpp;
+    struct componentname *cnp = ap->a_cnp;
+    struct vattr *vap = ap->a_vap;
+    struct fuse_mkdir_in fmdi;
+    struct vnode *tdp = NULL;
+    struct fuse_in_header hdr;
+    struct fuse_entry_out *feo;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error = 0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_mkdir %s\n", cnp->cn_nameptr);
+#endif
+    ip = VTOI(dvp);
+    fmp = ip->i_mnt;
+    fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKDIR)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = sizeof(fmdi) + cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_buff;
+    msg.rep.buff.len = sizeof(struct fuse_entry_out);
+    msg.rep.buff.data_rcv = NULL;
+    msg.cb = &fuse_sync_resp;
+
+    memcpy(msg.data, &fmdi, sizeof(fmdi));
+    memcpy((char *)msg.data + sizeof(fmdi), cnp->cn_nameptr, cnp->cn_namelen);
+    ((char *)msg.data)[sizeof(fmdi) + cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_MKDIR, ip->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse mkdir", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_MKDIR;
+        }
+        goto out;
+    }
+
+    feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+
+    if ((error = VFS_VGET(fmp->mp, feo->nodeid, &tdp)))
+        goto out;
+
+    tdp->v_type = IFTOVT(feo->attr.mode);
+    VTOI(tdp)->vtype = tdp->v_type;
+
+    if (dvp != NULL && dvp->v_type == VDIR)
+        VTOI(tdp)->parent = ip->i_number;
+
+    *vpp = tdp;
+    VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
+
+out:
+    vput(dvp);
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+
+    return (error);
+}
+
+int
+fusefs_rmdir(void *v)
+{
+    struct vop_rmdir_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
+    struct componentname *cnp = ap->a_cnp;
+    struct fuse_node *ip, *dp;
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_rmdir\n");
+    printf("len :%i, cnp: %c %c %c\n", cnp->cn_namelen,
cnp->cn_nameptr[0], cnp->cn_nameptr[1], cnp->cn_nameptr[2]);
+#endif
+    ip = VTOI(vp);
+    dp = VTOI(dvp);
+    fmp = ip->i_mnt;
+
+    /*
+     * No rmdir "." please.
+     */
+    if (dp == ip) {
+        vrele(dvp);
+        vput(vp);
+        return (EINVAL);
+    }
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_RMDIR)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_intr;
+    msg.cb = &fuse_sync_it;
+
+    memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+    ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_RMDIR, dp->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse rmdir", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS)
+            fmp->undef_op |= UNDEF_RMDIR;
+        if (error != ENOTEMPTY)
+            VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+        goto out;
+    }
+
+    VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+    cache_purge(dvp);
+    vput(dvp);
+    dvp = NULL;
+
+    cache_purge(ITOV(ip));
+out:
+    if (dvp)
+        vput(dvp);
+    VN_KNOTE(vp, NOTE_DELETE);
+    vput(vp);
+    return (error);
+}
+
+int
+fusefs_remove(void *v)
+{
+    struct vop_remove_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
+    struct componentname *cnp = ap->a_cnp;
+    struct fuse_node *ip;
+    struct fuse_node *dp;
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error = 0;
+
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_remove\n");
+    printf("len :%i, cnp: %c %c %c\n", cnp->cn_namelen,
cnp->cn_nameptr[0], cnp->cn_nameptr[1], cnp->cn_nameptr[2]);
+#endif
+    ip = VTOI(vp);
+    dp = VTOI(dvp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_REMOVE)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_intr;
+    msg.cb = &fuse_sync_it;
+
+    memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+    ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_UNLINK,
dp->i_number, curproc);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+
+    if ((error = tsleep(&msg, PWAIT, "fuse remove", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS)
+            fmp->undef_op |= UNDEF_REMOVE;
+        goto out;
+    }
+
+
+    VN_KNOTE(vp, NOTE_DELETE);
+    VN_KNOTE(dvp, NOTE_WRITE);
+out:
+    if (dvp == vp)
+        vrele(vp);
+    else
+        vput(vp);
+    vput(dvp);
+    return (error);
+}
+
+int
+fusefs_strategy(void *v)
+{
+#ifdef FUSE_DEBUG_VNOP
+    printf("fusefs_strategy\n");
+#endif
+    return 0;
+}
+
+int
+fusefs_lock(void *v)
+{
+    struct vop_lock_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+
+#ifdef FUSE_LOCK
+    printf("fuse_lock\n");
+#endif
+    return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, NULL));
+}
+
+int
+fusefs_unlock(void *v)
+{
+    struct vop_unlock_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+
+#ifdef FUSE_LOCK
+    printf("fuse_unlock\n");
+#endif
+    return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, NULL));
+}
+
+int
+fusefs_islocked(void *v)
+{
+    struct vop_islocked_args *ap = v;
+
+#ifdef FUSE_LOCK
+    printf("fuse_islock\n");
+#endif
+    return (lockstatus(&VTOI(ap->a_vp)->i_lock));
+}
+
+int
+fusefs_advlock(void *v)
+{
+    struct vop_advlock_args *ap = v;
+    struct fuse_node *ip = VTOI(ap->a_vp);
+
+#ifdef FUSE_LOCK
+    printf("fuse_advlock\n");
+#endif
+    return (lf_advlock(&ip->i_lockf, ip->filesize, ap->a_id, ap->a_op,
+        ap->a_fl, ap->a_flags));
+}
Index: miscfs/fuse/fusefs.h
===================================================================
RCS file: miscfs/fuse/fusefs.h
diff -N miscfs/fuse/fusefs.h
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fusefs.h    5 Mar 2013 15:16:09 -0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FUSEFS_H__
+#define __FUSEFS_H__
+
+struct fuse_msg;
+
+struct fuse_mnt {
+    struct mount *mp;
+    uint32_t undef_op;
+    uint32_t max_write;
+    int sess_init;
+    int unique;
+    int fd;
+};
+
+#define    UNDEF_ACCESS    1<<0
+#define    UNDEF_MKDIR    1<<1
+#define    UNDEF_CREATE    1<<2
+#define    UNDEF_LINK    1<<3
+#define UNDEF_READLINK    1<<4
+#define UNDEF_RMDIR    1<<5
+#define UNDEF_REMOVE    1<<6
+
+typedef void (*fuse_cb)(struct fuse_msg *msg,struct fuse_out_header
*hdr, void *buf);
+
+struct rcv_buf {
+    void *data_rcv;
+    size_t len;
+};
+
+enum msg_type {
+    msg_intr,
+    msg_buff,
+    msg_buff_async,
+};
+
+struct fuse_msg {
+    struct fuse_in_header *hdr;
+    struct fuse_mnt *fmp;
+    void *data;
+    int len;
+    int error;
+
+    enum msg_type type;
+    union {
+        struct rcv_buf buff;
+        uint32_t it_res;
+    } rep;
+
+    fuse_cb cb;
+    TAILQ_ENTRY(fuse_msg) node;
+};
+
+extern struct vops fusefs_vops;
+
+/*
+ * In and Out fifo for fuse communication
+ */
+TAILQ_HEAD(fuse_msg_head, fuse_msg);
+
+extern struct fuse_msg_head fmq_in;
+extern struct fuse_msg_head fmq_wait;
+
+/*
+ * fuse helpers
+ */
+void fuse_make_in(struct mount *, struct fuse_in_header *, int,
+          enum fuse_opcode, ino_t, struct proc *);
+void fuse_init_resp(struct fuse_msg *, struct fuse_out_header *, void *);
+void fuse_sync_resp(struct fuse_msg *, struct fuse_out_header *, void *);
+void fuse_sync_it(struct fuse_msg *msg, struct fuse_out_header *hdr,
void *data);
+
+/*
+ * files helpers.
+ */
+
+int fuse_file_open(struct fuse_mnt *, struct fuse_node *, enum
fufh_type, int, int);
+int fuse_file_close(struct fuse_mnt *, struct fuse_node *, enum
fufh_type, int, int);
+
+void fuse_internal_attr_fat2vat(struct mount *, struct fuse_attr *,
struct vattr *);
+
+/*
+ * The root inode is the root of the file system.  Inode 0 can't be used for
+ * normal purposes and bad blocks are normally linked to inode 1, thus
+ * the root inode is 2.
+ */
+#define    FUSE_ROOTINO ((ino_t)1)
+#define VFSTOFUSEFS(mp)    ((struct fuse_mnt *)((mp)->mnt_data))
+
+#define MAX_FUSE_DEV 4
+/*
+#define FUSE_DEBUG_VNOP 42
+#define FUSE_DEBUG_VFS 42
+#define FUSE_DEBUG 42
+#define FUSE_DEV_DEBUG 42
+#define FUSE_DEBUG_MSG 42
+*/
+/*
+ * Helpers
+ */
+
+#endif /* __FUSEFS_H__ */
Index: sys/conf.h
===================================================================
RCS file: /cvs/src/sys/sys/conf.h,v
retrieving revision 1.119
diff -u -p -u -p -r1.119 conf.h
--- sys/conf.h    23 Aug 2012 06:12:49 -0000    1.119
+++ sys/conf.h    5 Mar 2013 15:16:09 -0000
@@ -509,6 +509,13 @@ extern struct cdevsw cdevsw[];
     (dev_type_stop((*))) enodev, 0, selfalse, \
     (dev_type_mmap((*))) enodev }

+/* open, close, read, write, poll, ioctl */
+#define cdev_fuse_init(c,n) { \
+    dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+    dev_init(c,n,write), dev_init(c,n,ioctl), \
+    (dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
+    (dev_type_mmap((*))) enodev }
+
 #endif

 /*
@@ -657,6 +664,7 @@ cdev_decl(urio);
 cdev_decl(hotplug);
 cdev_decl(gpio);
 cdev_decl(amdmsr);
+cdev_decl(fuse);

 #endif

Index: sys/malloc.h
===================================================================
RCS file: /cvs/src/sys/sys/malloc.h,v
retrieving revision 1.101
diff -u -p -u -p -r1.101 malloc.h
--- sys/malloc.h    7 Feb 2013 11:06:42 -0000    1.101
+++ sys/malloc.h    5 Mar 2013 15:16:09 -0000
@@ -118,7 +118,8 @@
 #define    M_TTYS        62    /* allocated tty structures */
 #define    M_EXEC        63    /* argument lists & other mem used by exec */
 #define    M_MISCFSMNT    64    /* miscfs mount structures */
-/* 65-73 - free */
+#define M_FUSEFS    65    /* fusefs mount structures */
+/* 66-73 - free */
 #define    M_PFKEY        74    /* pfkey data */
 #define    M_TDB        75    /* Transforms database */
 #define    M_XDATA        76    /* IPsec data */
@@ -247,7 +248,7 @@
     "ttys",        /* 62 M_TTYS */ \
     "exec",        /* 63 M_EXEC */ \
     "miscfs mount",    /* 64 M_MISCFSMNT */ \
-    NULL, \
+    "fusefs mount", /* 65 M_FUSEFS */ \
     NULL, \
     NULL, \
     NULL, \
Index: sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.108
diff -u -p -u -p -r1.108 mount.h
--- sys/mount.h    5 Sep 2012 17:01:06 -0000    1.108
+++ sys/mount.h    5 Mar 2013 15:16:09 -0000
@@ -258,6 +258,15 @@ struct procfs_args {
 #define PROCFS_ARGSVERSION      1
 #define PROCFSMNT_LINUXCOMPAT   0x01

+/*
+ * Arguments to mount fusefs filesystems
+ */
+struct fusefs_args {
+    char *name;
+    char *url;
+    int fd;
+    int flags;
+};

 /*
  * file system statistics
@@ -325,6 +334,7 @@ struct statfs {
 #define    MOUNT_NCPFS    "ncpfs"        /* NetWare Network File System */
 #define    MOUNT_NTFS    "ntfs"        /* NTFS */
 #define    MOUNT_UDF    "udf"        /* UDF */
+#define MOUNT_FUSEFS    "fuse"        /* FUSE */

 /*
  * Structure per mounted file system.  Each mounted file system has an
Index: sys/vnode.h
===================================================================
RCS file: /cvs/src/sys/sys/vnode.h,v
retrieving revision 1.113
diff -u -p -u -p -r1.113 vnode.h
--- sys/vnode.h    8 Oct 2012 15:43:08 -0000    1.113
+++ sys/vnode.h    5 Mar 2013 15:16:09 -0000
@@ -71,13 +71,13 @@ enum vtype    { VNON, VREG, VDIR, VBLK, VCH
 enum vtagtype    {
     VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_MSDOSFS,
     VT_PORTAL, VT_PROCFS, VT_AFS, VT_ISOFS, VT_ADOSFS,
-    VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF,
+    VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF, VT_FUSEFS
 };

 #define    VTAG_NAMES \
     "NON", "UFS", "NFS", "MFS", "MSDOSFS",            \
     "PORTAL", "PROCFS", "AFS", "ISOFS", "ADOSFS",        \
-    "EXT2FS", "VFS", "NTFS", "UDF"
+    "EXT2FS", "VFS", "NTFS", "UDF", "FUSEFS"

 /*
  * Each underlying filesystem allocates its own private area and hangs

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
On Tue, Mar 5, 2013 at 4:29 PM, Sylvestre Gallon <[hidden email]> wrote:
>
> Martin,
>
> You will find inline the kernel patch
>

And here the userland :

Index: Makefile
===================================================================
RCS file: /cvs/src/sbin/Makefile,v
retrieving revision 1.97
diff -u -p -u -p -r1.97 Makefile
--- Makefile    23 Aug 2012 06:37:27 -0000    1.97
+++ Makefile    5 Mar 2013 15:21:12 -0000
@@ -5,7 +5,7 @@ SUBDIR=    atactl badsect bioctl clri dhcli
     fsck_msdos fsdb fsirand growfs ifconfig iked init iopctl ipsecctl  \
     isakmpd kbd ldattach lmccontrol mknod modload modunload mount \
     mount_cd9660 mount_ext2fs mount_ffs mount_msdos \
-    mount_nfs mount_ntfs mount_procfs mount_udf \
+    mount_nfs mount_ntfs mount_procfs mount_fusefs mount_udf \
     mount_vnd mountd ncheck_ffs newfs newfs_ext2fs newfs_msdos \
     nfsd nologin pdisk pfctl pflogd ping ping6 quotacheck \
     reboot restore route rtsol savecore scan_ffs \
Index: mount_fusefs/Makefile
===================================================================
RCS file: mount_fusefs/Makefile
diff -N mount_fusefs/Makefile
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ mount_fusefs/Makefile    5 Mar 2013 15:21:18 -0000
@@ -0,0 +1,10 @@
+#    $OpenBSD: src/sbin/mount_procfs/Makefile,v 1.7 2004/06/22
21:12:00 otto Exp $
+
+PROG=    mount_fusefs
+SRCS=    mount_fusefs.c getmntopts.c
+
+MOUNT=    ${.CURDIR}/../mount
+CFLAGS+= -I${MOUNT}
+.PATH:    ${MOUNT}
+
+.include <bsd.prog.mk>
Index: mount_fusefs/mount_fusefs.c
===================================================================
RCS file: mount_fusefs/mount_fusefs.c
diff -N mount_fusefs/mount_fusefs.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ mount_fusefs/mount_fusefs.c    5 Mar 2013 15:21:18 -0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mntopts.h"
+
+const struct mntopt mopts[] = {
+    MOPT_STDOPTS,
+    { "subtype",    0, MFLAG_SET | MFLAG_STRVAL | MFLAG_OPT },
+    { "fsname",    0, MFLAG_SET | MFLAG_STRVAL | MFLAG_OPT },
+    { NULL }
+};
+
+void    usage(void);
+
+int
+main(int argc, char *argv[])
+{
+    int ch, mntflags, altflags;
+    struct fusefs_args args;
+    char path[MAXPATHLEN];
+
+    mntflags = altflags = 0;
+    while ((ch = getopt(argc, argv, "o:")) != -1)
+        switch (ch) {
+        case 'o':
+            altflags |= getmntopts(optarg, mopts, &mntflags);
+            break;
+        case '?':
+        default:
+            usage();
+        }
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 2)
+        usage();
+
+    args.flags = altflags;
+    args.fd = atoi(argv[0]);
+
+    if (realpath(argv[1], path) == NULL)
+        err(1, "realpath %s", argv[1]);
+
+    if (mount(MOUNT_FUSEFS, path, mntflags, &args)) {
+        if (errno == EOPNOTSUPP)
+            errx(1, "%s: Filesystem not supported by kernel",
+                argv[1]);
+        else
+            err(1, "%s", argv[1]);
+    }
+    exit(0);
+}
+
+void
+usage(void)
+{
+    (void)fprintf(stderr,
+        "usage: mount_procfs [-o options] fd mount_point\n");
+    exit(1);
+}

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
In reply to this post by Sylvestre Gallon
Hi,

Martin suggested some ideas about my patches so I am sending you a new
inlined patch. This patch contains the following changes :

- code style changes
- I've fixed mount_fusefs usage() function
- By now I use DPRINTF for my debug messages
- I've got rid of curproc in vnops and vfsops.

Martin also told me that I could ask advises from vfs hackers about how
I can make a smarter patch. So here are my questions:

Do you know if miscfs is the best place to put my code ?
Do I keep the device code (fuse_device.c) in the same directory than the
filesystem code?
Do you know which fs type I can use in kern/vfs_init.c for fuse ? I've
taken 42 but I have no idea what I was doing when I choose this number :)

The things I will try to do during the next days are :

   * Using a standard cfdriver/cfattach structure in fuse_device.c
   * Writing a little documentation on the architecture of my fuse
implementation and on how the interaction between the vfs and the fuse
device works.
   * Taking a look at bufq_* to replace my TAILQ_* fifos.
   * Trying to use ufs_ihash* funcs instead of mine.11
   * Fixing bugs

It could also be interesting for the people looking at my code to know
that I've looked on the FreeBSD fuse implementation instead of NetBSD.
And I've tried to be closer to that implementation than to Puffs. I was
thinking that copying the real fuse would be easier that copying the copy...

Here is the new src patch :

Index: sbin/Makefile
===================================================================
RCS file: /cvs/src/sbin/Makefile,v
retrieving revision 1.97
diff -u -p -r1.97 Makefile
--- sbin/Makefile    23 Aug 2012 06:37:27 -0000    1.97
+++ sbin/Makefile    6 Mar 2013 20:04:20 -0000
@@ -5,7 +5,7 @@ SUBDIR=    atactl badsect bioctl clri dhcli
      fsck_msdos fsdb fsirand growfs ifconfig iked init iopctl ipsecctl  \
      isakmpd kbd ldattach lmccontrol mknod modload modunload mount \
      mount_cd9660 mount_ext2fs mount_ffs mount_msdos \
-    mount_nfs mount_ntfs mount_procfs mount_udf \
+    mount_nfs mount_ntfs mount_procfs mount_fusefs mount_udf \
      mount_vnd mountd ncheck_ffs newfs newfs_ext2fs newfs_msdos \
      nfsd nologin pdisk pfctl pflogd ping ping6 quotacheck \
      reboot restore route rtsol savecore scan_ffs \
Index: sbin/mount_fusefs/Makefile
===================================================================
RCS file: sbin/mount_fusefs/Makefile
diff -N sbin/mount_fusefs/Makefile
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sbin/mount_fusefs/Makefile    6 Mar 2013 20:04:21 -0000
@@ -0,0 +1,10 @@
+#    $OpenBSD: src/sbin/mount_procfs/Makefile,v 1.7 2004/06/22 21:12:00
otto Exp $
+
+PROG=    mount_fusefs
+SRCS=    mount_fusefs.c getmntopts.c
+
+MOUNT=    ${.CURDIR}/../mount
+CFLAGS+= -I${MOUNT}
+.PATH:    ${MOUNT}
+
+.include <bsd.prog.mk>
Index: sbin/mount_fusefs/mount_fusefs.c
===================================================================
RCS file: sbin/mount_fusefs/mount_fusefs.c
diff -N sbin/mount_fusefs/mount_fusefs.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sbin/mount_fusefs/mount_fusefs.c    6 Mar 2013 20:04:21 -0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mntopts.h"
+
+const struct mntopt mopts[] = {
+    MOPT_STDOPTS,
+    { "subtype",    0, MFLAG_SET | MFLAG_STRVAL | MFLAG_OPT },
+    { "fsname",    0, MFLAG_SET | MFLAG_STRVAL | MFLAG_OPT },
+    { NULL }
+};
+
+void    usage(void);
+
+int
+main(int argc, char *argv[])
+{
+    int ch, mntflags, altflags;
+    struct fusefs_args args;
+    char path[MAXPATHLEN];
+
+    mntflags = altflags = 0;
+    while ((ch = getopt(argc, argv, "o:")) != -1)
+        switch (ch) {
+        case 'o':
+            altflags |= getmntopts(optarg, mopts, &mntflags);
+            break;
+        case '?':
+        default:
+            usage();
+        }
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 2)
+        usage();
+
+    args.flags = altflags;
+    args.fd = atoi(argv[0]);
+
+    if (realpath(argv[1], path) == NULL)
+        err(1, "realpath %s", argv[1]);
+
+    if (mount(MOUNT_FUSEFS, path, mntflags, &args)) {
+        if (errno == EOPNOTSUPP)
+            errx(1, "%s: Filesystem not supported by kernel",
+                argv[1]);
+        else
+            err(1, "%s", argv[1]);
+    }
+    exit(0);
+}
+
+__dead void
+usage(void)
+{
+    (void)fprintf(stderr,
+        "usage: mount_fusefs [-o options] fd mount_point\n");
+    exit(1);
+}
Index: sys/arch/i386/i386/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/conf.c,v
retrieving revision 1.141
diff -u -p -r1.141 conf.c
--- sys/arch/i386/i386/conf.c    23 Aug 2012 06:12:49 -0000    1.141
+++ sys/arch/i386/i386/conf.c    6 Mar 2013 20:04:23 -0000
@@ -185,6 +185,7 @@ cdev_decl(pci);
  #include "amdmsr.h"
  #include "vscsi.h"
  #include "pppx.h"
+#include "fuse.h"

  struct cdevsw    cdevsw[] =
  {
@@ -293,6 +294,7 @@ struct cdevsw    cdevsw[] =
      cdev_vscsi_init(NVSCSI,vscsi),    /* 90: vscsi */
      cdev_disk_init(1,diskmap),    /* 91: disk mapper */
      cdev_pppx_init(NPPPX,pppx),     /* 92: pppx */
+    cdev_fuse_init(NFUSE, fuse),    /* 93: fuse */
  };
  int    nchrdev = nitems(cdevsw);

Index: sys/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/conf/GENERIC,v
retrieving revision 1.194
diff -u -p -r1.194 GENERIC
--- sys/conf/GENERIC    1 Mar 2013 21:06:04 -0000    1.194
+++ sys/conf/GENERIC    6 Mar 2013 20:04:25 -0000
@@ -45,6 +45,7 @@ option        NFSSERVER    # Network File System
  option        CD9660        # ISO 9660 + Rock Ridge file system
  option        UDF        # UDF (DVD) file system
  option        MSDOSFS        # MS-DOS file system
+option        FUSE        # Userland file system
  option        FIFO        # FIFOs; RECOMMENDED

  option        SOCKET_SPLICE    # Socket Splicing for TCP
@@ -73,6 +74,8 @@ scsibus*    at softraid?

  vscsi0        at root        # Userland backed Virtual SCSI
  scsibus*    at vscsi?
+
+pseudo-device    fuse        # filesystem in user land

  pseudo-device    pf        # packet filter
  pseudo-device    pflog        # pf log if
Index: sys/conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.540
diff -u -p -r1.540 files
--- sys/conf/files    21 Jan 2013 11:17:48 -0000    1.540
+++ sys/conf/files    6 Mar 2013 20:04:25 -0000
@@ -544,6 +544,15 @@ pseudo-device systrace
  pseudo-device ksyms
  file    dev/ksyms.c            ksyms needs-flag

+pseudo-device fuse
+file    miscfs/fuse/fuse_device.c    fuse    needs-flag
+file    miscfs/fuse/fuse_file.c        fuse
+file    miscfs/fuse/fuse_lookup.c    fuse
+file    miscfs/fuse/fuse_node.c        fuse
+file    miscfs/fuse/fuse_vfsops.c    fuse
+file    miscfs/fuse/fuse_vnops.c    fuse
+file    miscfs/fuse/fuse_subr.c        fuse
+
  pseudo-device pf: ifnet
  file    net/pf.c            pf    needs-flag
  file    net/pf_norm.c            pf
Index: sys/kern/vfs_init.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_init.c,v
retrieving revision 1.30
diff -u -p -r1.30 vfs_init.c
--- sys/kern/vfs_init.c    23 Aug 2012 06:12:49 -0000    1.30
+++ sys/kern/vfs_init.c    6 Mar 2013 20:04:26 -0000
@@ -85,6 +85,10 @@ extern  const struct vfsops ntfs_vfsops;
  extern  const struct vfsops udf_vfsops;
  #endif

+#ifdef FUSE
+extern const struct vfsops fusefs_vfsops;
+#endif
+
  /* Set up the filesystem operations for vnodes. */
  static struct vfsconf vfsconflist[] = {
  #ifdef FFS
@@ -121,6 +125,10 @@ static struct vfsconf vfsconflist[] = {

  #ifdef UDF
      { &udf_vfsops, MOUNT_UDF, 13, 0, MNT_LOCAL, NULL },
+#endif
+
+#ifdef FUSE
+    { &fusefs_vfsops, MOUNT_FUSEFS, 42, 0, MNT_LOCAL, NULL }, /* put 42
as type, I don't know witch number I can use*/
  #endif
  };

Index: sys/miscfs/fuse/fuse_device.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_device.c
diff -N sys/miscfs/fuse/fuse_device.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_device.c    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/poll.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/fcntl.h>
+#include <sys/vnode.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef    FUSE_DEV_DEBUG
+#define    DPRINTF(fmt, arg...)    printf("fuse device: " fmt, ##arg)
+#else
+#define    DPRINTF(fmt, arg...)
+#endif
+
+struct fuse_dev {
+    int opened;
+    int end;
+};
+
+#define FUSE_OPEN 1
+#define FUSE_CLOSE 0
+#define FUSE_DONE 2
+
+static struct fuse_dev *fuse_devs[MAX_FUSE_DEV];
+
+void    fuseattach(int);
+int    fuseopen(dev_t, int, int, struct proc *);
+int    fuseclose(dev_t, int, int, struct proc *);
+int    fuseioctl(dev_t, u_long, caddr_t, int, struct proc *);
+int    fuseread(dev_t, struct uio *, int);
+int    fusewrite(dev_t, struct uio *, int);
+int    fusepoll(dev_t, int, struct proc *);
+
+struct fuse_msg_head fmq_in;
+struct fuse_msg_head fmq_wait;
+
+#ifdef    FUSE_DEV_DEBUG
+static void
+dump_buff(char *buff, int len)
+{
+    char text[17];
+    int i;
+
+    bzero(text, 17);
+    for (i = 0; i < len ; i++) {
+
+        if (i != 0 && (i % 16) == 0) {
+            printf(": %s\n", text);
+            bzero(text, 17);
+        }
+
+        printf("%.2x ", buff[i] & 0xff);
+
+        if (buff[i] > ' ' && buff[i] < '~')
+            text[i%16] = buff[i] & 0xff;
+        else
+            text[i%16] = '.';
+    }
+
+    if ((i % 16) != 0) {
+        while ((i % 16) != 0) {
+            printf("   ");
+            i++;
+        }
+    }
+    printf(": %s\n", text);
+}
+#else
+#define dump_buff(x, y)
+#endif
+
+void
+fuseattach(int num)
+{
+    DPRINTF("fuse attach\n");
+}
+
+int
+fuseopen(dev_t dev, int flags, int fmt, struct proc * p)
+{
+    if (minor(dev) >= MAX_FUSE_DEV &&
+        fuse_devs[minor(dev)]->opened != FUSE_CLOSE)
+        return (ENXIO);
+
+    DPRINTF("open dev %i\n", minor(dev));
+
+    fuse_devs[minor(dev)] = malloc(sizeof(*fuse_devs[minor(dev)]),
+        M_FUSEFS, M_WAITOK | M_ZERO);
+    fuse_devs[minor(dev)]->opened = FUSE_OPEN;
+
+    return (0);
+}
+
+int
+fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
+{
+    if (minor(dev) >= MAX_FUSE_DEV)
+        return (ENXIO);
+
+    DPRINTF("close dev %i\n", minor(dev));
+
+    fuse_devs[minor(dev)]->opened = FUSE_CLOSE;
+    free(fuse_devs[minor(dev)], M_FUSEFS);
+    fuse_devs[minor(dev)] = NULL;
+    return (0);
+}
+
+int
+fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
+{
+    int error = 0;
+
+    switch (cmd) {
+    default:
+        DPRINTF("bad ioctl number %d\n", cmd);
+        return (ENODEV);
+    }
+
+    return (error);
+}
+
+int
+fuseread(dev_t dev, struct uio *uio, int ioflag)
+{
+    int error = 0;
+    struct fuse_msg *msg;
+
+    DPRINTF("read 0x%x\n", dev);
+
+
+    if (fuse_devs[minor(dev)]->opened != FUSE_OPEN) {
+        return (ENODEV);
+    }
+
+again:
+    if (TAILQ_EMPTY(&fmq_in)) {
+
+        if (ioflag & O_NONBLOCK) {
+            return (EAGAIN);
+        }
+
+        error = tsleep(&fmq_in, PWAIT, "fuse read", 0);
+
+        if (error)
+            return (error);
+    }
+    if (TAILQ_EMPTY(&fmq_in))
+        goto again;
+
+    if (!TAILQ_EMPTY(&fmq_in)) {
+        msg = TAILQ_FIRST(&fmq_in);
+
+        if (msg->hdr->opcode == FUSE_DESTROY) {
+            DPRINTF("catch done\n");
+            fuse_devs[minor(dev)]->opened = FUSE_DONE;
+        }
+
+        error = uiomove(msg->hdr, sizeof(struct fuse_in_header), uio);
+
+        DPRINTF("hdr r:\n");
+        dump_buff((char *)msg->hdr, sizeof(struct fuse_in_header));
+
+        if (msg->len > 0) {
+            error = uiomove(msg->data, msg->len, uio);
+            DPRINTF("data r:\n");
+            dump_buff(msg->data, msg->len);
+        }
+
+        DPRINTF("msg send : %i\n", msg->len);
+
+        if (error) {
+            DPRINTF("error: %i\n", error);
+            return (error);
+        }
+
+        /*
+          * msg moves from a tailq to another
+          */
+        TAILQ_REMOVE(&fmq_in, msg, node);
+        TAILQ_INSERT_TAIL(&fmq_wait, msg, node);
+    }
+
+    return (error);
+}
+
+int
+fusewrite(dev_t dev, struct uio *uio, int ioflag)
+{
+    struct fuse_out_header hdr;
+    struct fuse_msg *msg;
+    int error = 0;
+    int caught = 0;
+    int len;
+    void *data;
+
+    DPRINTF("write %x bytes\n", uio->uio_resid);
+
+    if (uio->uio_resid < sizeof(struct fuse_out_header)) {
+        DPRINTF("uio goes wrong\n");
+        return (EINVAL);
+    }
+
+    /*
+     * get out header
+     */
+
+    if ((error = uiomove(&hdr, sizeof(struct fuse_out_header), uio)) !=
0) {
+        DPRINTF("uiomove failed\n");
+        return (error);
+    }
+    DPRINTF("hdr w:\n");
+    dump_buff((char *)&hdr, sizeof(struct fuse_out_header));
+
+    /*
+     * check header validity
+     */
+    if (uio->uio_resid + sizeof(struct fuse_out_header) != hdr.len ||
+        (uio->uio_resid && hdr.error) || TAILQ_EMPTY(&fmq_wait) ) {
+        DPRINTF("corrupted fuse header or queue empty\n");
+        return (EINVAL);
+    }
+
+    /* fuse errno are negative */
+    if (hdr.error)
+        hdr.error = -(hdr.error);
+
+    TAILQ_FOREACH(msg, &fmq_wait, node) {
+        if (msg->hdr->unique == hdr.unique) {
+            DPRINTF("catch unique %i\n", msg->hdr->unique);
+            caught = 1;
+            break;
+        }
+    }
+
+    if (caught) {
+        if (uio->uio_resid > 0) {
+            len = uio->uio_resid;
+            data = malloc(len, M_FUSEFS, M_WAITOK);
+            error = uiomove(data, len, uio);
+
+            DPRINTF("data w:\n");
+            dump_buff(data, len);
+        } else {
+            data = NULL;
+        }
+
+        DPRINTF("call callback\n");
+
+        if (!error)
+            msg->cb(msg, &hdr, data);
+
+        TAILQ_REMOVE(&fmq_wait, msg, node);
+
+        if (msg->type == msg_buff_async) {
+            free(msg->hdr, M_FUSEFS);
+            free(msg, M_FUSEFS);
+
+            if (data)
+                free(data, M_FUSEFS);
+        }
+
+    } else {
+        error = EINVAL;
+    }
+
+    return (error);
+}
+
+int
+fusepoll(dev_t dev, int events, struct proc *p)
+{
+    int revents = 0;
+
+    DPRINTF("fuse poll\n");
+
+    if (events & (POLLIN | POLLRDNORM)) {
+        if (!TAILQ_EMPTY(&fmq_in))
+            revents |= events & (POLLIN | POLLRDNORM);
+    }
+
+    if (events & (POLLOUT | POLLWRNORM))
+        revents |= events & (POLLOUT | POLLWRNORM);
+
+    return (revents);
+}
Index: sys/miscfs/fuse/fuse_file.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_file.c
diff -N sys/miscfs/fuse/fuse_file.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_file.c    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef    FUSE_DEV_DEBUG
+#define    DPRINTF(fmt, arg...)    printf("fuse vnop: " fmt, ##arg)
+#else
+#define    DPRINTF(fmt, arg...)
+#endif
+
+
+int
+fuse_file_open(struct fuse_mnt *fmp, struct fuse_node *ip,
+    enum fufh_type fufh_type, int flags, int isdir, struct proc *p)
+{
+    struct fuse_open_out *open_out;
+    struct fuse_open_in open_in;
+    struct fuse_in_header hdr;
+    struct fuse_msg msg;
+    int error;
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.data = &open_in;
+    msg.len = sizeof(open_in);
+    msg.cb = &fuse_sync_resp;
+    msg.fmp = fmp;
+    msg.type = msg_buff;
+
+    open_in.flags = flags;
+    open_in.mode = 0;
+    msg.rep.buff.data_rcv = NULL;
+    msg.rep.buff.len = sizeof(*open_out);
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len,
+        ((isdir) ? FUSE_OPENDIR : FUSE_OPEN), ip->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse open", 0);
+
+    if (error)
+        return (error);
+
+    open_out = (struct fuse_open_out *)msg.rep.buff.data_rcv;
+
+    ip->fufh[fufh_type].fh_id = open_out->fh;
+    ip->fufh[fufh_type].fh_type = fufh_type;
+
+    free(open_out, M_FUSEFS);
+
+    return (0);
+}
+
+int
+fuse_file_close(struct fuse_mnt *fmp, struct fuse_node * ip,
+    enum fufh_type  fufh_type, int flags, int isdir, struct proc *p)
+{
+    struct fuse_release_in rel;
+    struct fuse_in_header hdr;
+    struct fuse_msg msg;
+    int error;
+
+    bzero(&msg, sizeof(msg));
+    bzero(&rel, sizeof(rel));
+    msg.hdr = &hdr;
+    msg.data = &rel;
+    msg.len = sizeof(rel);
+    msg.cb = &fuse_sync_it;
+    msg.fmp = fmp;
+    msg.type = msg_intr;
+
+    rel.fh  = ip->fufh[fufh_type].fh_id;
+    rel.flags = flags;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len,
+        ((isdir) ? FUSE_RELEASEDIR : FUSE_RELEASE), ip->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse close", 0);
+
+    if (error)
+        return (error);
+
+    error = msg.rep.it_res;
+    if (error)
+        printf("fuse file error %d\n", error);
+
+    ip->fufh[fufh_type].fh_id = (uint64_t)-1;
+    ip->fufh[fufh_type].fh_type = FUFH_INVALID;
+
+    return (error);
+}
Index: sys/miscfs/fuse/fuse_kernel.h
===================================================================
RCS file: sys/miscfs/fuse/fuse_kernel.h
diff -N sys/miscfs/fuse/fuse_kernel.h
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_kernel.h    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,233 @@
+/*
+    Copyright (C) 2012-2013 Sylvestre Gallon <[hidden email]>
+    Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+    ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY
+    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+#ifndef __FUSE_KERNEL_H__
+#define __FUSE_KERNEL_H__
+
+#define FUSE_KERNEL_VERSION 7
+#define FUSE_KERNEL_MINOR_VERSION 8
+
+/** The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+struct fuse_kstatfs {
+    uint64_t blocks;
+    uint64_t bfree;
+    uint64_t bavail;
+    uint64_t files;
+    uint64_t ffree;
+    uint32_t bsize;
+    uint32_t namelen;
+    uint32_t frsize;
+    uint32_t padding;
+    uint32_t spare[6];
+};
+
+enum fuse_opcode {
+    FUSE_LOOKUP =        1,
+    FUSE_FORGET =        2,  /* no reply */
+    FUSE_GETATTR =        3,
+    FUSE_SETATTR =        4,
+    FUSE_READLINK =        5,
+    FUSE_SYMLINK =        6,
+    FUSE_MKNOD =        8,
+    FUSE_MKDIR =        9,
+    FUSE_UNLINK =        10,
+    FUSE_RMDIR =        11,
+    FUSE_RENAME =        12,
+    FUSE_LINK =        13,
+    FUSE_OPEN =        14,
+    FUSE_READ =        15,
+    FUSE_WRITE =        16,
+    FUSE_STATFS =        17,
+    FUSE_RELEASE =        18,
+    FUSE_FSYNC =        20,
+    FUSE_SETXATTR =        21,
+    FUSE_GETXATTR =        22,
+    FUSE_LISTXATTR =    23,
+    FUSE_REMOVEXATTR =    24,
+    FUSE_FLUSH =        25,
+    FUSE_INIT =        26,
+    FUSE_OPENDIR =        27,
+    FUSE_READDIR =        28,
+    FUSE_RELEASEDIR =    29,
+    FUSE_FSYNCDIR =        30,
+    FUSE_GETLK =        31,
+    FUSE_SETLK =        32,
+    FUSE_SETLKW =        33,
+    FUSE_ACCESS =        34,
+    FUSE_CREATE =        35,
+    FUSE_INTERRUPT =    36,
+    FUSE_BMAP =        37,
+    FUSE_DESTROY =        38,
+};
+
+struct fuse_in_header {
+    uint32_t len;
+    uint32_t opcode;
+    uint64_t unique;
+    uint64_t nodeid;
+    uint32_t uid;
+    uint32_t gid;
+    uint32_t pid;
+    uint32_t padding;
+};
+
+struct fuse_init_in {
+    uint32_t major;
+    uint32_t minor;
+    uint32_t max_readahead;
+    uint32_t flags;
+};
+
+struct fuse_out_header {
+    uint32_t len;
+    uint32_t error;
+    uint64_t unique;
+};
+
+struct fuse_init_out {
+    uint32_t major;
+    uint32_t minor;
+    uint32_t max_readahead;
+    uint32_t flags;
+    uint32_t unused;
+    uint32_t max_write;
+};
+
+struct fuse_statfs_out {
+    struct fuse_kstatfs st;
+};
+
+struct fuse_attr {
+    uint64_t ino;
+    uint64_t size;
+    uint64_t blocks;
+    uint64_t atime;
+    uint64_t mtime;
+    uint64_t ctime;
+    uint32_t atimensec;
+    uint32_t mtimensec;
+    uint32_t ctimensec;
+    uint32_t mode;
+    uint32_t nlink;
+    uint32_t uid;
+    uint32_t gid;
+    uint32_t rdev;
+};
+
+struct fuse_attr_in {
+    uint32_t getattr_flags;
+    uint32_t dummy;
+    uint32_t fh;
+};
+
+struct fuse_attr_out {
+    uint64_t attr_valid;
+    uint32_t attr_valid_nsec;
+    uint32_t dummy;
+    struct fuse_attr attr;
+};
+
+struct fuse_access_in {
+    uint32_t mask;
+    uint32_t padding;
+};
+
+struct fuse_open_in {
+    uint32_t flags;
+    uint32_t mode;
+};
+
+struct fuse_open_out {
+    uint64_t fh;
+    uint32_t open_flags;
+    uint32_t padding;
+};
+
+struct fuse_release_in {
+    uint64_t fh;
+    uint32_t flags;
+    uint32_t release_flags;
+    uint64_t lock_owner;
+};
+
+struct fuse_read_in {
+    uint64_t fh;
+    uint64_t offset;
+    uint32_t size;
+    uint32_t padding;
+};
+
+struct fuse_dirent {
+    uint64_t ino;
+    uint64_t off;
+    uint32_t namelen;
+    uint32_t type;
+    char name[0];
+};
+
+struct pseudo_dirent {
+    uint32_t d_namlen;
+};
+
+struct fuse_entry_out {
+    uint64_t nodeid;
+    uint64_t generation;
+
+    uint64_t entry_valid;    /* Cache timeout for the name */
+    uint64_t attr_valid;    /* Cache timeout for the attributes */
+    uint32_t entry_valid_nsec;
+    uint32_t attr_valid_nsec;
+    struct fuse_attr attr;
+};
+
+struct fuse_mkdir_in {
+    uint32_t mode;
+    uint32_t padding;
+};
+
+struct fuse_link_in {
+    uint64_t oldnodeid;
+};
+
+struct fuse_write_in {
+    uint64_t fh;
+    uint64_t offset;
+    uint32_t size;
+    uint32_t write_flags;
+};
+
+struct fuse_write_out {
+    uint32_t size;
+    uint32_t padding;
+};
+
+#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
+#define FUSE_DIRENT_ALIGN(x) (((x)+sizeof(uint64_t)-1) &
~(sizeof(uint64_t)-1))
+#define FUSE_DIRENT_SIZE(d) \
+    FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
+
+#endif /* __FUSEFS_H__ */
Index: sys/miscfs/fuse/fuse_lookup.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_lookup.c
diff -N sys/miscfs/fuse/fuse_lookup.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_lookup.c    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/dirent.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef    FUSE_DEBUG_VNOP
+#define    DPRINTF(fmt, arg...)    printf("fuse vnop: " fmt, ##arg)
+#else
+#define    DPRINTF(fmt, arg...)
+#endif
+
+extern int fusefs_lookup(void *);
+
+int
+fusefs_lookup(void *v)
+{
+    struct vop_lookup_args *ap = v;
+    struct vnode *vdp;    /* vnode for directory being searched */
+    struct fuse_node *dp;    /* inode for directory being searched */
+    struct fuse_mnt *fmp;    /* file system that directory is in */
+    int lockparent;        /* 1 => lockparent flag is set */
+    struct vnode *tdp;    /* returned by VOP_VGET */
+    struct fuse_in_header hdr;
+    struct fuse_msg msg;
+    struct vnode **vpp = ap->a_vpp;
+    struct componentname *cnp = ap->a_cnp;
+    struct proc *p = cnp->cn_proc;
+    struct ucred *cred = cnp->cn_cred;
+    struct fuse_entry_out *feo = NULL;
+    int flags;
+    int nameiop = cnp->cn_nameiop;
+    /*struct proc *p = cnp->cn_proc;*/
+    int error = 0;
+    uint64_t nid;
+
+    flags = cnp->cn_flags;
+    *vpp = NULL;
+    vdp = ap->a_dvp;
+    dp = VTOI(vdp);
+    fmp = dp->i_mnt;
+    lockparent = flags & LOCKPARENT;
+
+    DPRINTF("lookup path %s\n", cnp->cn_pnbuf);
+    DPRINTF("lookup file %s\n", cnp->cn_nameptr);
+
+    if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0)
+        return (error);
+
+    if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
+        (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+        return (EROFS);
+
+    if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
+        return (error);
+
+    if (flags & ISDOTDOT) {
+        /* got ".." */
+        nid = dp->parent;
+        if (nid == 0) {
+            return (ENOENT);
+        }
+    } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
+        /* got "." */
+        nid = dp->i_number;
+    } else {
+        /* got a real entry */
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = cnp->cn_namelen + 1;
+
+        msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+        memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+        ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+        msg.type = msg_buff;
+        msg.rep.buff.len = 0;
+        msg.rep.buff.data_rcv = NULL;
+        msg.cb = &fuse_sync_resp;
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_LOOKUP,
+            dp->i_number, p);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        error = tsleep(&msg, PWAIT, "fuse lookup", 0);
+
+        if (error)
+            return (error);
+
+        if (msg.error) {
+            if ((nameiop == CREATE || nameiop == RENAME) &&
+                (flags & ISLASTCN) ) {
+                if (vdp->v_mount->mnt_flag & MNT_RDONLY)
+                    return (EROFS);
+
+                cnp->cn_flags |= SAVENAME;
+
+                if (!lockparent) {
+                    VOP_UNLOCK(vdp, 0, p);
+                    cnp->cn_flags |= PDIRUNLOCK;
+                }
+
+                error = EJUSTRETURN;
+                goto out;
+            }
+
+            error = ENOENT;
+            goto out;
+        }
+
+        feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+        nid = feo->nodeid;
+    }
+
+    if (nameiop == DELETE && (flags & ISLASTCN)) {
+        /*
+         * Write access to directory required to delete files.
+         */
+        if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0)
+            return (error);
+
+        cnp->cn_flags |= SAVENAME;
+    }
+
+    if (flags & ISDOTDOT) {
+        DPRINTF("lookup for ..\n");
+        VOP_UNLOCK(vdp, 0, p);    /* race to get the inode */
+        cnp->cn_flags |= PDIRUNLOCK;
+
+        error = VFS_VGET(fmp->mp, nid, &tdp);
+
+        if (error) {
+            if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
+                cnp->cn_flags &= ~PDIRUNLOCK;
+
+            return (error);
+        }
+
+        if (lockparent && (flags & ISLASTCN)) {
+            if ((error = vn_lock(vdp, LK_EXCLUSIVE, p))) {
+                vput(tdp);
+                return (error);
+            }
+            cnp->cn_flags &= ~PDIRUNLOCK;
+        }
+        *vpp = tdp;
+
+    } else if (nid == dp->i_number) {
+        vref(vdp);
+        *vpp = vdp;
+        error = 0;
+    } else {
+        error = VFS_VGET(fmp->mp, nid, &tdp);
+
+        if (!error) {
+            tdp->v_type = IFTOVT(feo->attr.mode);
+            VTOI(tdp)->vtype = tdp->v_type;
+        }
+
+        fuse_internal_attr_fat2vat(fmp->mp, &feo->attr,
+            &(VTOI(tdp)->cached_attrs));
+        free(feo, M_FUSEFS);
+
+        if (error)
+            return (error);
+
+        if (vdp != NULL && vdp->v_type == VDIR) {
+            VTOI(tdp)->parent = dp->i_number;
+        }
+        if (!lockparent || !(flags & ISLASTCN)) {
+            VOP_UNLOCK(vdp, 0, p);
+            cnp->cn_flags |= PDIRUNLOCK;
+        }
+
+        *vpp = tdp;
+    }
+
+out:
+    if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE &&
+        nameiop != DELETE )
+        cache_enter(vdp, *vpp, cnp);
+
+    return (error);
+}
Index: sys/miscfs/fuse/fuse_node.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_node.c
diff -N sys/miscfs/fuse/fuse_node.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_node.c    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+LIST_HEAD(ihashhead, fuse_node) *fhashtbl;
+u_long    fhash;    /* size of hash table - 1 */
+#define    INOHASH(fd, inum)    (&fhashtbl[((fd) + (inum)) & fhash])
+
+void
+fusefs_ihashinit(void)
+{
+    fhashtbl = hashinit(desiredvnodes, M_FUSEFS, M_WAITOK, &fhash);
+}
+
+/*
+ * Use the fd/inum pair to find the incore inode, and return a pointer
+ * to it. If it is in core, but locked, wait for it.
+ */
+struct vnode *
+fusefs_ihashget(int fd, ino_t inum)
+{
+    struct proc *p = curproc;
+    struct fuse_node *ip;
+    struct vnode *vp;
+loop:
+    /* XXXLOCKING lock hash list */
+    LIST_FOREACH(ip, INOHASH(fd, inum), i_hash) {
+        if (inum == ip->i_number && fd == ip->i_fd) {
+            vp = ITOV(ip);
+            /* XXXLOCKING unlock hash list? */
+            if (vget(vp, LK_EXCLUSIVE, p))
+                goto loop;
+            return (vp);
+        }
+    }
+    /* XXXLOCKING unlock hash list? */
+    return (NULL);
+}
+
+int
+fusefs_ihashins(struct fuse_node *ip)
+{
+    struct fuse_node *curip;
+    struct ihashhead *ipp;
+    int fd = ip->i_fd;
+    ino_t inum = ip->i_number;
+
+    /* lock the inode, then put it on the appropriate hash list */
+    lockmgr(&ip->i_lock, LK_EXCLUSIVE, NULL);
+
+    /* XXXLOCKING lock hash list */
+
+    LIST_FOREACH(curip, INOHASH(fd, inum), i_hash) {
+        if (inum == curip->i_number && fd == curip->i_fd) {
+            /* XXXLOCKING unlock hash list? */
+            lockmgr(&ip->i_lock, LK_RELEASE, NULL);
+            return (EEXIST);
+        }
+    }
+
+    ipp = INOHASH(fd, inum);
+    LIST_INSERT_HEAD(ipp, ip, i_hash);
+    /* XXXLOCKING unlock hash list? */
+
+    return (0);
+}
+
+/*
+ * Remove the inode from the hash table.
+ */
+void
+fusefs_ihashrem(struct fuse_node *ip)
+{
+    /* XXXLOCKING lock hash list */
+
+    if (ip->i_hash.le_prev == NULL)
+        return;
+
+    LIST_REMOVE(ip, i_hash);
+#ifdef DIAGNOSTIC
+    ip->i_hash.le_next = NULL;
+    ip->i_hash.le_prev = NULL;
+#endif
+    /* XXXLOCKING unlock hash list? */
+}
Index: sys/miscfs/fuse/fuse_node.h
===================================================================
RCS file: sys/miscfs/fuse/fuse_node.h
diff -N sys/miscfs/fuse/fuse_node.h
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_node.h    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FUSE_NODE_H__
+#define __FUSE_NODE_H__
+
+enum fufh_type {
+    FUFH_INVALID = -1,
+    FUFH_RDONLY  = 0,
+    FUFH_WRONLY  = 1,
+    FUFH_RDWR    = 2,
+    FUFH_MAXTYPE = 3,
+};
+
+struct fuse_filehandle {
+    uint64_t fh_id;
+    enum fufh_type fh_type;
+};
+
+struct fuse_node {
+    LIST_ENTRY(fuse_node) i_hash;    /* Hash chain */
+    struct vnode *i_vnode;        /* vnode associated with this inode */
+    struct lockf *i_lockf;        /* Head of byte-level lock list. */
+    struct lock i_lock;        /* node lock */
+    ino_t i_number;            /* the identity of the inode */
+    int i_fd;            /* fd of fuse session */
+
+    struct fuse_mnt *i_mnt;        /* fs associated with this inode */
+    uint64_t parent;
+
+    /** I/O **/
+    struct     fuse_filehandle fufh[FUFH_MAXTYPE];
+
+    /** flags **/
+    uint32_t   flag;
+
+    /** meta **/
+    struct vattr      cached_attrs;
+    off_t             filesize;
+    uint64_t          nlookup;
+    enum vtype        vtype;
+};
+
+extern struct fuse_node **fusehashtbl;
+extern u_long fusehash;
+
+void fusefs_ihashinit(void);
+struct vnode *fusefs_ihashget(int, ino_t);
+int fusefs_ihashins(struct fuse_node *);
+void fusefs_ihashrem(struct fuse_node *);
+#define ITOV(ip) ((ip)->i_vnode)
+#define VTOI(vp) ((struct fuse_node *)(vp)->v_data)
+
+#endif /* __FUSE_NODE_H__ */
Index: sys/miscfs/fuse/fuse_subr.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_subr.c
diff -N sys/miscfs/fuse/fuse_subr.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_subr.c    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef    FUSE_DEBUG_MSG
+#define    DPRINTF(fmt, arg...)    printf("fuse ipc: " fmt, ##arg)
+#else
+#define    DPRINTF(fmt, arg...)
+#endif
+
+void
+fuse_make_in(struct mount *mp, struct fuse_in_header *hdr, int len,
+    enum fuse_opcode op, ino_t ino, struct proc *p)
+{
+    struct fuse_mnt *fmp;
+
+    fmp = VFSTOFUSEFS(mp);
+    fmp->unique++;
+
+    hdr->len = sizeof(*hdr) + len;
+    hdr->opcode = op;
+    hdr->nodeid = ino;
+    hdr->unique = fmp->unique;
+
+    DPRINTF("create unique %i\n", hdr->unique);
+
+    if (!p) {
+        hdr->pid = curproc->p_pid;
+        hdr->uid = 0;
+        hdr->gid = 0;
+    } else {
+        hdr->pid = p->p_pid;
+        hdr->uid = p->p_cred->p_ruid;
+        hdr->gid = p->p_cred->p_rgid;
+    }
+}
+
+void
+fuse_init_resp(struct fuse_msg *msg, struct fuse_out_header *hdr, void
*data)
+{
+    struct fuse_init_out *out = data;
+
+    DPRINTF("async init unique %i\n", msg->hdr->unique);
+    DPRINTF("init_out flags %i\n", out->flags);
+    DPRINTF("init_out major %i\n", out->major);
+    DPRINTF("init_out minor %i\n", out->minor);
+    DPRINTF("init_out max_readahead %i\n", out->max_readahead);
+    DPRINTF("init_out max_write %i\n", out->max_write);
+    DPRINTF("init_out unused %i\n", out->unused);
+
+    msg->fmp->sess_init = 1;
+    msg->fmp->max_write = out->max_readahead;
+}
+
+void
+fuse_sync_resp(struct fuse_msg *msg, struct fuse_out_header *hdr, void
*data)
+{
+    size_t len;
+
+    DPRINTF("unique %i\n", msg->hdr->unique);
+
+    if (msg->type != msg_buff)
+        DPRINTF("bad msg type\n");
+
+    if (data != NULL && msg->rep.buff.len != 0) {
+        len = hdr->len - sizeof(*hdr);
+        if (msg->rep.buff.len != len) {
+            DPRINTF("fusefs: packet size error on opcode %i\n",
+                msg->hdr->opcode);
+        }
+
+        if (msg->rep.buff.len > len)
+            printf("unused byte : 0x%x\n", msg->rep.buff.len - len);
+
+        msg->rep.buff.data_rcv = malloc(msg->rep.buff.len, M_FUSEFS,
+            M_WAITOK | M_ZERO);
+        memcpy(msg->rep.buff.data_rcv, data, msg->rep.buff.len);
+
+        wakeup(msg);
+
+    } else if (data != NULL) {
+        len = hdr->len - sizeof(*hdr);
+        msg->rep.buff.data_rcv = malloc(len,  M_FUSEFS,
+            M_WAITOK | M_ZERO);
+        memcpy(msg->rep.buff.data_rcv, data, len);
+        msg->rep.buff.len = len;
+
+        wakeup(msg);
+    } else if (hdr->error) {
+        msg->error = hdr->error;
+        DPRINTF("error %i\n", msg->error);
+        wakeup(msg);
+    } else {
+        msg->error = -1;
+        DPRINTF("ack for msg\n");
+        wakeup(msg);
+    }
+}
+
+void
+fuse_sync_it(struct fuse_msg *msg, struct fuse_out_header *hdr, void *data)
+{
+    DPRINTF("unique %i\n", msg->hdr->unique);
+
+    if (msg->type != msg_intr)
+        printf("bad msg type\n");
+
+    if (data != NULL)
+        printf("normally data should be Null\n");
+
+    msg->rep.it_res = hdr->error;
+    DPRINTF("errno = %d\n", msg->rep.it_res);
+    wakeup(msg);
+}
Index: sys/miscfs/fuse/fuse_vfsops.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_vfsops.c
diff -N sys/miscfs/fuse/fuse_vfsops.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_vfsops.c    6 Mar 2013 20:04:26 -0000
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/lock.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef    FUSE_DEBUG_VFS
+#define    DPRINTF(fmt, arg...)    printf("fuse vfsop: " fmt, ##arg)
+#else
+#define    DPRINTF(fmt, arg...)
+#endif
+
+int    fusefs_mount(struct mount *, const char *, void *, struct
nameidata *,
+        struct proc *);
+int    fusefs_start(struct mount *, int, struct proc *);
+int    fusefs_unmount(struct mount *, int, struct proc *);
+int    fusefs_root(struct mount *, struct vnode **);
+int    fusefs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *);
+int    fusefs_statfs(struct mount *, struct statfs *, struct proc *);
+int    fusefs_sync(struct mount *, int, struct ucred *, struct proc *);
+int    fusefs_vget(struct mount *, ino_t, struct vnode **);
+int    fusefs_fhtovp(struct mount *, struct fid *, struct vnode **);
+int    fusefs_vptofh(struct vnode *, struct fid *);
+int    fusefs_init(struct vfsconf *);
+int    fusefs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
+        struct proc *);
+int    fusefs_checkexp(struct mount *, struct mbuf *, int *,
+        struct ucred **);
+
+const struct vfsops fusefs_vfsops = {
+    fusefs_mount,
+    fusefs_start,
+    fusefs_unmount,
+    fusefs_root,
+    fusefs_quotactl,
+    fusefs_statfs,
+    fusefs_sync,
+    fusefs_vget,
+    fusefs_fhtovp,
+    fusefs_vptofh,
+    fusefs_init,
+    fusefs_sysctl,
+    fusefs_checkexp
+};
+
+int
+fusefs_mount(struct mount *mp, const char *path, void *data,
+    struct nameidata *ndp, struct proc *p)
+{
+    struct fuse_mnt *fmp;
+    struct fuse_msg *msg;
+    struct fuse_init_in *init;
+    struct fusefs_args args;
+    int error;
+
+    DPRINTF("mount\n");
+
+    if (mp->mnt_flag & MNT_UPDATE)
+        return (EOPNOTSUPP);
+
+    error = copyin(data, &args, sizeof(struct fusefs_args));
+    if (error)
+        return (error);
+
+    DPRINTF("fd = %d\n", args.fd);
+
+    fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO);
+    fmp->mp = mp;
+    fmp->sess_init = 0;
+    fmp->unique = 0;
+    fmp->fd = args.fd;
+    mp->mnt_data = (qaddr_t)fmp;
+
+    mp->mnt_flag |= MNT_LOCAL;
+    vfs_getnewfsid(mp);
+
+    bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
+    strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
+    bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
+    bcopy("fusefs", mp->mnt_stat.f_mntfromname, sizeof("fusefs"));
+
+    msg = malloc(sizeof(struct fuse_msg), M_FUSEFS, M_WAITOK | M_ZERO);
+    msg->hdr = malloc(sizeof(struct fuse_in_header), M_FUSEFS,
+        M_WAITOK | M_ZERO);
+    init = malloc(sizeof(struct fuse_init_in), M_FUSEFS, M_WAITOK |
M_ZERO);
+
+    init->major = FUSE_KERNEL_VERSION;
+    init->minor = FUSE_KERNEL_MINOR_VERSION;
+    init->max_readahead = 4096 * 16;
+    init->flags = 0;
+    msg->data = init;
+    msg->len = sizeof(*init);
+    msg->cb = &fuse_init_resp;
+    msg->fmp = fmp;
+    msg->type = msg_buff_async;
+
+    fuse_make_in(mp, msg->hdr, msg->len, FUSE_INIT, 0, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, msg, node);
+    wakeup(&fmq_in);
+
+    return (0);
+}
+
+int
+fusefs_start(struct mount *mp, int flags, struct proc *p)
+{
+    DPRINTF("start\n");
+    return (0);
+}
+
+int
+fusefs_unmount(struct mount *mp, int mntflags, struct proc *p)
+{
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    extern int doforce;
+    struct fuse_msg *m;
+    int flags = 0;
+    int error;
+
+    fmp = VFSTOFUSEFS(mp);
+
+    if (!fmp->sess_init)
+        return (0);
+
+    fmp->sess_init = 0;
+
+    DPRINTF("unmount\n");
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = 0;
+    msg.type = msg_intr;
+    msg.data = NULL;
+    msg.cb = &fuse_sync_it;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_DESTROY, 0, p);
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse unmount", 0);
+
+    if (error)
+        return (error);
+
+    error = msg.rep.it_res;
+
+    if (error)
+        DPRINTF("error from fuse\n");
+
+    /* clear FIFO IN*/
+    while ((m = TAILQ_FIRST(&fmq_in))) {
+        DPRINTF("warning some msg where not processed....\n");
+    }
+
+    /* clear FIFO WAIT*/
+    while ((m = TAILQ_FIRST(&fmq_wait))) {
+        DPRINTF("warning some msg where not processed....\n");
+    }
+
+    if (mntflags & MNT_FORCE) {
+        /* fusefs can never be rootfs so don't check for it */
+        if (!doforce)
+            return (EINVAL);
+        flags |= FORCECLOSE;
+    }
+
+    if ((error = vflush(mp, 0, flags)))
+        return (error);
+
+    free(fmp, M_FUSEFS);
+
+    return (error);
+}
+
+int
+fusefs_root(struct mount *mp, struct vnode **vpp)
+{
+    struct vnode *nvp;
+    struct fuse_node *ip;
+    int error;
+
+    DPRINTF("root\n");
+
+    if ((error = VFS_VGET(mp, (ino_t)FUSE_ROOTINO, &nvp)) != 0)
+        return (error);
+
+    ip = VTOI(nvp);
+    nvp->v_type = VDIR;
+    ip->vtype = VDIR;
+
+    *vpp = nvp;
+    return (0);
+}
+
+int fusefs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
+    struct proc *p)
+{
+    DPRINTF("quotactl\n");
+    return (0);
+}
+
+int fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
+{
+    struct fuse_statfs_out *stat;
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error;
+
+    DPRINTF("statfs\n");
+
+    fmp = VFSTOFUSEFS(mp);
+
+    if (fmp->sess_init) {
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = 0;
+        msg.data = NULL;
+        msg.rep.buff.data_rcv = NULL;
+        msg.rep.buff.len = sizeof(*stat);
+        msg.cb = &fuse_sync_resp;
+        msg.type = msg_buff;
+
+        fuse_make_in(mp, msg.hdr, msg.len, FUSE_STATFS, FUSE_ROOT_ID,
+            NULL);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        error = tsleep(&msg, PWAIT, "fuse stat", 0);
+        if (error) {
+            if (msg.rep.buff.data_rcv)
+                free(msg.rep.buff.data_rcv, M_FUSEFS);
+            return (error);
+        }
+
+        stat = (struct fuse_statfs_out *)msg.rep.buff.data_rcv;
+
+        DPRINTF("statfs a: %i\n", stat->st.bavail);
+        DPRINTF("statfs a: %i\n", stat->st.bfree);
+        DPRINTF("statfs a: %i\n", stat->st.blocks);
+        DPRINTF("statfs a: %i\n", stat->st.bsize);
+        DPRINTF("statfs a: %i\n", stat->st.ffree);
+        DPRINTF("statfs a: %i\n", stat->st.files);
+        DPRINTF("statfs a: %i\n", stat->st.frsize);
+        DPRINTF("statfs a: %i\n", stat->st.namelen);
+        DPRINTF("statfs a: %i\n", stat->st.padding);
+
+        sbp->f_bavail = stat->st.bavail;
+        sbp->f_bfree = stat->st.bfree;
+        sbp->f_blocks = stat->st.blocks;
+        sbp->f_ffree = stat->st.ffree;
+        sbp->f_files = stat->st.files;
+        sbp->f_bsize = stat->st.frsize;
+        sbp->f_namemax = stat->st.namelen;
+
+        free(stat, M_FUSEFS);
+    } else {
+        sbp->f_bavail = 0;
+        sbp->f_bfree = 0;
+        sbp->f_blocks = 0;
+        sbp->f_ffree = 0;
+        sbp->f_files = 0;
+        sbp->f_bsize = 0;
+        sbp->f_namemax = 0;
+    }
+
+
+    return (0);
+}
+
+int fusefs_sync(struct mount *mp, int waitfor, struct ucred *cred,
+    struct proc *p)
+{
+    DPRINTF("sync\n");
+    return (0);
+}
+
+int fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
+{
+    struct fuse_mnt *fmp;
+    struct fuse_node *ip;
+    struct vnode *nvp;
+    int i;
+    int error;
+
+    DPRINTF("vget\n");
+
+retry:
+    fmp = VFSTOFUSEFS(mp);
+    /*
+     * check if vnode is in hash.
+     */
+    if ((*vpp = fusefs_ihashget(fmp->fd, ino)) != NULLVP)
+        return (0);
+
+    /*
+     * if not create it
+     */
+    if ((error = getnewvnode(VT_FUSEFS, mp, &fusefs_vops, &nvp)) != 0) {
+        DPRINTF("getnewvnode error\n");
+        *vpp = NULLVP;
+        return (error);
+    }
+
+    ip = malloc(sizeof(*ip), M_FUSEFS, M_WAITOK | M_ZERO);
+    lockinit(&ip->i_lock, PINOD, "fuseinode", 0, 0);
+    nvp->v_data = ip;
+    ip->i_vnode = nvp;
+    ip->i_fd = fmp->fd;
+    ip->i_number = ino;
+    ip->parent = 0;
+
+    for (i = 0; i < FUFH_MAXTYPE; i++)
+        ip->fufh[i].fh_type = FUFH_INVALID;
+
+    error = fusefs_ihashins(ip);
+    if (error) {
+        vrele(nvp);
+
+        if (error == EEXIST)
+            goto retry;
+
+        return (error);
+    }
+
+    ip->i_mnt = fmp;
+
+    if (ino == FUSE_ROOTINO)
+        nvp->v_flag |= VROOT;
+
+    *vpp = nvp;
+
+    return (0);
+}
+
+int fusefs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
+{
+    DPRINTF("fhtovp\n");
+    return (0);
+}
+
+int fusefs_vptofh(struct vnode *vp, struct fid *fhp)
+{
+    DPRINTF("vptofh\n");
+    return (0);
+}
+
+int fusefs_init(struct vfsconf *vfc)
+{
+    DPRINTF("init\n");
+
+    TAILQ_INIT(&fmq_in);
+    TAILQ_INIT(&fmq_wait);
+
+    fusefs_ihashinit();
+    return (0);
+}
+
+int fusefs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldplen,
+    void *newp, size_t newlen, struct proc *p)
+{
+    DPRINTF("sysctl\n");
+    return (0);
+}
+
+int fusefs_checkexp(struct mount *mp, struct mbuf *nam, int *extflagsp,
+    struct ucred **credanonp)
+{
+    DPRINTF("checkexp\n");
+    return (0);
+}
Index: sys/miscfs/fuse/fuse_vnops.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_vnops.c
diff -N sys/miscfs/fuse/fuse_vnops.c
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_vnops.c    6 Mar 2013 20:04:27 -0000
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/dirent.h>
+#include <sys/specdev.h>
+#include <sys/poll.h>
+#include <sys/lockf.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef    FUSE_DEBUG_VNOP
+#define    DPRINTF(fmt, arg...)    printf("fuse vnop: " fmt, ##arg)
+#else
+#define    DPRINTF(fmt, arg...)
+#endif
+
+
+/*
+ * Prototypes for fusefs vnode ops
+ */
+extern int fusefs_lookup(void *);
+int    fusefs_open(void *);
+int    fusefs_close(void *);
+int    fusefs_access(void *);
+int    fusefs_getattr(void *);
+int    fusefs_setattr(void *);
+int    fusefs_ioctl(void *);
+int    fusefs_link(void *);
+int    fusefs_symlink(void *);
+int    fusefs_readdir(void *);
+int    fusefs_readlink(void *);
+int    fusefs_inactive(void *);
+int    fusefs_reclaim(void *);
+int    fusefs_print(void *);
+int    fusefs_create(void *);
+int    fusefs_mknod(void *);
+int    fusefs_read(void *);
+int    fusefs_write(void *);
+int    fusefs_poll(void *);
+int    fusefs_fsync(void *);
+int    fusefs_remove(void *);
+int    fusefs_rename(void *);
+int    fusefs_mkdir(void *);
+int    fusefs_rmdir(void *);
+int    fusefs_strategy(void *);
+int    fusefs_lock(void *);
+int    fusefs_unlock(void *);
+int    fusefs_islocked(void *);
+int    fusefs_advlock(void *);
+int    readdir_process_data(void *buff, int len, struct uio *uio);
+
+struct vops fusefs_vops = {
+    .vop_lookup    = fusefs_lookup,
+    .vop_create    = fusefs_create,
+    .vop_mknod    = fusefs_mknod,
+    .vop_open    = fusefs_open,
+    .vop_close    = fusefs_close,
+    .vop_access    = fusefs_access,
+    .vop_getattr    = fusefs_getattr,
+    .vop_setattr    = fusefs_setattr,
+    .vop_read    = fusefs_read,
+    .vop_write    = fusefs_write,
+    .vop_ioctl    = fusefs_ioctl,
+    .vop_poll    = fusefs_poll,
+    .vop_fsync    = fusefs_fsync,
+    .vop_remove    = fusefs_remove,
+    .vop_link    = fusefs_link,
+    .vop_rename    = fusefs_rename,
+    .vop_mkdir    = fusefs_mkdir,
+    .vop_rmdir    = fusefs_rmdir,
+    .vop_symlink    = fusefs_symlink,
+    .vop_readdir    = fusefs_readdir,
+    .vop_readlink    = fusefs_readlink,
+    .vop_abortop    = vop_generic_abortop,
+    .vop_inactive    = fusefs_inactive,
+    .vop_reclaim    = fusefs_reclaim,
+    .vop_lock    = fusefs_lock,
+    .vop_unlock    = fusefs_unlock,
+    .vop_bmap    = vop_generic_bmap,
+    .vop_strategy    = fusefs_strategy,
+    .vop_print    = fusefs_print,
+    .vop_islocked    = fusefs_islocked,
+    .vop_pathconf    = spec_pathconf,
+    .vop_advlock    = fusefs_advlock,
+};
+
+
+void
+fuse_internal_attr_fat2vat(struct mount *mp,
+                           struct fuse_attr *fat,
+                           struct vattr *vap)
+{
+    vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
+    vap->va_fileid = fat->ino;/* XXX cast from 64 bits to 32 */
+    vap->va_mode = fat->mode & ~S_IFMT;
+    vap->va_nlink = fat->nlink;
+    vap->va_uid = fat->uid;
+    vap->va_gid = fat->gid;
+    vap->va_rdev = fat->rdev;
+    vap->va_size = fat->size;
+    vap->va_atime.tv_sec = fat->atime;
+    vap->va_atime.tv_nsec = fat->atimensec;
+    vap->va_mtime.tv_sec = fat->mtime;
+    vap->va_mtime.tv_nsec = fat->mtimensec;
+    vap->va_ctime.tv_sec = fat->ctime;
+    vap->va_ctime.tv_nsec = fat->ctimensec;
+    vap->va_blocksize = PAGE_SIZE;
+    vap->va_type = IFTOVT(fat->mode);
+
+#if (S_BLKSIZE == 512)
+    /* Optimize this case */
+    vap->va_bytes = fat->blocks << 9;
+#else
+    vap->va_bytes = fat->blocks * S_BLKSIZE;
+#endif
+
+}
+
+int
+fusefs_open(void *v)
+{
+    struct vop_open_args *ap;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    enum fufh_type fufh_type;
+    int flags;
+    int error;
+    int isdir;
+
+    DPRINTF("fusefs_open\n");
+
+    ap = v;
+    ip = VTOI(ap->a_vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        return (0);
+    }
+
+    DPRINTF("inode = %i mode=0x%x\n", ip->i_number, ap->a_mode);
+
+    isdir = 0;
+    if (ip->vtype == VDIR) {
+        fufh_type = FUFH_RDONLY;
+        flags = O_RDONLY;
+        isdir = 1;
+    } else {
+        if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) {
+            fufh_type = FUFH_RDWR;
+            flags = O_RDWR;
+        }
+        else if (ap->a_mode  & (FWRITE)) {
+            fufh_type = FUFH_WRONLY;
+            flags = O_WRONLY;
+        }
+        else if (ap->a_mode & (FREAD)) {
+            fufh_type = FUFH_RDONLY;
+            flags = O_RDONLY;
+        }
+    }
+
+    /* already open i think all is ok */
+    if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+        return (0);
+
+    error = fuse_file_open(fmp, ip, fufh_type, flags, isdir, ap->a_p);
+
+    if (error)
+        return (error);
+
+    DPRINTF("file open fd : %i\n", ip->fufh[fufh_type].fh_id);
+
+    return (error);
+}
+
+int
+fusefs_close(void *v)
+{
+    struct vop_close_args *ap;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    enum fufh_type fufh_type;
+    int isdir, flags, i;
+
+    DPRINTF("fusefs_close\n");
+
+    ap = v;
+    ip = VTOI(ap->a_vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        return (0);
+    }
+
+    isdir = 0;
+    if (ip->vtype == VDIR) {
+        fufh_type = FUFH_RDONLY;
+        isdir = 1;
+
+        if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+            return (fuse_file_close(fmp, ip, fufh_type, O_RDONLY,
+                isdir, ap->a_p));
+    } else {
+        if (ap->a_fflag & IO_NDELAY) {
+            return (0);
+        }
+
+        if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE)) {
+            fufh_type = FUFH_RDWR;
+            flags = O_RDWR;
+        }
+        else if (ap->a_fflag  & (FWRITE)) {
+            fufh_type = FUFH_WRONLY;
+            flags = O_WRONLY;
+        }
+        else if (ap->a_fflag & (FREAD)) {
+            fufh_type = FUFH_RDONLY;
+            flags = O_RDONLY;
+        }
+    }
+
+    /*
+     * if fh not valid lookup for another valid fh in vnode.
+     * panic if there's not fh valid
+     */
+    if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) {
+        for (i = 0; i < FUFH_MAXTYPE; i++)
+            if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+                break;
+        return (0);
+    }
+
+    return (0);
+}
+
+int
+fusefs_access(void *v)
+{
+    struct fuse_access_in access;
+    struct vop_access_args *ap;
+    struct fuse_in_header hdr;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    struct proc *p;
+    uint32_t mask = 0;
+    int error = 0;
+
+    DPRINTF("fusefs_access\n");
+
+    ap = v;
+    p = ap->a_p;
+    ip = VTOI(ap->a_vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_ACCESS))
+        goto system_check;
+
+    if (ap->a_vp->v_type == VLNK)
+        goto system_check;
+
+    if (ap->a_vp->v_type == VREG && (ap->a_mode & VWRITE & VEXEC))
+        goto system_check;
+
+    if ((ap->a_mode & VWRITE) && (fmp->mp->mnt_flag & MNT_RDONLY))
+        return (EACCES);
+
+    if ((ap->a_mode & VWRITE) != 0) {
+        mask |= 0x2;
+    }
+    if ((ap->a_mode & VREAD) != 0) {
+        mask |= 0x4;
+    }
+    if ((ap->a_mode & VEXEC) != 0) {
+        mask |= 0x1;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    access.mask = mask;
+    msg.data = &access;
+    msg.len = sizeof(access);
+    msg.cb = &fuse_sync_it;
+    msg.fmp = fmp;
+    msg.type = msg_intr;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_ACCESS, ip->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse access", 0);
+
+    if (error)
+        return (error);
+
+    DPRINTF("it with value %x\n", msg.rep.it_res);
+    error = msg.rep.it_res;
+
+    if (error == ENOSYS) {
+        fmp->undef_op |= UNDEF_ACCESS;
+        goto system_check;
+    }
+
+    return (error);
+
+system_check:
+    DPRINTF("Use kernel access\n");
+
+    return (vaccess(ap->a_vp->v_type, ip->cached_attrs.va_mode & ALLPERMS,
+        ip->cached_attrs.va_uid, ip->cached_attrs.va_gid, ap->a_mode,
+        ap->a_cred));
+}
+
+int
+fusefs_getattr(void *v)
+{
+    struct vop_getattr_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_mnt *fmp;
+    struct vattr *vap = ap->a_vap;
+    struct proc *p = ap->a_p;
+    struct fuse_in_header hdr;
+    struct fuse_attr_out *fat;
+    struct fuse_node *ip;
+    struct fuse_msg msg;
+    int error = 0;
+
+    DPRINTF("fusefs_getattr\n");
+
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        goto fake;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = 0;
+    msg.data = NULL;
+    msg.rep.buff.len = sizeof(*fat);
+    msg.rep.buff.data_rcv = NULL;
+    msg.type = msg_buff;
+    msg.cb = &fuse_sync_resp;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_GETATTR, ip->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse getattr", 0);
+
+    if (error) {
+        if (msg.rep.buff.data_rcv != NULL)
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+        return (error);
+    }
+
+    fat = (struct fuse_attr_out *)msg.rep.buff.data_rcv;
+
+    DPRINTF("ino: %d\n", fat->attr.ino);
+    DPRINTF("size: %d\n", fat->attr.size);
+    DPRINTF("blocks: %d\n", fat->attr.blocks);
+    DPRINTF("atime: %d\n", fat->attr.atime);
+    DPRINTF("mtime: %d\n", fat->attr.mtime);
+    DPRINTF("ctime: %d\n", fat->attr.ctime);
+    DPRINTF("atimensec: %d\n", fat->attr.atimensec);
+    DPRINTF("mtimensec: %d\n", fat->attr.mtimensec);
+    DPRINTF("ctimensec: %d\n", fat->attr.ctimensec);
+    DPRINTF("mode: %d\n", fat->attr.mode);
+    DPRINTF("nlink: %d\n", fat->attr.nlink);
+    DPRINTF("uid: %d\n", fat->attr.uid);
+    DPRINTF("gid: %d\n", fat->attr.gid);
+    DPRINTF("rdev: %d\n", fat->attr.rdev);
+
+    fuse_internal_attr_fat2vat(fmp->mp, &fat->attr, vap);
+
+    memcpy(&ip->cached_attrs, vap, sizeof(*vap));
+    free(fat, M_FUSEFS);
+
+    return (error);
+fake:
+    bzero(vap, sizeof(*vap));
+    vap->va_type = vp->v_type;
+    return (0);
+}
+
+int
+fusefs_setattr(void *v)
+{
+    DPRINTF("fusefs_setattr\n");
+    return (0);
+}
+
+int
+fusefs_ioctl(void *v)
+{
+    DPRINTF("fusefs_ioctl\n");
+    return (ENOTTY);
+}
+
+int
+fusefs_link(void *v)
+{
+    struct vop_link_args *ap = v;
+    struct vnode *dvp = ap->a_dvp;
+    struct vnode *vp = ap->a_vp;
+    struct componentname *cnp = ap->a_cnp;
+    struct proc *p = cnp->cn_proc;
+    struct fuse_in_header hdr;
+    struct fuse_entry_out *feo;
+    struct fuse_link_in fli;
+    struct fuse_mnt *fmp;
+    struct fuse_node *ip;
+    struct fuse_msg msg;
+    int error = 0;
+
+    DPRINTF("fusefs_link\n");
+
+    if (vp->v_type == VDIR) {
+        VOP_ABORTOP(dvp, cnp);
+        error = EISDIR;
+        goto out2;
+    }
+    if (dvp->v_mount != vp->v_mount) {
+        VOP_ABORTOP(dvp, cnp);
+        error = EXDEV;
+        goto out2;
+    }
+    if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
+        VOP_ABORTOP(dvp, cnp);
+        goto out2;
+    }
+
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_LINK))
+        goto out1;
+
+    fli.oldnodeid = ip->i_number;
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = sizeof(fli);
+    msg.data = &fli;
+    msg.rep.buff.len = sizeof(struct fuse_entry_out);
+    msg.rep.buff.data_rcv = NULL;
+    msg.type = msg_buff;
+    msg.cb = &fuse_sync_resp;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_LINK, ip->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    error = tsleep(&msg, PWAIT, "fuse link", 0);
+
+    if (error) {
+        if (msg.rep.buff.data_rcv != NULL)
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+        goto out1;
+    }
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_LINK;
+        }
+
+        goto out1;
+    }
+
+    feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+    free(feo, M_FUSEFS);
+
+out1:
+    if (dvp != vp)
+        VOP_UNLOCK(vp, 0, p);
+out2:
+    vput(dvp);
+    return (error);
+}
+
+int
+fusefs_symlink(void *v)
+{
+    DPRINTF("fusefs_symlink\n");
+    return (0);
+}
+
+#define GENERIC_DIRSIZ(dp) \
+    ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3)
&~ 3))
+
+
+int
+readdir_process_data(void *buff, int len, struct uio *uio)
+{
+    struct fuse_dirent *fdir;
+    struct dirent dir;
+    int bytes;
+    int flen, error = 0;
+
+    if (len < FUSE_NAME_OFFSET) {
+        return (0);
+    }
+
+    while ( len > 0) {
+        if ( len < sizeof(*fdir)) {
+            error = 0;
+            break;
+        }
+
+        fdir = (struct fuse_dirent *)buff;
+        flen = FUSE_DIRENT_SIZE(fdir);
+
+        if (!fdir->namelen || fdir->namelen > MAXNAMLEN || len < flen) {
+            error = EINVAL;
+            break;
+        }
+
+        bytes = GENERIC_DIRSIZ((struct pseudo_dirent *) &fdir->namelen);
+        if (bytes > uio->uio_resid) {
+            error = 0;
+            break;
+        }
+
+        bzero(&dir, sizeof(dir));
+        dir.d_fileno = fdir->ino;
+        dir.d_reclen = bytes;
+        dir.d_type = fdir->type;
+        dir.d_namlen = fdir->namelen;
+        bcopy(fdir->name, dir.d_name, fdir->namelen);
+
+        uiomove(&dir, bytes , uio);
+        len -= flen;
+        /* ugly pointer arithmetic must find something else ...*/
+        buff = (void *)(((char *) buff) + flen);
+        uio->uio_offset = fdir->off;
+    }
+
+    return (error);
+}
+
+int
+fusefs_readdir(void *v)
+{
+    struct vop_readdir_args *ap = v;
+    struct fuse_read_in read;
+    struct fuse_in_header hdr;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    struct vnode *vp;
+    struct proc *p;
+    struct uio *uio;
+    int error = 0;
+
+    vp = ap->a_vp;
+    uio = ap->a_uio;
+    p = uio->uio_procp;
+
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init) {
+        return (0);
+    }
+
+    DPRINTF("fusefs_readdir\n");
+    DPRINTF("uio resid 0x%x\n", uio->uio_resid);
+
+    if (uio->uio_resid == 0)
+        return (error);
+
+    while (uio->uio_resid > 0) {
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = sizeof(read);
+        msg.type = msg_buff;
+
+        msg.rep.buff.len= 0;
+        msg.rep.buff.data_rcv = NULL;
+        msg.data = &read;
+        msg.cb = &fuse_sync_resp;
+
+        if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) {
+              DPRINTF("dir not open\n");
+              /* TODO open the file */
+              return (error);
+        }
+        read.fh = ip->fufh[FUFH_RDONLY].fh_id;
+        read.offset = uio->uio_offset;
+        read.size = MIN(uio->uio_resid, PAGE_SIZE);
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READDIR,
+            ip->i_number, p);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        error = tsleep(&msg, PWAIT, "fuse getattr", 0);
+
+        if (error) {
+            if (msg.rep.buff.len != 0)
+                free(msg.rep.buff.data_rcv, M_FUSEFS);
+            return (error);
+        }
+
+        if (msg.error == -1) {
+            //ack for end of readdir
+            break;
+        }
+
+        if ((error = readdir_process_data(msg.rep.buff.data_rcv,
+            msg.rep.buff.len, uio))) {
+            if (msg.rep.buff.len != 0)
+                free(msg.rep.buff.data_rcv, M_FUSEFS);
+            break;
+        }
+
+        if (msg.rep.buff.len != 0)
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+    }
+
+    return (error);
+}
+
+int
+fusefs_inactive(void *v)
+{
+    struct vop_inactive_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct proc *p = ap->a_p;
+    register struct fuse_node *ip = VTOI(vp);
+    int error = 0;
+
+    DPRINTF("fusefs_inactive\n");
+
+    ip->flag = 0;
+    VOP_UNLOCK(vp, 0, p);
+
+    /* not sure if it is ok to do like that ...*/
+    if (ip->cached_attrs.va_mode == 0)
+        vrecycle(vp, p);
+
+    return (error);
+}
+
+int
+fusefs_readlink(void *v)
+{
+    struct vop_readlink_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_in_header hdr;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    struct uio *uio;
+    struct proc *p;
+    int error = 0;
+
+    DPRINTF("fusefs_readlink\n");
+
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+    uio = ap->a_uio;
+    p = uio->uio_procp;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_READLINK)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = 0;
+    msg.data = NULL;
+    msg.type = msg_buff;
+    msg.rep.buff.len = 0;
+    msg.rep.buff.data_rcv = NULL;
+    msg.cb = &fuse_sync_resp;
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READLINK, ip->i_number,
+        p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse readlink", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_READLINK;
+        }
+        goto out;
+    }
+
+    error = uiomove(msg.rep.buff.data_rcv, msg.rep.buff.len, uio);
+
+out:
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+    return (error);
+}
+
+int
+fusefs_reclaim(void *v)
+{
+    struct vop_reclaim_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_node *ip = VTOI(vp);
+
+    DPRINTF("fusefs_reclaim\n");
+
+    /*
+     * Purge old data structures associated with the inode.
+     */
+    ip->parent = 0;
+
+    /*
+     * Remove the inode from its hash chain.
+     */
+    fusefs_ihashrem(ip);
+    cache_purge(vp);
+
+    /*close file if exist
+    if (ip->i_fd) {
+        vrele(ip->i_devvp);
+        ip->i_devvp = 0;
+    }*/
+
+    free(ip, M_FUSEFS);
+    vp->v_data = NULL;
+    return (0);
+}
+
+int
+fusefs_print(void *v)
+{
+    struct vop_print_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct fuse_node *ip = VTOI(vp);
+
+    /*
+     * Complete the information given by vprint().
+     */
+    printf("tag VT_FUSE, hash id %u ", ip->i_number);
+    lockmgr_printinfo(&ip->i_lock);
+    printf("\n");
+    return (0);
+}
+
+int
+fusefs_create(void *v)
+{
+    struct vop_create_args *ap = v;
+    struct componentname *cnp = ap->a_cnp;
+    struct vnode **vpp = ap->a_vpp;
+    struct vnode *dvp = ap->a_dvp;
+    struct vattr *vap = ap->a_vap;
+    struct proc *p = cnp->cn_proc;
+    struct fuse_entry_out *feo;
+    struct fuse_in_header hdr;
+    struct vnode *tdp = NULL;
+    struct fuse_open_in foi;
+    struct fuse_mnt *fmp;
+    struct fuse_node *ip;
+    struct fuse_msg msg;
+    int error = 0;
+    mode_t mode;
+
+    DPRINTF("fusefs_create(cnp %08x, vap %08x\n", cnp, vap);
+
+    ip = VTOI(dvp);
+    fmp = ip->i_mnt;
+    mode = MAKEIMODE(vap->va_type, vap->va_mode);
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_CREATE)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = sizeof(foi) + cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_buff;
+    msg.rep.buff.len = sizeof(struct fuse_entry_out) +
+        sizeof(struct fuse_open_out);
+    msg.rep.buff.data_rcv = NULL;
+    msg.cb = &fuse_sync_resp;
+
+    foi.mode = mode;
+    foi.flags = O_CREAT | O_RDWR;
+
+    memcpy(msg.data, &foi, sizeof(foi));
+    memcpy((char *)msg.data + sizeof(foi), cnp->cn_nameptr,
+        cnp->cn_namelen);
+    ((char *)msg.data)[sizeof(foi) + cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_CREATE, ip->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse create", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_CREATE;
+        }
+        goto out;
+    }
+
+    feo = msg.rep.buff.data_rcv;
+    if ((error = VFS_VGET(fmp->mp, feo->nodeid, &tdp)))
+        goto out;
+
+    tdp->v_type = IFTOVT(feo->attr.mode);
+    VTOI(tdp)->vtype = tdp->v_type;
+
+    if (dvp != NULL && dvp->v_type == VDIR)
+        VTOI(tdp)->parent = ip->i_number;
+
+    *vpp = tdp;
+    VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+
+out:
+    vput(ap->a_dvp);
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+
+    return (error);
+}
+
+int
+fusefs_mknod(void *v)
+{
+    struct vop_mknod_args *ap = v;
+
+    VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+    vput(ap->a_dvp);
+    return (EINVAL);
+}
+
+int
+fusefs_read(void *v)
+{
+    struct vop_read_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct uio *uio = ap->a_uio;
+    struct proc *p = uio->uio_procp;
+    struct fuse_in_header hdr;
+    struct fuse_read_in fri;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error=0;
+
+    DPRINTF("fusefs_read\n");
+
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    DPRINTF("read inode=%i, offset=%%llu, resid=%x\n", ip->i_number,
+           uio->uio_offset, uio->uio_resid);
+
+    if (uio->uio_resid == 0)
+        return (error);
+    if (uio->uio_offset < 0)
+        return (EINVAL);
+
+    while (uio->uio_resid > 0) {
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = sizeof(fri);
+        msg.data = &fri;
+        msg.type = msg_buff;
+        msg.rep.buff.len = 0;
+        msg.rep.buff.data_rcv = NULL;
+        msg.cb = &fuse_sync_resp;
+
+        fri.fh = ip->fufh[FUFH_RDONLY].fh_id;
+        fri.offset = uio->uio_offset;
+        fri.size = MIN(uio->uio_resid, fmp->max_write);
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READ,
+            ip->i_number, p);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        if ((error = tsleep(&msg, PWAIT, "fuse read", 0)))
+            break;
+
+        if (msg.error) {
+            DPRINTF("read error %i\n", msg.error);
+        }
+
+        if ((error = uiomove(msg.rep.buff.data_rcv,
+            MIN(fri.size, msg.rep.buff.len), uio))) {
+            break;
+        }
+
+        if (msg.rep.buff.len < fri.size)
+            break;
+
+        if (msg.rep.buff.data_rcv) {
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+            msg.rep.buff.data_rcv = NULL;
+        }
+    }
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+    return (error);
+}
+
+int
+fusefs_write(void *v)
+{
+    struct vop_write_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct uio *uio = ap->a_uio;
+    struct proc *p = uio->uio_procp;
+    struct fuse_in_header hdr;
+    struct fuse_write_in *fwi;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    size_t len, diff;
+    int error=0;
+
+    DPRINTF("fusefs_write\n");
+
+    ip = VTOI(vp);
+    fmp = ip->i_mnt;
+
+    DPRINTF("write inode=%i, offset=%llu, resid=%x\n", ip->i_number,
+           uio->uio_offset, uio->uio_resid);
+
+    if (uio->uio_resid == 0)
+        return (error);
+
+    while (uio->uio_resid > 0) {
+        len = MIN(uio->uio_resid, fmp->max_write);
+        bzero(&msg, sizeof(msg));
+        msg.hdr = &hdr;
+        msg.len = sizeof(*fwi) + len;
+        msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+        msg.type = msg_buff;
+        msg.rep.buff.len = sizeof(struct fuse_write_out);
+        msg.rep.buff.data_rcv = NULL;
+        msg.cb = &fuse_sync_resp;
+
+        fwi = (struct fuse_write_in *)msg.data;
+        fwi->fh = ip->fufh[FUFH_WRONLY].fh_id;
+        fwi->offset = uio->uio_offset;
+        fwi->size = len;
+
+        if ((error = uiomove((char *)msg.data + sizeof(*fwi), len,
+            uio))) {
+            DPRINTF("uio error %i", error);
+            break;
+        }
+
+        fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_WRITE,
+            ip->i_number, p);
+
+        TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+        wakeup(&fmq_in);
+
+        if ((error = tsleep(&msg, PWAIT, "fuse write", 0)))
+            break;
+
+        if (msg.error) {
+            DPRINTF("write error %i\n", msg.error);
+        }
+
+        diff = len -
+            ((struct fuse_write_out *)msg.rep.buff.data_rcv)->size;
+        if (diff < 0) {
+            error = EINVAL;
+            break;
+        }
+
+        uio->uio_resid += diff;
+        uio->uio_offset -= diff;
+
+        if (msg.rep.buff.data_rcv) {
+            free(msg.rep.buff.data_rcv, M_FUSEFS);
+            msg.rep.buff.data_rcv = NULL;
+        }
+    }
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+    return (error);
+}
+
+int
+fusefs_poll(void *v)
+{
+    struct vop_poll_args *ap = v;
+
+    DPRINTF("fusefs_poll\n");
+
+    /*
+     * We should really check to see if I/O is possible.
+     */
+    return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
+}
+
+int
+fusefs_fsync(void *v)
+{
+    DPRINTF("fusefs_fsync\n");
+    return (0);
+}
+
+int
+fusefs_rename(void *v)
+{
+    DPRINTF("fusefs_rename\n");
+    return (0);
+}
+
+int
+fusefs_mkdir(void *v)
+{
+    struct vop_mkdir_args *ap = v;
+    struct vnode *dvp = ap->a_dvp;
+    struct vnode **vpp = ap->a_vpp;
+    struct componentname *cnp = ap->a_cnp;
+    struct vattr *vap = ap->a_vap;
+    struct proc *p = cnp->cn_proc;
+    struct fuse_mkdir_in fmdi;
+    struct vnode *tdp = NULL;
+    struct fuse_in_header hdr;
+    struct fuse_entry_out *feo;
+    struct fuse_node *ip;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error = 0;
+
+    DPRINTF("fusefs_mkdir %s\n", cnp->cn_nameptr);
+
+    ip = VTOI(dvp);
+    fmp = ip->i_mnt;
+    fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKDIR)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = sizeof(fmdi) + cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_buff;
+    msg.rep.buff.len = sizeof(struct fuse_entry_out);
+    msg.rep.buff.data_rcv = NULL;
+    msg.cb = &fuse_sync_resp;
+
+    memcpy(msg.data, &fmdi, sizeof(fmdi));
+    memcpy((char *)msg.data + sizeof(fmdi), cnp->cn_nameptr,
+        cnp->cn_namelen);
+    ((char *)msg.data)[sizeof(fmdi) + cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_MKDIR, ip->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse mkdir", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS) {
+            fmp->undef_op |= UNDEF_MKDIR;
+        }
+        goto out;
+    }
+
+    feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+
+    if ((error = VFS_VGET(fmp->mp, feo->nodeid, &tdp)))
+        goto out;
+
+    tdp->v_type = IFTOVT(feo->attr.mode);
+    VTOI(tdp)->vtype = tdp->v_type;
+
+    if (dvp != NULL && dvp->v_type == VDIR)
+        VTOI(tdp)->parent = ip->i_number;
+
+    *vpp = tdp;
+    VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
+
+out:
+    vput(dvp);
+
+    if (msg.rep.buff.data_rcv)
+        free(msg.rep.buff.data_rcv, M_FUSEFS);
+
+    return (error);
+}
+
+int
+fusefs_rmdir(void *v)
+{
+    struct vop_rmdir_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
+    struct componentname *cnp = ap->a_cnp;
+    struct proc *p = cnp->cn_proc;
+    struct fuse_node *ip, *dp;
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error;
+
+    DPRINTF("fusefs_rmdir\n");
+    DPRINTF("len :%i, cnp: %c %c %c\n", cnp->cn_namelen,
cnp->cn_nameptr[0],
+        cnp->cn_nameptr[1], cnp->cn_nameptr[2]);
+
+    ip = VTOI(vp);
+    dp = VTOI(dvp);
+    fmp = ip->i_mnt;
+
+    /*
+     * No rmdir "." please.
+     */
+    if (dp == ip) {
+        vrele(dvp);
+        vput(vp);
+        return (EINVAL);
+    }
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_RMDIR)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_intr;
+    msg.cb = &fuse_sync_it;
+
+    memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+    ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_RMDIR, dp->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+    if ((error = tsleep(&msg, PWAIT, "fuse rmdir", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS)
+            fmp->undef_op |= UNDEF_RMDIR;
+        if (error != ENOTEMPTY)
+            VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+        goto out;
+    }
+
+    VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+    cache_purge(dvp);
+    vput(dvp);
+    dvp = NULL;
+
+    cache_purge(ITOV(ip));
+out:
+    if (dvp)
+        vput(dvp);
+    VN_KNOTE(vp, NOTE_DELETE);
+    vput(vp);
+    return (error);
+}
+
+int
+fusefs_remove(void *v)
+{
+    struct vop_remove_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
+    struct componentname *cnp = ap->a_cnp;
+    struct proc *p = cnp->cn_proc;
+    struct fuse_node *ip;
+    struct fuse_node *dp;
+    struct fuse_in_header hdr;
+    struct fuse_mnt *fmp;
+    struct fuse_msg msg;
+    int error = 0;
+
+    DPRINTF("fusefs_remove\n");
+    DPRINTF("len :%i, cnp: %c %c %c\n", cnp->cn_namelen,
cnp->cn_nameptr[0],
+        cnp->cn_nameptr[1], cnp->cn_nameptr[2]);
+
+    ip = VTOI(vp);
+    dp = VTOI(dvp);
+    fmp = ip->i_mnt;
+
+    if (!fmp->sess_init || (fmp->undef_op & UNDEF_REMOVE)) {
+        error = ENOSYS;
+        goto out;
+    }
+
+    bzero(&msg, sizeof(msg));
+    msg.hdr = &hdr;
+    msg.len = cnp->cn_namelen + 1;
+    msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+    msg.type = msg_intr;
+    msg.cb = &fuse_sync_it;
+
+    memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+    ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+    fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_UNLINK, dp->i_number, p);
+
+    TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+    wakeup(&fmq_in);
+
+
+    if ((error = tsleep(&msg, PWAIT, "fuse remove", 0)))
+        goto out;
+
+    if (msg.error) {
+        error = msg.error;
+
+        if (error == ENOSYS)
+            fmp->undef_op |= UNDEF_REMOVE;
+        goto out;
+    }
+
+
+    VN_KNOTE(vp, NOTE_DELETE);
+    VN_KNOTE(dvp, NOTE_WRITE);
+out:
+    if (dvp == vp)
+        vrele(vp);
+    else
+        vput(vp);
+    vput(dvp);
+    return (error);
+}
+
+int
+fusefs_strategy(void *v)
+{
+    DPRINTF("fusefs_strategy\n");
+    return (0);
+}
+
+int
+fusefs_lock(void *v)
+{
+    struct vop_lock_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+
+    DPRINTF("fuse_lock\n");
+    return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, NULL));
+}
+
+int
+fusefs_unlock(void *v)
+{
+    struct vop_unlock_args *ap = v;
+    struct vnode *vp = ap->a_vp;
+
+    DPRINTF("fuse_unlock\n");
+    return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, NULL));
+}
+
+int
+fusefs_islocked(void *v)
+{
+    struct vop_islocked_args *ap = v;
+
+    DPRINTF("fuse_islock\n");
+    return (lockstatus(&VTOI(ap->a_vp)->i_lock));
+}
+
+int
+fusefs_advlock(void *v)
+{
+    struct vop_advlock_args *ap = v;
+    struct fuse_node *ip = VTOI(ap->a_vp);
+
+    DPRINTF("fuse_advlock\n");
+    return (lf_advlock(&ip->i_lockf, ip->filesize, ap->a_id, ap->a_op,
+        ap->a_fl, ap->a_flags));
+}
Index: sys/miscfs/fuse/fusefs.h
===================================================================
RCS file: sys/miscfs/fuse/fusefs.h
diff -N sys/miscfs/fuse/fusefs.h
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fusefs.h    6 Mar 2013 20:04:27 -0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FUSEFS_H__
+#define __FUSEFS_H__
+
+struct fuse_msg;
+
+struct fuse_mnt {
+    struct mount *mp;
+    uint32_t undef_op;
+    uint32_t max_write;
+    int sess_init;
+    int unique;
+    int fd;
+};
+
+#define    UNDEF_ACCESS    1<<0
+#define    UNDEF_MKDIR    1<<1
+#define    UNDEF_CREATE    1<<2
+#define    UNDEF_LINK    1<<3
+#define UNDEF_READLINK    1<<4
+#define UNDEF_RMDIR    1<<5
+#define UNDEF_REMOVE    1<<6
+
+typedef void (*fuse_cb)(struct fuse_msg *,struct fuse_out_header *,
void *);
+
+struct rcv_buf {
+    void *data_rcv;
+    size_t len;
+};
+
+enum msg_type {
+    msg_intr,
+    msg_buff,
+    msg_buff_async,
+};
+
+struct fuse_msg {
+    struct fuse_in_header *hdr;
+    struct fuse_mnt *fmp;
+    void *data;
+    int len;
+    int error;
+
+    enum msg_type type;
+    union {
+        struct rcv_buf buff;
+        uint32_t it_res;
+    } rep;
+
+    fuse_cb cb;
+    TAILQ_ENTRY(fuse_msg) node;
+};
+
+extern struct vops fusefs_vops;
+
+/*
+ * In and Out fifo for fuse communication
+ */
+TAILQ_HEAD(fuse_msg_head, fuse_msg);
+
+extern struct fuse_msg_head fmq_in;
+extern struct fuse_msg_head fmq_wait;
+
+/*
+ * fuse helpers
+ */
+void fuse_make_in(struct mount *, struct fuse_in_header *, int,
+          enum fuse_opcode, ino_t, struct proc *);
+void fuse_init_resp(struct fuse_msg *, struct fuse_out_header *, void *);
+void fuse_sync_resp(struct fuse_msg *, struct fuse_out_header *, void *);
+void fuse_sync_it(struct fuse_msg *, struct fuse_out_header *, void *);
+
+/*
+ * files helpers.
+ */
+
+int fuse_file_open(struct fuse_mnt *, struct fuse_node *, enum
fufh_type, int,
+    int, struct proc *);
+int fuse_file_close(struct fuse_mnt *, struct fuse_node *, enum
fufh_type, int,
+    int, struct proc *);
+void fuse_internal_attr_fat2vat(struct mount *, struct fuse_attr *,
+    struct vattr *);
+
+/*
+ * The root inode is the root of the file system.  Inode 0 can't be
used for
+ * normal purposes and bad blocks are normally linked to inode 1, thus
+ * the root inode is 2.
+ */
+#define    FUSE_ROOTINO ((ino_t)1)
+#define VFSTOFUSEFS(mp)    ((struct fuse_mnt *)((mp)->mnt_data))
+
+#define MAX_FUSE_DEV 4
+/*
+#define FUSE_DEBUG_VNOP
+#define FUSE_DEBUG_VFS
+#define FUSE_DEV_DEBUG
+#define FUSE_DEBUG_MSG
+*/
+
+#endif /* __FUSEFS_H__ */
Index: sys/sys/conf.h
===================================================================
RCS file: /cvs/src/sys/sys/conf.h,v
retrieving revision 1.119
diff -u -p -r1.119 conf.h
--- sys/sys/conf.h    23 Aug 2012 06:12:49 -0000    1.119
+++ sys/sys/conf.h    6 Mar 2013 20:04:27 -0000
@@ -509,6 +509,13 @@ extern struct cdevsw cdevsw[];
      (dev_type_stop((*))) enodev, 0, selfalse, \
      (dev_type_mmap((*))) enodev }

+/* open, close, read, write, poll, ioctl */
+#define cdev_fuse_init(c,n) { \
+    dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+    dev_init(c,n,write), dev_init(c,n,ioctl), \
+    (dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
+    (dev_type_mmap((*))) enodev }
+
  #endif

  /*
@@ -657,6 +664,7 @@ cdev_decl(urio);
  cdev_decl(hotplug);
  cdev_decl(gpio);
  cdev_decl(amdmsr);
+cdev_decl(fuse);

  #endif

Index: sys/sys/malloc.h
===================================================================
RCS file: /cvs/src/sys/sys/malloc.h,v
retrieving revision 1.101
diff -u -p -r1.101 malloc.h
--- sys/sys/malloc.h    7 Feb 2013 11:06:42 -0000    1.101
+++ sys/sys/malloc.h    6 Mar 2013 20:04:28 -0000
@@ -118,7 +118,8 @@
  #define    M_TTYS        62    /* allocated tty structures */
  #define    M_EXEC        63    /* argument lists & other mem used by
exec */
  #define    M_MISCFSMNT    64    /* miscfs mount structures */
-/* 65-73 - free */
+#define M_FUSEFS    65    /* fusefs mount structures */
+/* 66-73 - free */
  #define    M_PFKEY        74    /* pfkey data */
  #define    M_TDB        75    /* Transforms database */
  #define    M_XDATA        76    /* IPsec data */
@@ -247,7 +248,7 @@
      "ttys",        /* 62 M_TTYS */ \
      "exec",        /* 63 M_EXEC */ \
      "miscfs mount",    /* 64 M_MISCFSMNT */ \
-    NULL, \
+    "fusefs mount", /* 65 M_FUSEFS */ \
      NULL, \
      NULL, \
      NULL, \
Index: sys/sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.108
diff -u -p -r1.108 mount.h
--- sys/sys/mount.h    5 Sep 2012 17:01:06 -0000    1.108
+++ sys/sys/mount.h    6 Mar 2013 20:04:28 -0000
@@ -258,6 +258,15 @@ struct procfs_args {
  #define PROCFS_ARGSVERSION      1
  #define PROCFSMNT_LINUXCOMPAT   0x01

+/*
+ * Arguments to mount fusefs filesystems
+ */
+struct fusefs_args {
+    char *name;
+    char *url;
+    int fd;
+    int flags;
+};

  /*
   * file system statistics
@@ -325,6 +334,7 @@ struct statfs {
  #define    MOUNT_NCPFS    "ncpfs"        /* NetWare Network File System */
  #define    MOUNT_NTFS    "ntfs"        /* NTFS */
  #define    MOUNT_UDF    "udf"        /* UDF */
+#define MOUNT_FUSEFS    "fuse"        /* FUSE */

  /*
   * Structure per mounted file system.  Each mounted file system has an
Index: sys/sys/vnode.h
===================================================================
RCS file: /cvs/src/sys/sys/vnode.h,v
retrieving revision 1.113
diff -u -p -r1.113 vnode.h
--- sys/sys/vnode.h    8 Oct 2012 15:43:08 -0000    1.113
+++ sys/sys/vnode.h    6 Mar 2013 20:04:28 -0000
@@ -71,13 +71,13 @@ enum vtype    { VNON, VREG, VDIR, VBLK, VCH
  enum vtagtype    {
      VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_MSDOSFS,
      VT_PORTAL, VT_PROCFS, VT_AFS, VT_ISOFS, VT_ADOSFS,
-    VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF,
+    VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF, VT_FUSEFS
  };

  #define    VTAG_NAMES \
      "NON", "UFS", "NFS", "MFS", "MSDOSFS",            \
      "PORTAL", "PROCFS", "AFS", "ISOFS", "ADOSFS",        \
-    "EXT2FS", "VFS", "NTFS", "UDF"
+    "EXT2FS", "VFS", "NTFS", "UDF", "FUSEFS"

  /*
   * Each underlying filesystem allocates its own private area and hangs

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Ted Unangst-6
In reply to this post by Martin Pieuchot-2
On Wed, Mar 06, 2013 at 22:27, Sylvestre Gallon wrote:
> Do you know if miscfs is the best place to put my code ?

I think so.

> Do I keep the device code (fuse_device.c) in the same directory than the
> filesystem code?

I'd prefer that.  sys/dev is kind of cluttered as it is, and since the
dev code and fs code are tightly coupled, it makes sense to keep it
all in one place.

> Do you know which fs type I can use in kern/vfs_init.c for fuse ? I've
> taken 42 but I have no idea what I was doing when I choose this number :)

Whatever.  I don't think those numbers are used.

> +/*
> + * The root inode is the root of the file system.  Inode 0 can't be
> used for
> + * normal purposes and bad blocks are normally linked to inode 1, thus
> + * the root inode is 2.
> + */
> +#define    FUSE_ROOTINO ((ino_t)1)

Internal disagreement here. :)

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Jonathan ARMANI-2
In reply to this post by Sylvestre Gallon
On Tue, Mar 05, 2013 at 03:24:06PM +0100, Sylvestre Gallon wrote:

> I am not quite sure but I think that only libfuse and sshfs are GPL
> licenced. The patches for those two items are only present in ports.
>
> All the code present in src is ISC licenced. The kernel communicate with
> libfuse througth a device (ie /dev/fuse) and only share a header with the
> libfuse (fuse_kernel.h) which is BSD licenced. FreeBSD used the same way to
> implement it. (I do not know if it is a good example)
>

Hi Sylvestre,

Nice to see that someone is working on this.

I think the problem here is that the kernel will provide a service that only
ports can use. If we want to use it in the basesystem, we will have to
rewrite a BSD licenced libfuse.

Other possibility is to make it a loadable kernel module, but I don't know
the current state of our support.
 

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Gilles Chehade-7
On Thu, Mar 07, 2013 at 01:10:48PM +0100, Jonathan Armani wrote:

> On Tue, Mar 05, 2013 at 03:24:06PM +0100, Sylvestre Gallon wrote:
>
> > I am not quite sure but I think that only libfuse and sshfs are GPL
> > licenced. The patches for those two items are only present in ports.
> >
> > All the code present in src is ISC licenced. The kernel communicate with
> > libfuse througth a device (ie /dev/fuse) and only share a header with the
> > libfuse (fuse_kernel.h) which is BSD licenced. FreeBSD used the same way to
> > implement it. (I do not know if it is a good example)
> >
>
> Hi Sylvestre,
>
> Nice to see that someone is working on this.
>
> I think the problem here is that the kernel will provide a service that only
> ports can use. If we want to use it in the basesystem, we will have to
> rewrite a BSD licenced libfuse.
>

Quite frankly, if there's work in that area and hope that it does not go
to waste, I will happily volunteer to work on that.

--
Gilles Chehade

https://www.poolp.org                                          @poolpOrg

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Bob Beck-2
On Thu, Mar 7, 2013 at 6:16 AM, Gilles Chehade <[hidden email]> wrote:

> On Thu, Mar 07, 2013 at 01:10:48PM +0100, Jonathan Armani wrote:
> > On Tue, Mar 05, 2013 at 03:24:06PM +0100, Sylvestre Gallon wrote:
> >
> > > I am not quite sure but I think that only libfuse and sshfs are GPL
> > > licenced. The patches for those two items are only present in ports.
> > >
> > > All the code present in src is ISC licenced. The kernel communicate
> with
> > > libfuse througth a device (ie /dev/fuse) and only share a header with
> the
> > > libfuse (fuse_kernel.h) which is BSD licenced. FreeBSD used the same
> way to
> > > implement it. (I do not know if it is a good example)
> > >
> >
> > Hi Sylvestre,
> >
> > Nice to see that someone is working on this.
> >
> > I think the problem here is that the kernel will provide a service that
> only
> > ports can use. If we want to use it in the basesystem, we will have to
> > rewrite a BSD licenced libfuse.
> >
>
> Quite frankly, if there's work in that area and hope that it does not go
> to waste, I will happily volunteer to work on that.
>


....

Which is why I keep pointing people at puffs and librefuse in netbsd....



>
> --
> Gilles Chehade
>
> https://www.poolp.org                                          @poolpOrg
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
On Thu, Mar 7, 2013 at 3:03 PM, Bob Beck <[hidden email]> wrote:
>
> ....
>
> Which is why I keep pointing people at puffs and librefuse in netbsd....
>
>

Hi,

Using puffs will induce a rewrite of all the kernel code, because the
internals are completely different (and I think a little bit more
complex, but this is a personal opinion...).

For a libfuse support in basesystem we will need to do a librefuse
like library. In this case we could perhaps keep the librefuse
frontend and only rewrite the backend.

Which solution do you think is best ? In any case and if you need me,
I will be provide all the help I can :)

Cheers,

--
Sylvestre Gallon

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Bob Beck-2
> Using puffs will induce a rewrite of all the kernel code, because the
> internals are completely different (and I think a little bit more
> complex, but this is a personal opinion...).
>
>
I might share that opinon :)



> For a libfuse support in basesystem we will need to do a librefuse
> like library. In this case we could perhaps keep the librefuse
> frontend and only rewrite the backend.

 |

>

Which solution do you think is best ? In any case and if you need me,
> I will be provide all the help I can :)
>

Essentially we just need the best solution to have a base acceptable fuse
library. I don't know
what the right answer to that is, but  perhaps starting with librefuse and
makeing it less refusey (and more towards
compatible with a working ISC licensed fuse implementation in the kernel
would be the way to go.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
On 03/07/13 18:15, Bob Beck wrote:

>
>     Using puffs will induce a rewrite of all the kernel code, because the
>     internals are completely different (and I think a little bit more
>     complex, but this is a personal opinion...).
>
>
> I might share that opinon :)
>
>  
>
>     For a libfuse support in basesystem we will need to do a librefuse
>     like library. In this case we could perhaps keep the librefuse
>     frontend and only rewrite the backend.
>
>  |  
>
>      
>
>     Which solution do you think is best ? In any case and if you need me,
>     I will be provide all the help I can :)
>
>
> Essentially we just need the best solution to have a base acceptable
> fuse library. I don't know
> what the right answer to that is, but  perhaps starting with librefuse
> and makeing it less refusey (and more towards
> compatible with a working ISC licensed fuse implementation in the kernel
> would be the way to go.
>

Hi,

Here you can find a new inline patch (you can also found it here
http://www.pmbsd.org/patch-fuse-src)

It includes :

- Bug fixes.
- KNF changes
- Add a struct node in the fuse_node. (fuse_node only has fuse specific
now...)
- Replacement of fuse_ihash to ufs_ihash
- Use of *_softc structures and *UNIT macros for the fuse device.
- use of dev_t instead of fd as fuse connection identifier.
- todd@ patches for MAKEDEV
- todd@ patches for more arch supports.

I have started a minimalist README on how works the internals :

http://www.pmbsd.org/README

I will spend the next days working on the NetBSD librefuse, I will try
to get it working with my kernel code and will come back here when I
have something that works.

Cheers,

Index: etc/MAKEDEV.common
===================================================================
RCS file: /cvs/src/etc/MAKEDEV.common,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 MAKEDEV.common
--- etc/MAKEDEV.common 30 Jan 2013 01:59:20 -0000 1.61
+++ etc/MAKEDEV.common 8 Mar 2013 15:40:36 -0000
@@ -171,6 +171,7 @@ target(all, gpr, 0)dnl
 target(all, ptm)dnl
 target(all, hotplug)dnl
 target(all, pppx)dnl
+target(all, fuse)dnl
 dnl
 _mkdev(all, {-all-}, {-dnl
 show_target(all)dnl
@@ -208,6 +209,8 @@ __devitem(cd, {-cd*-}, ATAPI and SCSI CD
 _mkdev(cd, cd*, {-dodisk2 cd $U major_cd_b major_cd_c $U
0{--}ifstep(cd)-})dnl
 __devitem(bthub, {-bthub*-}, Bluetooth Hubs)dnl
 _mcdev(bthub, bthub*, bthub, {-major_bthub_c-})dnl
+__devitem(fuse, fuse, Userland Filesystem, fuse 1)dnl
+_mcdev(fuse, fuse, fuse, {-major_fuse_c-}, 600)dnl
 __devitem(ch, {-ch*-}, SCSI media changers)dnl
 _mcdev(ch, ch*, ch, {-major_ch_c-}, 660, operator)dnl
 __devitem(uk, uk*, Unknown SCSI devices)dnl
Index: etc/etc.alpha/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.alpha/MAKEDEV,v
retrieving revision 1.173
diff -u -p -u -p -r1.173 MAKEDEV
--- etc/etc.alpha/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.173
+++ etc/etc.alpha/MAKEDEV 8 Mar 2013 15:40:41 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.alpha/MAKEDEV.md,v 1.55 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -75,6 +75,7 @@
 # crypto Hardware crypto access driver
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # iop* I2O controller devices
 # lkm Loadable kernel modules interface
@@ -326,6 +327,10 @@ hotplug)
  M hotplug c 56 $U 400
  ;;

+fuse)
+ M fuse$U c 67 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 10 $n;n=$(($n+1));done
@@ -553,9 +558,9 @@ all)
  R sd4 sd5 sd6 sd7 sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bpf0
  R bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 fd1 fd1B
  R fd1C fd1D fd1E fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F
- R fd0G fd0H diskmap vscsi0 ch0 bio audio0 audio1 audio2 pppx
- R hotplug ptm local wscons pci0 pci1 pci2 pci3 iop0 iop1 uall
- R rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7
+ R fd0G fd0H diskmap vscsi0 ch0 bio audio0 audio1 audio2 fuse
+ R pppx hotplug ptm local wscons pci0 pci1 pci2 pci3 iop0 iop1
+ R uall rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7
  R tuner0 radio0 music0 speaker video0 video1 uk0 random lpa0
  R lpa1 lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyc0
  R ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 ttyB0 ttyB1 ttyB2
Index: etc/etc.alpha/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.alpha/MAKEDEV.md,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 MAKEDEV.md
--- etc/etc.alpha/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.55
+++ etc/etc.alpha/MAKEDEV.md 8 Mar 2013 15:40:41 -0000
@@ -69,6 +69,7 @@ _DEV(bthub, 62)
 _DEV(cry, 57)
 _DEV(diskmap, 63)
 _DEV(fdesc, 10)
+_DEV(fuse, 67)
 _DEV(hotplug, 56)
 _DEV(iop, 54)
 _DEV(lkm, 16)
Index: etc/etc.amd64/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.amd64/MAKEDEV,v
retrieving revision 1.80
diff -u -p -u -p -r1.80 MAKEDEV
--- etc/etc.amd64/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.80
+++ etc/etc.amd64/MAKEDEV 8 Mar 2013 15:40:41 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.amd64/MAKEDEV.md,v 1.48 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -77,6 +77,7 @@
 # diskmap Disk mapper
 # drm* Direct Rendering Manager
 # fd fd/* nodes
+# fuse Userland Filesystem
 # gpio* General Purpose Input/Output
 # gpr* GPR400 smartcard reader
 # hotplug devices hot plugging
@@ -343,6 +344,10 @@ gpio*)
  M gpio$U c 88 $U 600
  ;;

+fuse)
+ M fuse$U c 92 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 22 $n;n=$(($n+1));done
@@ -585,12 +590,12 @@ all)
  R sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3
  R bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 bio pty0 fd1 fd1B fd1C fd1D
  R fd1E fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H
- R diskmap vscsi0 ch0 audio0 audio1 audio2 pppx hotplug ptm
- R gpr0 local wscons pci0 pci1 pci2 pci3 iop0 iop1 uall rmidi0
- R rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7 tuner0
- R radio0 music0 speaker video0 video1 uk0 random lpa0 lpa1
- R lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyc0 ttyc1
- R ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 apm crypto pf pctr
+ R diskmap vscsi0 ch0 audio0 audio1 audio2 fuse pppx hotplug
+ R ptm gpr0 local wscons pci0 pci1 pci2 pci3 iop0 iop1 uall
+ R rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7
+ R tuner0 radio0 music0 speaker video0 video1 uk0 random lpa0
+ R lpa1 lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyc0
+ R ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 apm crypto pf pctr
  R systrace wd0 wd1 wd2 wd3 std st0 st1 fd
  ;;

Index: etc/etc.amd64/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.amd64/MAKEDEV.md,v
retrieving revision 1.48
diff -u -p -u -p -r1.48 MAKEDEV.md
--- etc/etc.amd64/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.48
+++ etc/etc.amd64/MAKEDEV.md 8 Mar 2013 15:40:41 -0000
@@ -77,6 +77,7 @@ _DEV(cry, 70)
 _DEV(diskmap, 90)
 _DEV(drm, 87)
 _DEV(fdesc, 22)
+_DEV(fuse, 92)
 _DEV(gpio, 88)
 _DEV(gpr, 80)
 _DEV(hotplug, 82)
Index: etc/etc.hp300/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.hp300/MAKEDEV,v
retrieving revision 1.134
diff -u -p -u -p -r1.134 MAKEDEV
--- etc/etc.hp300/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.134
+++ etc/etc.hp300/MAKEDEV 8 Mar 2013 15:40:41 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.hp300/MAKEDEV.md,v 1.45 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -63,6 +63,7 @@
 # bpf* Berkeley Packet Filter
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # lkm Loadable kernel modules interface
 # pf* Packet Filter
@@ -321,6 +322,10 @@ hotplug)
  M hotplug c 56 $U 400
  ;;

+fuse)
+ M fuse$U c 57 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done
@@ -471,8 +476,8 @@ all)
  R ct0 ct1 hd0 hd1 hd2 dcm0 dcm1 dcm2 dcm3 dca0 dca1 vnd0 vnd1
  R vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 cd0 cd1 rd0 tun0 tun1 tun2
  R tun3 bio bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9
- R pty0 diskmap vscsi0 ch0 audio0 pppx hotplug ptm local ppi0
- R apci0 wscons uk0 random lkm pf systrace std st0 st1 fd
+ R pty0 diskmap vscsi0 ch0 audio0 fuse pppx hotplug ptm local
+ R ppi0 apci0 wscons uk0 random lkm pf systrace std st0 st1 fd
  ;;

 sd*|hd*)
Index: etc/etc.hp300/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.hp300/MAKEDEV.md,v
retrieving revision 1.45
diff -u -p -u -p -r1.45 MAKEDEV.md
--- etc/etc.hp300/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.45
+++ etc/etc.hp300/MAKEDEV.md 8 Mar 2013 15:40:41 -0000
@@ -84,6 +84,7 @@ _DEV(bio, 49)
 _DEV(bpf, 22)
 _DEV(diskmap, 54)
 _DEV(fdesc, 21)
+_DEV(fuse, 57)
 _DEV(hotplug, 56)
 _DEV(lkm, 24)
 _DEV(pf, 33)
Index: etc/etc.hppa/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.hppa/MAKEDEV,v
retrieving revision 1.114
diff -u -p -u -p -r1.114 MAKEDEV
--- etc/etc.hppa/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.114
+++ etc/etc.hppa/MAKEDEV 8 Mar 2013 15:40:41 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.hppa/MAKEDEV.md,v 1.48 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -71,6 +71,7 @@
 # crypto Hardware crypto access driver
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # lkm Loadable kernel modules interface
 # pci* PCI bus devices
@@ -279,6 +280,10 @@ hotplug)
  M hotplug c 47 $U 400
  ;;

+fuse)
+ M fuse$U c 58 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 16 $n;n=$(($n+1));done
@@ -502,11 +507,11 @@ all)
  R sd4 sd5 sd6 sd7 sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bpf0
  R bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 fd1 fd1B
  R fd1C fd1D fd1E fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F
- R fd0G fd0H diskmap vscsi0 bio ch0 audio0 audio1 audio2 pppx
- R hotplug ptm local wscons pci0 pci1 pci2 pci3 uall video0
- R video1 uk0 random lpa0 lpa1 lpa2 lpt0 lpt1 lpt2 lkm tty00
- R tty01 tty02 tty03 crypto pf systrace wd0 wd1 wd2 wd3 std st0
- R st1 fd
+ R fd0G fd0H diskmap vscsi0 bio ch0 audio0 audio1 audio2 fuse
+ R pppx hotplug ptm local wscons pci0 pci1 pci2 pci3 uall
+ R video0 video1 uk0 random lpa0 lpa1 lpa2 lpt0 lpt1 lpt2 lkm
+ R tty00 tty01 tty02 tty03 crypto pf systrace wd0 wd1 wd2 wd3
+ R std st0 st1 fd
  ;;

 wd*|sd*)
Index: etc/etc.hppa/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.hppa/MAKEDEV.md,v
retrieving revision 1.48
diff -u -p -u -p -r1.48 MAKEDEV.md
--- etc/etc.hppa/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.48
+++ etc/etc.hppa/MAKEDEV.md 8 Mar 2013 15:40:41 -0000
@@ -66,6 +66,7 @@ _DEV(bthub,55)
 _DEV(cry, 36)
 _DEV(diskmap,56)
 _DEV(fdesc, 16)
+_DEV(fuse, 58)
 _DEV(hotplug, 47)
 _DEV(lkm, 19)
 _DEV(pci, 31)
Index: etc/etc.hppa64/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.hppa64/MAKEDEV,v
retrieving revision 1.48
diff -u -p -u -p -r1.48 MAKEDEV
--- etc/etc.hppa64/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.48
+++ etc/etc.hppa64/MAKEDEV 8 Mar 2013 15:40:41 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.hppa64/MAKEDEV.md,v 1.25 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -70,6 +70,7 @@
 # crypto Hardware crypto access driver
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # lkm Loadable kernel modules interface
 # pci* PCI bus devices
 # pdc PDC device
@@ -273,6 +274,10 @@ lkm)
  M lkm c 19 0 640 _lkm
  ;;

+fuse)
+ M fuse$U c 58 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 16 $n;n=$(($n+1));done
@@ -492,9 +497,9 @@ all)
  R cd0 cd1 rd0 tun0 tun1 tun2 tun3 bio bpf0 bpf1 bpf2 bpf3 bpf4
  R bpf5 bpf6 bpf7 bpf8 bpf9 pty0 fd1 fd1B fd1C fd1D fd1E fd1F
  R fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H diskmap
- R vscsi0 ch0 audio0 audio1 audio2 pppx ptm local wscons pci0
- R pci1 pci2 pci3 uall video0 video1 uk0 random lpa0 lpa1 lpa2
- R lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 crypto pf
+ R vscsi0 ch0 audio0 audio1 audio2 fuse pppx ptm local wscons
+ R pci0 pci1 pci2 pci3 uall video0 video1 uk0 random lpa0 lpa1
+ R lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 crypto pf
  R systrace wd0 wd1 wd2 wd3 std st0 st1 fd
  ;;

Index: etc/etc.hppa64/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.hppa64/MAKEDEV.md,v
retrieving revision 1.25
diff -u -p -u -p -r1.25 MAKEDEV.md
--- etc/etc.hppa64/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.25
+++ etc/etc.hppa64/MAKEDEV.md 8 Mar 2013 15:40:41 -0000
@@ -65,6 +65,7 @@ _DEV(bpf, 17)
 _DEV(cry, 36)
 _DEV(diskmap,56)
 _DEV(fdesc, 16)
+_DEV(fuse, 58)
 _DEV(lkm, 19)
 _DEV(pci, 31)
 _DEV(pdc, 22)
Index: etc/etc.i386/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.i386/MAKEDEV,v
retrieving revision 1.221
diff -u -p -u -p -r1.221 MAKEDEV
--- etc/etc.i386/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.221
+++ etc/etc.i386/MAKEDEV 8 Mar 2013 15:40:41 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.i386/MAKEDEV.md,v 1.63 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -78,6 +78,7 @@
 # diskmap Disk mapper
 # drm* Direct Rendering Manager
 # fd fd/* nodes
+# fuse Userland Filesystem
 # gpio* General Purpose Input/Output
 # gpr* GPR400 smartcard reader
 # hotplug devices hot plugging
@@ -349,6 +350,10 @@ gpio*)
  M gpio$U c 83 $U 600
  ;;

+fuse)
+ M fuse$U c 93 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 22 $n;n=$(($n+1));done
@@ -595,9 +600,9 @@ all)
  R sd7 sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bio bpf0 bpf1
  R bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 fd1 fd1B fd1C
  R fd1D fd1E fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F fd0G
- R fd0H diskmap vscsi0 ch0 audio0 audio1 audio2 pppx hotplug
- R ptm gpr0 local wscons pci0 pci1 pci2 pci3 iop0 iop1 uall
- R rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7
+ R fd0H diskmap vscsi0 ch0 audio0 audio1 audio2 fuse pppx
+ R hotplug ptm gpr0 local wscons pci0 pci1 pci2 pci3 iop0 iop1
+ R uall rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7
  R tuner0 radio0 music0 speaker video0 video1 uk0 random joy0
  R joy1 lpa0 lpa1 lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02
  R tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 apm
Index: etc/etc.i386/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.i386/MAKEDEV.md,v
retrieving revision 1.63
diff -u -p -u -p -r1.63 MAKEDEV.md
--- etc/etc.i386/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.63
+++ etc/etc.i386/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -80,6 +80,7 @@ _DEV(cry, 70)
 _DEV(diskmap, 91)
 _DEV(drm, 88)
 _DEV(fdesc, 22)
+_DEV(fuse, 93)
 _DEV(gpio, 83)
 _DEV(gpr, 80)
 _DEV(hotplug, 82)
Index: etc/etc.landisk/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.landisk/MAKEDEV,v
retrieving revision 1.43
diff -u -p -u -p -r1.43 MAKEDEV
--- etc/etc.landisk/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.43
+++ etc/etc.landisk/MAKEDEV 8 Mar 2013 15:40:42 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.landisk/MAKEDEV.md,v 1.27 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -67,6 +67,7 @@
 # crypto Hardware crypto access driver
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # lkm Loadable kernel modules interface
 # music* MIDI sequencer
@@ -292,6 +293,10 @@ hotplug)
  M hotplug c 37 $U 400
  ;;

+fuse)
+ M fuse$U c 103 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 7 $n;n=$(($n+1));done
@@ -473,11 +478,11 @@ all)
  R bthub0 bthub1 bthub2 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3
  R sd4 sd5 sd6 sd7 sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bio
  R bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0
- R diskmap vscsi0 ch0 ttya audio0 audio1 audio2 pppx hotplug
- R ptm local wscons pci0 pci1 pci2 pci3 uall rmidi0 rmidi1
- R rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7 radio0 music0
- R video0 video1 uk0 random lkm crypto pf systrace wd0 wd1 wd2
- R wd3 std st0 st1 fd
+ R diskmap vscsi0 ch0 ttya audio0 audio1 audio2 fuse pppx
+ R hotplug ptm local wscons pci0 pci1 pci2 pci3 uall rmidi0
+ R rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6 rmidi7 radio0
+ R music0 video0 video1 uk0 random lkm crypto pf systrace wd0
+ R wd1 wd2 wd3 std st0 st1 fd
  ;;

 wd*|sd*)
Index: etc/etc.landisk/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.landisk/MAKEDEV.md,v
retrieving revision 1.27
diff -u -p -u -p -r1.27 MAKEDEV.md
--- etc/etc.landisk/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.27
+++ etc/etc.landisk/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -78,6 +78,7 @@ _DEV(bthub,100)
 _DEV(cry, 47)
 _DEV(diskmap,101)
 _DEV(fdesc, 7)
+_DEV(fuse, 103)
 _DEV(hotplug, 37)
 dnl _DEV(iop, 73)
 _DEV(lkm, 35)
Index: etc/etc.loongson/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.loongson/MAKEDEV,v
retrieving revision 1.23
diff -u -p -u -p -r1.23 MAKEDEV
--- etc/etc.loongson/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.23
+++ etc/etc.loongson/MAKEDEV 8 Mar 2013 15:40:42 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.loongson/MAKEDEV.md,v 1.13 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -69,6 +69,7 @@
 # crypto Hardware crypto access driver
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # pci* PCI bus devices
 # pf* Packet Filter
@@ -265,6 +266,10 @@ hotplug)
  M hotplug c 67 $U 400
  ;;

+fuse)
+ M fuse$U c 73 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 7 $n;n=$(($n+1));done
@@ -459,8 +464,8 @@ all)
  R bthub0 bthub1 bthub2 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3
  R sd4 sd5 sd6 sd7 sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bio
  R bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 pty1
- R pty2 diskmap vscsi0 audio0 audio1 audio2 pppx hotplug ptm
- R local wscons pci0 pci1 pci2 pci3 uall video0 video1 uk0
+ R pty2 diskmap vscsi0 audio0 audio1 audio2 fuse pppx hotplug
+ R ptm local wscons pci0 pci1 pci2 pci3 uall video0 video1 uk0
  R random tty00 tty01 tty02 tty03 apm crypto pf systrace wd0
  R wd1 wd2 wd3 std st0 st1 fd
  ;;
Index: etc/etc.loongson/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.loongson/MAKEDEV.md,v
retrieving revision 1.13
diff -u -p -u -p -r1.13 MAKEDEV.md
--- etc/etc.loongson/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.13
+++ etc/etc.loongson/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -72,6 +72,7 @@ _DEV(bthub, 68)
 _DEV(cry, 47)
 _DEV(diskmap, 70)
 _DEV(fdesc, 7)
+_DEV(fuse, 73)
 _DEV(hotplug, 67)
 dnl _DEV(lkm)
 _DEV(pci, 29)
Index: etc/etc.sgi/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.sgi/MAKEDEV,v
retrieving revision 1.67
diff -u -p -u -p -r1.67 MAKEDEV
--- etc/etc.sgi/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.67
+++ etc/etc.sgi/MAKEDEV 8 Mar 2013 15:40:42 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.sgi/MAKEDEV.md,v 1.37 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -68,6 +68,7 @@
 # crypto Hardware crypto access driver
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # pci* PCI bus devices
 # pf* Packet Filter
@@ -264,6 +265,10 @@ hotplug)
  M hotplug c 67 $U 400
  ;;

+fuse)
+ M fuse$U c 73 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 7 $n;n=$(($n+1));done
@@ -464,8 +469,8 @@ all)
  R ttya ttyb vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 sd5 sd6
  R sd7 sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bio bpf0 bpf1
  R bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 pty1 pty2
- R diskmap vscsi0 ch0 audio0 audio1 audio2 pppx hotplug ptm
- R local wscons pci0 pci1 pci2 pci3 uall video0 video1 uk0
+ R diskmap vscsi0 ch0 audio0 audio1 audio2 fuse pppx hotplug
+ R ptm local wscons pci0 pci1 pci2 pci3 uall video0 video1 uk0
  R random tty00 tty01 tty02 tty03 crypto pf systrace wd0 wd1
  R wd2 wd3 std st0 st1 fd
  ;;
Index: etc/etc.sgi/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.sgi/MAKEDEV.md,v
retrieving revision 1.37
diff -u -p -u -p -r1.37 MAKEDEV.md
--- etc/etc.sgi/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.37
+++ etc/etc.sgi/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -79,6 +79,7 @@ _DEV(bpf, 12)
 _DEV(cry, 47)
 _DEV(diskmap, 69)
 _DEV(fdesc, 7)
+_DEV(fuse, 73)
 _DEV(hotplug, 67)
 dnl _DEV(lkm)
 _DEV(pci, 29)
Index: etc/etc.socppc/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.socppc/MAKEDEV,v
retrieving revision 1.31
diff -u -p -u -p -r1.31 MAKEDEV
--- etc/etc.socppc/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.31
+++ etc/etc.socppc/MAKEDEV 8 Mar 2013 15:40:42 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.socppc/MAKEDEV.md,v 1.18 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -65,6 +65,7 @@
 # bthub* Bluetooth Hubs
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # lkm Loadable kernel modules interface
 # pci* PCI bus devices
@@ -262,6 +263,10 @@ hotplug)
  M hotplug c 84 $U 400
  ;;

+fuse)
+ M fuse$U c 85 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done
@@ -432,9 +437,9 @@ all)
  R bthub0 bthub1 bthub2 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3
  R sd4 sd5 sd6 sd7 sd8 sd9 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bpf0
  R bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 diskmap
- R vscsi0 ch0 pppx hotplug ptm local wscons pci0 pci1 pci2 pci3
- R uall video0 video1 random lkm tty00 tty01 tty02 tty03 pf
- R systrace wd0 wd1 wd2 wd3 std st0 st1 fd
+ R vscsi0 ch0 fuse pppx hotplug ptm local wscons pci0 pci1 pci2
+ R pci3 uall video0 video1 random lkm tty00 tty01 tty02 tty03
+ R pf systrace wd0 wd1 wd2 wd3 std st0 st1 fd
  ;;

 wd*|sd*)
Index: etc/etc.socppc/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.socppc/MAKEDEV.md,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 MAKEDEV.md
--- etc/etc.socppc/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.18
+++ etc/etc.socppc/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -65,6 +65,7 @@ _DEV(bthub, 81)
 dnl _DEV(cry, 47)
 _DEV(diskmap, 82)
 _DEV(fdesc, 21)
+_DEV(fuse, 85)
 dnl _DEV(gpio, 79)
 _DEV(hotplug, 84)
 dnl _DEV(iop, 73)
Index: etc/etc.sparc/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.sparc/MAKEDEV,v
retrieving revision 1.177
diff -u -p -u -p -r1.177 MAKEDEV
--- etc/etc.sparc/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.177
+++ etc/etc.sparc/MAKEDEV 8 Mar 2013 15:40:42 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.sparc/MAKEDEV.md,v 1.50 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -69,6 +69,7 @@
 # bpf* Berkeley Packet Filter
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # lkm Loadable kernel modules interface
 # openprom PROM settings
@@ -270,6 +271,10 @@ hotplug)
  M hotplug c 131 $U 400
  ;;

+fuse)
+ M fuse$U c 82 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 24 $n;n=$(($n+1));done
@@ -518,9 +523,9 @@ all)
  R bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 fd1 fd1B fd1C fd1D
  R fd1E fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H
  R diskmap vscsi0 ch0 bio cuaa cuab cuac cuad ttya ttyb ttyc
- R ttyd audio0 audio1 audio2 pppx hotplug ptm local wscons uk0
- R random lkm tty00 tty01 tty02 tty03 apm pf systrace xd0 xd1
- R xd2 xd3 std st0 st1 fd
+ R ttyd audio0 audio1 audio2 fuse pppx hotplug ptm local wscons
+ R uk0 random lkm tty00 tty01 tty02 tty03 apm pf systrace xd0
+ R xd1 xd2 xd3 std st0 st1 fd
  ;;

 presto*|xd*|xy*|sd*)
Index: etc/etc.sparc/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.sparc/MAKEDEV.md,v
retrieving revision 1.50
diff -u -p -u -p -r1.50 MAKEDEV.md
--- etc/etc.sparc/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.50
+++ etc/etc.sparc/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -96,6 +96,7 @@ _DEV(bio, 124)
 _DEV(bpf, 105)
 _DEV(diskmap, 129)
 _DEV(fdesc, 24)
+_DEV(fuse, 82)
 _DEV(hotplug, 131)
 _DEV(lkm, 112)
 _DEV(oppr)
Index: etc/etc.sparc64/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.sparc64/MAKEDEV,v
retrieving revision 1.162
diff -u -p -u -p -r1.162 MAKEDEV
--- etc/etc.sparc64/MAKEDEV 12 Feb 2013 12:04:21 -0000 1.162
+++ etc/etc.sparc64/MAKEDEV 8 Mar 2013 15:40:42 -0000
@@ -82,6 +82,7 @@
 # crypto Hardware crypto access driver
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # hotplug devices hot plugging
 # lkm Loadable kernel modules interface
 # openprom PROM settings
@@ -325,6 +326,10 @@ hotplug)
  M hotplug c 124 $U 400
  ;;

+fuse)
+ M fuse$U c 134 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 24 $n;n=$(($n+1));done
@@ -638,10 +643,10 @@ all)
  R tun2 tun3 bio bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8
  R bpf9 pty0 fd1 fd1B fd1C fd1D fd1E fd1F fd1G fd1H fd0 fd0B
  R fd0C fd0D fd0E fd0F fd0G fd0H diskmap vscsi0 ch0 audio0
- R audio1 audio2 pppx hotplug ptm local wscons pci0 pci1 pci2
- R pci3 uall rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 rmidi5 rmidi6
- R rmidi7 video0 video1 uk0 random lpa0 lpa1 lpa2 lpt0 lpt1
- R lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 ttyh1 crypto pf
+ R audio1 audio2 fuse pppx hotplug ptm local wscons pci0 pci1
+ R pci2 pci3 uall rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 rmidi5
+ R rmidi6 rmidi7 video0 video1 uk0 random lpa0 lpa1 lpa2 lpt0
+ R lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 ttyh1 crypto pf
  R systrace wd0 wd1 wd2 wd3 std st0 st1 fd
  ;;

Index: etc/etc.sparc64/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.sparc64/MAKEDEV.md,v
retrieving revision 1.72
diff -u -p -u -p -r1.72 MAKEDEV.md
--- etc/etc.sparc64/MAKEDEV.md 12 Feb 2013 12:03:57 -0000 1.72
+++ etc/etc.sparc64/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -115,6 +115,7 @@ _DEV(bthub, 129)
 _DEV(cry, 75)
 _DEV(diskmap, 130)
 _DEV(fdesc, 24)
+_DEV(fuse, 134)
 _DEV(hotplug, 124)
 _DEV(lkm, 112)
 _DEV(oppr)
Index: etc/etc.vax/MAKEDEV
===================================================================
RCS file: /cvs/src/etc/etc.vax/MAKEDEV,v
retrieving revision 1.124
diff -u -p -u -p -r1.124 MAKEDEV
--- etc/etc.vax/MAKEDEV 30 Jan 2013 02:02:02 -0000 1.124
+++ etc/etc.vax/MAKEDEV 8 Mar 2013 15:40:42 -0000
@@ -4,7 +4,7 @@
 # generated from:
 #
 # OpenBSD: etc.vax/MAKEDEV.md,v 1.49 2012/08/23 06:15:28 deraadt Exp
-# OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+# OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 # OpenBSD: MAKEDEV.mi,v 1.81 2012/11/05 08:07:09 jasper Exp
 # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp
 #
@@ -62,6 +62,7 @@
 # bpf* Berkeley Packet Filter
 # diskmap Disk mapper
 # fd fd/* nodes
+# fuse Userland Filesystem
 # lkm Loadable kernel modules interface
 # pf* Packet Filter
 # pppx* PPP Multiplexer
@@ -283,6 +284,10 @@ lkm)
  M lkm c 28 0 640 _lkm
  ;;

+fuse)
+ M fuse$U c 82 $U 600
+ ;;
+
 fd)
  RMlist[${#RMlist[*]}]=";mkdir -p fd;rm -f" n=0
  while [ $n -lt 64 ];do M fd/$n c 53 $n;n=$(($n+1));done
@@ -468,9 +473,9 @@ local)
 all)
  R qsc0 dl0 dz0 dhu0 mt0 mt1 hd0 hd1 hd2 vnd0 sd0 sd1 sd2 sd3
  R cd0 tun0 tun1 bio bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7
- R pty0 diskmap vscsi0 ch0 audio0 pppx ptm local wscons uk0
- R random lkm pf systrace rx0 rx1 ra0 ra1 ra2 ra3 std st0 st1
- R fd
+ R pty0 diskmap vscsi0 ch0 audio0 fuse pppx ptm local wscons
+ R uk0 random lkm pf systrace rx0 rx1 ra0 ra1 ra2 ra3 std st0
+ R st1 fd
  ;;

 sd*|rx*|ra*|hd*)
Index: etc/etc.vax/MAKEDEV.md
===================================================================
RCS file: /cvs/src/etc/etc.vax/MAKEDEV.md,v
retrieving revision 1.49
diff -u -p -u -p -r1.49 MAKEDEV.md
--- etc/etc.vax/MAKEDEV.md 23 Aug 2012 06:15:28 -0000 1.49
+++ etc/etc.vax/MAKEDEV.md 8 Mar 2013 15:40:42 -0000
@@ -122,6 +122,7 @@ _DEV(bio, 72)
 _DEV(bpf, 56)
 _DEV(diskmap, 79)
 _DEV(fdesc, 53)
+_DEV(fuse, 82)
 _DEV(lkm, 28)
 _DEV(pf, 42)
 _DEV(pppx, 80)
Index: sbin/Makefile
===================================================================
RCS file: /cvs/src/sbin/Makefile,v
retrieving revision 1.97
diff -u -p -u -p -r1.97 Makefile
--- sbin/Makefile 23 Aug 2012 06:37:27 -0000 1.97
+++ sbin/Makefile 8 Mar 2013 15:40:47 -0000
@@ -5,7 +5,7 @@ SUBDIR= atactl badsect bioctl clri dhcli
  fsck_msdos fsdb fsirand growfs ifconfig iked init iopctl ipsecctl  \
  isakmpd kbd ldattach lmccontrol mknod modload modunload mount \
  mount_cd9660 mount_ext2fs mount_ffs mount_msdos \
- mount_nfs mount_ntfs mount_procfs mount_udf \
+ mount_nfs mount_ntfs mount_procfs mount_fusefs mount_udf \
  mount_vnd mountd ncheck_ffs newfs newfs_ext2fs newfs_msdos \
  nfsd nologin pdisk pfctl pflogd ping ping6 quotacheck \
  reboot restore route rtsol savecore scan_ffs \
Index: sbin/mount_fusefs/Makefile
===================================================================
RCS file: sbin/mount_fusefs/Makefile
diff -N sbin/mount_fusefs/Makefile
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sbin/mount_fusefs/Makefile 8 Mar 2013 15:40:47 -0000
@@ -0,0 +1,10 @@
+# $OpenBSD: src/sbin/mount_procfs/Makefile,v 1.7 2004/06/22 21:12:00
otto Exp $
+
+PROG= mount_fusefs
+SRCS= mount_fusefs.c getmntopts.c
+
+MOUNT= ${.CURDIR}/../mount
+CFLAGS+= -I${MOUNT}
+.PATH: ${MOUNT}
+
+.include <bsd.prog.mk>
Index: sbin/mount_fusefs/mount_fusefs.c
===================================================================
RCS file: sbin/mount_fusefs/mount_fusefs.c
diff -N sbin/mount_fusefs/mount_fusefs.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sbin/mount_fusefs/mount_fusefs.c 8 Mar 2013 15:40:47 -0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mntopts.h"
+
+const struct mntopt mopts[] = {
+ MOPT_STDOPTS,
+ { "subtype", 0, MFLAG_SET | MFLAG_STRVAL | MFLAG_OPT },
+ { "fsname", 0, MFLAG_SET | MFLAG_STRVAL | MFLAG_OPT },
+ { NULL }
+};
+
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, mntflags, altflags;
+ struct fusefs_args args;
+ char path[MAXPATHLEN];
+
+ mntflags = altflags = 0;
+ while ((ch = getopt(argc, argv, "o:")) != -1)
+ switch (ch) {
+ case 'o':
+ altflags |= getmntopts(optarg, mopts, &mntflags);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ args.flags = altflags;
+ args.fd = atoi(argv[0]);
+
+ if (realpath(argv[1], path) == NULL)
+ err(1, "realpath %s", argv[1]);
+
+ if (mount(MOUNT_FUSEFS, path, mntflags, &args)) {
+ if (errno == EOPNOTSUPP)
+ errx(1, "%s: Filesystem not supported by kernel",
+    argv[1]);
+ else
+ err(1, "%s", argv[1]);
+ }
+ exit(0);
+}
+
+__dead void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: mount_fusefs [-o options] fd mount_point\n");
+ exit(1);
+}
Index: share/man/man8/man8.alpha/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.alpha/MAKEDEV.8,v
retrieving revision 1.54
diff -u -p -u -p -r1.54 MAKEDEV.8
--- share/man/man8/man8.alpha/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.54
+++ share/man/man8/man8.alpha/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.54 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.alpha/MAKEDEV.md,v 1.55 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 alpha
 .Os
 .Sh NAME
@@ -220,6 +220,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.amd64/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.amd64/MAKEDEV.8,v
retrieving revision 1.57
diff -u -p -u -p -r1.57 MAKEDEV.8
--- share/man/man8/man8.amd64/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.57
+++ share/man/man8/man8.amd64/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.57 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.amd64/MAKEDEV.md,v 1.48 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 amd64
 .Os
 .Sh NAME
@@ -226,6 +226,9 @@ Direct Rendering Manager, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar gpio*
 General Purpose Input/Output, see
 .Xr gpio 4 .
Index: share/man/man8/man8.hp300/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.hp300/MAKEDEV.8,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 MAKEDEV.8
--- share/man/man8/man8.hp300/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.61
+++ share/man/man8/man8.hp300/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.61 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.hp300/MAKEDEV.md,v 1.45 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 hp300
 .Os
 .Sh NAME
@@ -182,6 +182,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.hppa/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.hppa/MAKEDEV.8,v
retrieving revision 1.51
diff -u -p -u -p -r1.51 MAKEDEV.8
--- share/man/man8/man8.hppa/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.51
+++ share/man/man8/man8.hppa/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.51 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.hppa/MAKEDEV.md,v 1.48 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 hppa
 .Os
 .Sh NAME
@@ -208,6 +208,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.hppa64/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.hppa64/MAKEDEV.8,v
retrieving revision 1.33
diff -u -p -u -p -r1.33 MAKEDEV.8
--- share/man/man8/man8.hppa64/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.33
+++ share/man/man8/man8.hppa64/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.33 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.hppa64/MAKEDEV.md,v 1.25 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 hppa64
 .Os
 .Sh NAME
@@ -205,6 +205,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar lkm
 Loadable kernel modules interface, see
 .Xr lkm 4 .
Index: share/man/man8/man8.i386/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.i386/MAKEDEV.8,v
retrieving revision 1.83
diff -u -p -u -p -r1.83 MAKEDEV.8
--- share/man/man8/man8.i386/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.83
+++ share/man/man8/man8.i386/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.83 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.i386/MAKEDEV.md,v 1.63 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 i386
 .Os
 .Sh NAME
@@ -229,6 +229,9 @@ Direct Rendering Manager, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar gpio*
 General Purpose Input/Output, see
 .Xr gpio 4 .
Index: share/man/man8/man8.landisk/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.landisk/MAKEDEV.8,v
retrieving revision 1.29
diff -u -p -u -p -r1.29 MAKEDEV.8
--- share/man/man8/man8.landisk/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.29
+++ share/man/man8/man8.landisk/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.29 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.landisk/MAKEDEV.md,v 1.27 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 landisk
 .Os
 .Sh NAME
@@ -194,6 +194,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.loongson/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.loongson/MAKEDEV.8,v
retrieving revision 1.14
diff -u -p -u -p -r1.14 MAKEDEV.8
--- share/man/man8/man8.loongson/MAKEDEV.8 23 Aug 2012 06:17:00 -0000 1.14
+++ share/man/man8/man8.loongson/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.14 2012/08/23 06:17:00 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.loongson/MAKEDEV.md,v 1.13 2012/08/23 06:15:28 deraadt
Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 loongson
 .Os
 .Sh NAME
@@ -201,6 +201,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.sgi/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.sgi/MAKEDEV.8,v
retrieving revision 1.46
diff -u -p -u -p -r1.46 MAKEDEV.8
--- share/man/man8/man8.sgi/MAKEDEV.8 23 Aug 2012 06:17:01 -0000 1.46
+++ share/man/man8/man8.sgi/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.46 2012/08/23 06:17:01 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.sgi/MAKEDEV.md,v 1.37 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 sgi
 .Os
 .Sh NAME
@@ -198,6 +198,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.socppc/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.socppc/MAKEDEV.8,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 MAKEDEV.8
--- share/man/man8/man8.socppc/MAKEDEV.8 6 Apr 2012 15:32:57 -0000 1.18
+++ share/man/man8/man8.socppc/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.18 2012/04/06 15:32:57 jsing Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
-.\" OpenBSD: etc.socppc/MAKEDEV.md,v 1.17 2012/04/06 15:18:41 jsing Exp
-.\" OpenBSD: MAKEDEV.common,v 1.59 2012/04/06 15:18:41 jsing Exp
+.\" OpenBSD: etc.socppc/MAKEDEV.md,v 1.18 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: April 6 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 socppc
 .Os
 .Sh NAME
@@ -189,6 +189,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.sparc/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.sparc/MAKEDEV.8,v
retrieving revision 1.60
diff -u -p -u -p -r1.60 MAKEDEV.8
--- share/man/man8/man8.sparc/MAKEDEV.8 23 Aug 2012 06:17:01 -0000 1.60
+++ share/man/man8/man8.sparc/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.60 2012/08/23 06:17:01 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.sparc/MAKEDEV.md,v 1.50 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 sparc
 .Os
 .Sh NAME
@@ -202,6 +202,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.sparc64/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.sparc64/MAKEDEV.8,v
retrieving revision 1.57
diff -u -p -u -p -r1.57 MAKEDEV.8
--- share/man/man8/man8.sparc64/MAKEDEV.8 19 Dec 2012 21:11:24 -0000 1.57
+++ share/man/man8/man8.sparc64/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.57 2012/12/19 21:11:24 kettenis Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
-.\" OpenBSD: etc.sparc64/MAKEDEV.md,v 1.71 2012/12/19 21:10:16 kettenis
Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: etc.sparc64/MAKEDEV.md,v 1.72 2013/02/12 12:03:57
ajacoutot Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: December 19 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 sparc64
 .Os
 .Sh NAME
@@ -243,6 +243,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar hotplug
 devices hot plugging, see
 .Xr hotplug 4 .
Index: share/man/man8/man8.vax/MAKEDEV.8
===================================================================
RCS file: /cvs/src/share/man/man8/man8.vax/MAKEDEV.8,v
retrieving revision 1.62
diff -u -p -u -p -r1.62 MAKEDEV.8
--- share/man/man8/man8.vax/MAKEDEV.8 23 Aug 2012 06:17:01 -0000 1.62
+++ share/man/man8/man8.vax/MAKEDEV.8 8 Mar 2013 15:40:47 -0000
@@ -1,10 +1,10 @@
-.\" $OpenBSD: MAKEDEV.8,v 1.62 2012/08/23 06:17:01 deraadt Exp $
+.\" $OpenBSD$
 .\"
 .\" THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
 .\" generated from:
 .\"
 .\" OpenBSD: etc.vax/MAKEDEV.md,v 1.49 2012/08/23 06:15:28 deraadt Exp
-.\" OpenBSD: MAKEDEV.common,v 1.60 2012/08/23 06:15:28 deraadt Exp
+.\" OpenBSD: MAKEDEV.common,v 1.61 2013/01/30 01:59:20 yasuoka Exp
 .\" OpenBSD: MAKEDEV.man,v 1.7 2009/03/18 17:34:25 sobrado Exp
 .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 23 2012 $
+.Dd $Mdocdate: March 18 2009 $
 .Dt MAKEDEV 8 vax
 .Os
 .Sh NAME
@@ -178,6 +178,9 @@ Disk mapper, see
 .It Ar fd
 fd/* nodes, see
 .Xr fd 4 .
+.It Ar fuse
+Userland Filesystem, see
+.Xr fuse 1 .
 .It Ar lkm
 Loadable kernel modules interface, see
 .Xr lkm 4 .
Index: sys/arch/alpha/alpha/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/alpha/alpha/conf.c,v
retrieving revision 1.69
diff -u -p -u -p -r1.69 conf.c
--- sys/arch/alpha/alpha/conf.c 23 Aug 2012 06:12:49 -0000 1.69
+++ sys/arch/alpha/alpha/conf.c 8 Mar 2013 15:40:47 -0000
@@ -132,6 +132,7 @@ cdev_decl(pci);
 #include "hotplug.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -206,6 +207,7 @@ struct cdevsw cdevsw[] =
  cdev_pppx_init(NPPPX,pppx), /* 64: pppx */
  cdev_urio_init(NURIO,urio), /* 65: USB Diamond Rio 500 */
  cdev_usbdev_init(NUSCANNER,uscanner), /* 66: USB scanners */
+ cdev_fuse_init(NFUSE,fuse), /* 67: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/amd64/amd64/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/conf.c,v
retrieving revision 1.39
diff -u -p -u -p -r1.39 conf.c
--- sys/arch/amd64/amd64/conf.c 2 Mar 2013 11:08:38 -0000 1.39
+++ sys/arch/amd64/amd64/conf.c 8 Mar 2013 15:40:47 -0000
@@ -181,6 +181,7 @@ cdev_decl(pci);
 #include "gpio.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -288,6 +289,7 @@ struct cdevsw cdevsw[] =
  cdev_vscsi_init(NVSCSI,vscsi), /* 89: vscsi */
  cdev_disk_init(1,diskmap), /* 90: disk mapper */
  cdev_pppx_init(NPPPX,pppx),     /* 91: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 92: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/hp300/hp300/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/hp300/hp300/conf.c,v
retrieving revision 1.54
diff -u -p -u -p -r1.54 conf.c
--- sys/arch/hp300/hp300/conf.c 23 Aug 2012 06:12:49 -0000 1.54
+++ sys/arch/hp300/hp300/conf.c 8 Mar 2013 15:40:47 -0000
@@ -111,6 +111,7 @@ cdev_decl(fd);
 #include "vscsi.h"
 #include "pppx.h"
 #include "hotplug.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -171,6 +172,7 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 54: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 55: pppx */
  cdev_hotplug_init(NHOTPLUG,hotplug), /* 56: devices hot plugging */
+ cdev_fuse_init(NFUSE,fuse), /* 57: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/hppa/hppa/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/hppa/hppa/conf.c,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 conf.c
--- sys/arch/hppa/hppa/conf.c 23 Aug 2012 06:12:49 -0000 1.55
+++ sys/arch/hppa/hppa/conf.c 8 Mar 2013 15:40:47 -0000
@@ -120,6 +120,7 @@ cdev_decl(pci);
 #include "uscanner.h"

 #include "bthub.h"
+#include "fuse.h"

 struct cdevsw   cdevsw[] =
 {
@@ -186,6 +187,7 @@ struct cdevsw   cdevsw[] =
  cdev_bthub_init(NBTHUB,bthub), /* 55: bthub */
  cdev_disk_init(1,diskmap), /* 56: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 57: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 58: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/hppa64/hppa64/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/hppa64/hppa64/conf.c,v
retrieving revision 1.22
diff -u -p -u -p -r1.22 conf.c
--- sys/arch/hppa64/hppa64/conf.c 23 Aug 2012 06:12:49 -0000 1.22
+++ sys/arch/hppa64/hppa64/conf.c 8 Mar 2013 15:40:47 -0000
@@ -120,6 +120,7 @@ cdev_decl(pci);
 #include "uscanner.h"

 #include "bthub.h"
+#include "fuse.h"

 struct cdevsw   cdevsw[] =
 {
@@ -186,6 +187,7 @@ struct cdevsw   cdevsw[] =
  cdev_bthub_init(NBTHUB,bthub), /* 55: bthub */
  cdev_disk_init(1,diskmap), /* 56: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 57: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 58: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/i386/i386/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/conf.c,v
retrieving revision 1.141
diff -u -p -u -p -r1.141 conf.c
--- sys/arch/i386/i386/conf.c 23 Aug 2012 06:12:49 -0000 1.141
+++ sys/arch/i386/i386/conf.c 8 Mar 2013 15:40:47 -0000
@@ -185,6 +185,7 @@ cdev_decl(pci);
 #include "amdmsr.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -293,6 +294,7 @@ struct cdevsw cdevsw[] =
  cdev_vscsi_init(NVSCSI,vscsi), /* 90: vscsi */
  cdev_disk_init(1,diskmap), /* 91: disk mapper */
  cdev_pppx_init(NPPPX,pppx),     /* 92: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 93: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/landisk/landisk/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/landisk/landisk/conf.c,v
retrieving revision 1.23
diff -u -p -u -p -r1.23 conf.c
--- sys/arch/landisk/landisk/conf.c 23 Aug 2012 06:12:49 -0000 1.23
+++ sys/arch/landisk/landisk/conf.c 8 Mar 2013 15:40:47 -0000
@@ -256,6 +256,7 @@ struct bdevsw bdevsw[] = {
 #include "scif.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] = {
  cdev_cn_init(1,cn), /*  0: virtual console */
@@ -365,6 +366,7 @@ struct cdevsw cdevsw[] = {
  cdev_bthub_init(NBTHUB,bthub), /* 100: bthub */
  cdev_disk_init(1,diskmap), /* 101: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 102: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 103: fuse */
 };

 int nblkdev = nitems(bdevsw);
Index: sys/arch/loongson/loongson/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/loongson/loongson/conf.c,v
retrieving revision 1.14
diff -u -p -u -p -r1.14 conf.c
--- sys/arch/loongson/loongson/conf.c 23 Aug 2012 06:12:49 -0000 1.14
+++ sys/arch/loongson/loongson/conf.c 8 Mar 2013 15:40:47 -0000
@@ -130,6 +130,7 @@ cdev_decl(pci);
 #include "bthub.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -210,6 +211,7 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 70: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 71: pppx */
  cdev_usbdev_init(NUSCANNER,uscanner), /* 72: USB scanners */
+ cdev_fuse_init(NFUSE,fuse), /* 73: fuse */
 };

 int nchrdev = nitems(cdevsw);
Index: sys/arch/sgi/sgi/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/conf.c,v
retrieving revision 1.31
diff -u -p -u -p -r1.31 conf.c
--- sys/arch/sgi/sgi/conf.c 23 Aug 2012 06:12:49 -0000 1.31
+++ sys/arch/sgi/sgi/conf.c 8 Mar 2013 15:40:47 -0000
@@ -130,6 +130,7 @@ cdev_decl(pci);

 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -210,6 +211,7 @@ struct cdevsw cdevsw[] =
  cdev_pppx_init(NPPPX,pppx), /* 70: pppx */
  cdev_notdef(), /* 71: */
  cdev_usbdev_init(NUSCANNER,uscanner), /* 72: USB scanners */
+ cdev_fuse_init(NFUSE,fuse), /* 73: fuse */
 };

 int nchrdev = nitems(cdevsw);
Index: sys/arch/socppc/socppc/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/socppc/socppc/conf.c,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 conf.c
--- sys/arch/socppc/socppc/conf.c 6 Apr 2012 15:10:40 -0000 1.16
+++ sys/arch/socppc/socppc/conf.c 8 Mar 2013 15:40:48 -0000
@@ -119,6 +119,7 @@ cdev_decl(pci);
 #include "vscsi.h"
 #include "pppx.h"
 #include "hotplug.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] = {
  cdev_cn_init(1,cn), /* 0: virtual console */
@@ -212,6 +213,7 @@ struct cdevsw cdevsw[] = {
  cdev_disk_init(1,diskmap), /* 82: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 83: pppx */
  cdev_hotplug_init(NHOTPLUG,hotplug), /* 84: devices hot plugging */
+ cdev_fuse_init(NFUSE,fuse), /* 85: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/sparc/sparc/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc/sparc/conf.c,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 conf.c
--- sys/arch/sparc/sparc/conf.c 23 Aug 2012 06:12:49 -0000 1.61
+++ sys/arch/sparc/sparc/conf.c 8 Mar 2013 15:40:48 -0000
@@ -124,6 +124,7 @@ int nblkdev = nitems(bdevsw);
 #include "vscsi.h"
 #include "pppx.h"
 #include "hotplug.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -214,7 +215,7 @@ struct cdevsw cdevsw[] =
  cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */
  cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */
  cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexer */
- cdev_notdef(), /* 82 */
+ cdev_fuse_init(NFUSE, fuse), /* 82: fuse */
  cdev_notdef(), /* 83 */
  cdev_notdef(), /* 84 */
  cdev_notdef(), /* 85 */
Index: sys/arch/sparc64/sparc64/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/sparc64/conf.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 conf.c
--- sys/arch/sparc64/sparc64/conf.c 8 Dec 2012 20:38:10 -0000 1.66
+++ sys/arch/sparc64/sparc64/conf.c 8 Mar 2013 15:40:48 -0000
@@ -117,6 +117,7 @@ cdev_decl(pci);
 #include "hotplug.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"

 struct bdevsw bdevsw[] =
 {
@@ -289,7 +290,8 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 130: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 131: pppx */
  cdev_gen_init(NVLDCP,vldcp), /* 132: vldcp */
- cdev_vdsp_init(NVDSP,vdsp) /* 133: vdsp */
+ cdev_vdsp_init(NVDSP,vdsp), /* 133: vdsp */
+ cdev_fuse_init(NFUSE,fuse), /* 134: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/arch/vax/vax/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/vax/vax/conf.c,v
retrieving revision 1.68
diff -u -p -u -p -r1.68 conf.c
--- sys/arch/vax/vax/conf.c 23 Aug 2012 06:12:49 -0000 1.68
+++ sys/arch/vax/vax/conf.c 8 Mar 2013 15:40:48 -0000
@@ -175,6 +175,7 @@ cdev_decl(dl);
 #include "vscsi.h"
 #include "pppx.h"
 #include "audio.h"
+#include "fuse.h"

 struct cdevsw cdevsw[] =
 {
@@ -260,6 +261,7 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 79: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 80: pppx */
  cdev_audio_init(NAUDIO,audio), /* 81: /dev/audio */
+ cdev_fuse_init(NFUSE,fuse), /* 82: fuse */
 };
 int nchrdev = nitems(cdevsw);

Index: sys/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/conf/GENERIC,v
retrieving revision 1.194
diff -u -p -u -p -r1.194 GENERIC
--- sys/conf/GENERIC 1 Mar 2013 21:06:04 -0000 1.194
+++ sys/conf/GENERIC 8 Mar 2013 15:40:48 -0000
@@ -45,6 +45,7 @@ option NFSSERVER # Network File System
 option CD9660 # ISO 9660 + Rock Ridge file system
 option UDF # UDF (DVD) file system
 option MSDOSFS # MS-DOS file system
+option FUSE # Userland file system
 option FIFO # FIFOs; RECOMMENDED

 option SOCKET_SPLICE # Socket Splicing for TCP
@@ -73,6 +74,8 @@ scsibus* at softraid?

 vscsi0 at root # Userland backed Virtual SCSI
 scsibus* at vscsi?
+
+pseudo-device fuse # filesystem in user land

 pseudo-device pf # packet filter
 pseudo-device pflog # pf log if
Index: sys/conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.540
diff -u -p -u -p -r1.540 files
--- sys/conf/files 21 Jan 2013 11:17:48 -0000 1.540
+++ sys/conf/files 8 Mar 2013 15:40:48 -0000
@@ -544,6 +544,14 @@ pseudo-device systrace
 pseudo-device ksyms
 file dev/ksyms.c ksyms needs-flag

+pseudo-device fuse
+file miscfs/fuse/fuse_device.c fuse needs-flag
+file miscfs/fuse/fuse_file.c fuse
+file miscfs/fuse/fuse_lookup.c fuse
+file miscfs/fuse/fuse_vfsops.c fuse
+file miscfs/fuse/fuse_vnops.c fuse
+file miscfs/fuse/fuse_subr.c fuse
+
 pseudo-device pf: ifnet
 file net/pf.c pf needs-flag
 file net/pf_norm.c pf
Index: sys/kern/vfs_init.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_init.c,v
retrieving revision 1.30
diff -u -p -u -p -r1.30 vfs_init.c
--- sys/kern/vfs_init.c 23 Aug 2012 06:12:49 -0000 1.30
+++ sys/kern/vfs_init.c 8 Mar 2013 15:40:48 -0000
@@ -85,6 +85,10 @@ extern  const struct vfsops ntfs_vfsops;
 extern  const struct vfsops udf_vfsops;
 #endif

+#ifdef FUSE
+extern const struct vfsops fusefs_vfsops;
+#endif
+
 /* Set up the filesystem operations for vnodes. */
 static struct vfsconf vfsconflist[] = {
 #ifdef FFS
@@ -121,6 +125,10 @@ static struct vfsconf vfsconflist[] = {

 #ifdef UDF
  { &udf_vfsops, MOUNT_UDF, 13, 0, MNT_LOCAL, NULL },
+#endif
+
+#ifdef FUSE
+ { &fusefs_vfsops, MOUNT_FUSEFS, 42, 0, MNT_LOCAL, NULL }, /* put 42 as
type, I don't know witch number I can use*/
 #endif
 };

Index: sys/miscfs/fuse/fuse_device.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_device.c
diff -N sys/miscfs/fuse/fuse_device.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_device.c 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,363 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/poll.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/fcntl.h>
+#include <sys/vnode.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#define FUSEUNIT(dev) (minor(dev))
+#ifdef FUSE_DEV_DEBUG
+#define DPRINTF(fmt, arg...) printf("fuse device: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+struct fuse_softc {
+ struct device sc_dev;
+ struct fuse_mnt *fmp;
+
+ int opened;
+ int end;
+};
+
+#define FUSE_OPEN 1
+#define FUSE_CLOSE 0
+#define FUSE_DONE 2
+
+struct fuse_softc *fuse_softc;
+int numfuse = 0;
+
+void fuseattach(int);
+int fuseopen(dev_t, int, int, struct proc *);
+int fuseclose(dev_t, int, int, struct proc *);
+int fuseioctl(dev_t, u_long, caddr_t, int, struct proc *);
+int fuseread(dev_t, struct uio *, int);
+int fusewrite(dev_t, struct uio *, int);
+int fusepoll(dev_t, int, struct proc *);
+
+struct fuse_msg_head fmq_in;
+struct fuse_msg_head fmq_wait;
+
+#ifdef FUSE_DEV_DEBUG
+static void
+dump_buff(char *buff, int len)
+{
+ char text[17];
+ int i;
+
+ bzero(text, 17);
+ for (i = 0; i < len ; i++) {
+
+ if (i != 0 && (i % 16) == 0) {
+ printf(": %s\n", text);
+ bzero(text, 17);
+ }
+
+ printf("%.2x ", buff[i] & 0xff);
+
+ if (buff[i] > ' ' && buff[i] < '~')
+ text[i%16] = buff[i] & 0xff;
+ else
+ text[i%16] = '.';
+ }
+
+ if ((i % 16) != 0) {
+ while ((i % 16) != 0) {
+ printf("   ");
+ i++;
+ }
+ }
+ printf(": %s\n", text);
+}
+#else
+#define dump_buff(x, y)
+#endif
+
+void
+fuseattach(int num)
+{
+ char *mem;
+ u_long size;
+ int i;
+
+ DPRINTF("attach %i devices\n", num);
+ if (num <= 0)
+ return;
+ size = num * sizeof(struct fuse_softc);
+ mem = malloc(size, M_FUSEFS, M_NOWAIT | M_ZERO);
+
+ if (mem == NULL) {
+ printf("WARNING: no memory for fuse device\n");
+ return;
+ }
+ fuse_softc = (struct fuse_softc *)mem;
+ for (i = 0; i < num; i++) {
+ struct fuse_softc *sc = &fuse_softc[i];
+
+ sc->sc_dev.dv_unit = i;
+ snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname),
+    "fuse%d", i);
+ device_ref(&sc->sc_dev);
+ }
+ numfuse = num;
+}
+
+int
+fuseopen(dev_t dev, int flags, int fmt, struct proc * p)
+{
+ int unit = FUSEUNIT(dev);
+ struct fuse_softc *sc;
+
+ if (unit >= numfuse)
+ return (ENXIO);
+ sc = &fuse_softc[unit];
+
+ if (sc->opened != FUSE_CLOSE)
+ return (ENXIO);
+
+ DPRINTF("open dev %i\n", unit);
+ sc->opened = FUSE_OPEN;
+
+ return (0);
+}
+
+int
+fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
+{
+ int unit = FUSEUNIT(dev);
+ struct fuse_softc *sc;
+
+ if (unit >= numfuse)
+ return (ENXIO);
+ sc = &fuse_softc[unit];
+
+ DPRINTF("close dev %i\n", unit);
+
+ if (sc->fmp) {
+ DPRINTF("libfuse close the device without umount\n");
+ VFS_UNMOUNT(sc->fmp->mp, MNT_FUSE_DOOMED, p);
+ }
+
+ sc->opened = FUSE_CLOSE;
+ return (0);
+}
+
+int
+fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
+{
+ int error = 0;
+
+ switch (cmd) {
+ default:
+ DPRINTF("bad ioctl number %d\n", cmd);
+ return (ENODEV);
+ }
+
+ return (error);
+}
+
+int
+fuseread(dev_t dev, struct uio *uio, int ioflag)
+{
+ int unit = FUSEUNIT(dev);
+ struct fuse_softc *sc;
+ struct fuse_msg *msg;
+ int error = 0;
+
+ if (unit >= numfuse)
+ return (ENXIO);
+ sc = &fuse_softc[unit];
+
+ DPRINTF("read 0x%x\n", dev);
+
+ if (sc->opened != FUSE_OPEN) {
+ return (ENODEV);
+ }
+
+again:
+ if (TAILQ_EMPTY(&fmq_in)) {
+
+ if (ioflag & O_NONBLOCK) {
+ DPRINTF("Return EAGAIN");
+ return (EAGAIN);
+ }
+
+ error = tsleep(&fmq_in, PWAIT, "fuse read", 0);
+
+ if (error)
+ return (error);
+ }
+ if (TAILQ_EMPTY(&fmq_in))
+ goto again;
+
+ if (!TAILQ_EMPTY(&fmq_in)) {
+ msg = TAILQ_FIRST(&fmq_in);
+
+ switch (msg->hdr->opcode) {
+ case FUSE_INIT:
+ DPRINTF("dev_t equals %x\n", dev);
+ sc->fmp = msg->fmp;
+ msg->fmp->dev = dev;
+ break;
+ case FUSE_DESTROY:
+ DPRINTF("catch done\n");
+ sc->opened = FUSE_DONE;
+ sc->fmp = NULL;
+ break;
+ default:
+ break;
+ }
+
+ error = uiomove(msg->hdr, sizeof(struct fuse_in_header), uio);
+
+ DPRINTF("hdr r:\n");
+ dump_buff((char *)msg->hdr, sizeof(struct fuse_in_header));
+
+ if (msg->len > 0) {
+ error = uiomove(msg->data, msg->len, uio);
+ DPRINTF("data r:\n");
+ dump_buff(msg->data, msg->len);
+ }
+
+ DPRINTF("msg send : %i\n", msg->len);
+
+ if (error) {
+ DPRINTF("error: %i\n", error);
+ return (error);
+ }
+
+ /*
+ * msg moves from a tailq to another
+ */
+ TAILQ_REMOVE(&fmq_in, msg, node);
+ TAILQ_INSERT_TAIL(&fmq_wait, msg, node);
+ }
+
+ return (error);
+}
+
+int
+fusewrite(dev_t dev, struct uio *uio, int ioflag)
+{
+ struct fuse_out_header hdr;
+ struct fuse_msg *msg;
+ int error = 0;
+ int caught = 0;
+ int len;
+ void *data;
+
+ DPRINTF("write %x bytes\n", uio->uio_resid);
+
+ if (uio->uio_resid < sizeof(struct fuse_out_header)) {
+ DPRINTF("uio goes wrong\n");
+ return (EINVAL);
+ }
+
+ /*
+ * get out header
+ */
+
+ if ((error = uiomove(&hdr, sizeof(struct fuse_out_header), uio)) != 0) {
+ DPRINTF("uiomove failed\n");
+ return (error);
+ }
+ DPRINTF("hdr w:\n");
+ dump_buff((char *)&hdr, sizeof(struct fuse_out_header));
+
+ /*
+ * check header validity
+ */
+ if (uio->uio_resid + sizeof(struct fuse_out_header) != hdr.len ||
+    (uio->uio_resid && hdr.error) || TAILQ_EMPTY(&fmq_wait) ) {
+ DPRINTF("corrupted fuse header or queue empty\n");
+ return (EINVAL);
+ }
+
+ /* fuse errno are negative */
+ if (hdr.error)
+ hdr.error = -(hdr.error);
+
+ TAILQ_FOREACH(msg, &fmq_wait, node) {
+ if (msg->hdr->unique == hdr.unique) {
+ DPRINTF("catch unique %i\n", msg->hdr->unique);
+ caught = 1;
+ break;
+ }
+ }
+
+ if (caught) {
+ if (uio->uio_resid > 0) {
+ len = uio->uio_resid;
+ data = malloc(len, M_FUSEFS, M_WAITOK);
+ error = uiomove(data, len, uio);
+
+ DPRINTF("data w:\n");
+ dump_buff(data, len);
+ } else {
+ data = NULL;
+ }
+
+ DPRINTF("call callback\n");
+
+ if (!error)
+ msg->cb(msg, &hdr, data);
+
+ TAILQ_REMOVE(&fmq_wait, msg, node);
+
+ if (msg->type == msg_buff_async) {
+ free(msg->hdr, M_FUSEFS);
+ free(msg, M_FUSEFS);
+
+ if (data)
+ free(data, M_FUSEFS);
+ }
+
+ } else {
+ error = EINVAL;
+ }
+
+ return (error);
+}
+
+int
+fusepoll(dev_t dev, int events, struct proc *p)
+{
+ int revents = 0;
+
+ DPRINTF("fuse poll\n");
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ if (!TAILQ_EMPTY(&fmq_in))
+ revents |= events & (POLLIN | POLLRDNORM);
+ }
+
+ if (events & (POLLOUT | POLLWRNORM))
+ revents |= events & (POLLOUT | POLLWRNORM);
+
+ return (revents);
+}
Index: sys/miscfs/fuse/fuse_file.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_file.c
diff -N sys/miscfs/fuse/fuse_file.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_file.c 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,123 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEV_DEBUG
+#define DPRINTF(fmt, arg...) printf("fuse vnop: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+int
+fuse_file_open(struct fuse_mnt *fmp, struct fuse_node *ip,
+    enum fufh_type fufh_type, int flags, int isdir, struct proc *p)
+{
+ struct fuse_open_out *open_out;
+ struct fuse_open_in open_in;
+ struct fuse_in_header hdr;
+ struct fuse_msg msg;
+ int error;
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.data = &open_in;
+ msg.len = sizeof(open_in);
+ msg.cb = &fuse_sync_resp;
+ msg.fmp = fmp;
+ msg.type = msg_buff;
+
+ open_in.flags = flags;
+ open_in.mode = 0;
+ msg.rep.buff.data_rcv = NULL;
+ msg.rep.buff.len = sizeof(*open_out);
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len,
+    ((isdir) ? FUSE_OPENDIR : FUSE_OPEN), ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse open", 0);
+
+ if (error)
+ return (error);
+
+ open_out = (struct fuse_open_out *)msg.rep.buff.data_rcv;
+
+ ip->fufh[fufh_type].fh_id = open_out->fh;
+ ip->fufh[fufh_type].fh_type = fufh_type;
+
+ free(open_out, M_FUSEFS);
+
+ return (0);
+}
+
+int
+fuse_file_close(struct fuse_mnt *fmp, struct fuse_node * ip,
+    enum fufh_type  fufh_type, int flags, int isdir, struct proc *p)
+{
+ struct fuse_release_in rel;
+ struct fuse_in_header hdr;
+ struct fuse_msg msg;
+ int error;
+
+ bzero(&msg, sizeof(msg));
+ bzero(&rel, sizeof(rel));
+ msg.hdr = &hdr;
+ msg.data = &rel;
+ msg.len = sizeof(rel);
+ msg.cb = &fuse_sync_it;
+ msg.fmp = fmp;
+ msg.type = msg_intr;
+
+ rel.fh  = ip->fufh[fufh_type].fh_id;
+ rel.flags = flags;
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len,
+    ((isdir) ? FUSE_RELEASEDIR : FUSE_RELEASE), ip->ufs_ino.i_number,
+    p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse close", 0);
+
+ if (error)
+ return (error);
+
+ error = msg.rep.it_res;
+ if (error)
+ printf("fuse file error %d\n", error);
+
+ ip->fufh[fufh_type].fh_id = (uint64_t)-1;
+ ip->fufh[fufh_type].fh_type = FUFH_INVALID;
+
+ return (error);
+}
Index: sys/miscfs/fuse/fuse_kernel.h
===================================================================
RCS file: sys/miscfs/fuse/fuse_kernel.h
diff -N sys/miscfs/fuse/fuse_kernel.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_kernel.h 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,234 @@
+/* $OpenBSD$ */
+/*
+    Copyright (C) 2012-2013 Sylvestre Gallon <[hidden email]>
+    Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+    ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY
+    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+#ifndef __FUSE_KERNEL_H__
+#define __FUSE_KERNEL_H__
+
+#define FUSE_KERNEL_VERSION 7
+#define FUSE_KERNEL_MINOR_VERSION 8
+
+/** The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+struct fuse_kstatfs {
+ uint64_t blocks;
+ uint64_t bfree;
+ uint64_t bavail;
+ uint64_t files;
+ uint64_t ffree;
+ uint32_t bsize;
+ uint32_t namelen;
+ uint32_t frsize;
+ uint32_t padding;
+ uint32_t spare[6];
+};
+
+enum fuse_opcode {
+ FUSE_LOOKUP = 1,
+ FUSE_FORGET = 2,  /* no reply */
+ FUSE_GETATTR = 3,
+ FUSE_SETATTR = 4,
+ FUSE_READLINK = 5,
+ FUSE_SYMLINK = 6,
+ FUSE_MKNOD = 8,
+ FUSE_MKDIR = 9,
+ FUSE_UNLINK = 10,
+ FUSE_RMDIR = 11,
+ FUSE_RENAME = 12,
+ FUSE_LINK = 13,
+ FUSE_OPEN = 14,
+ FUSE_READ = 15,
+ FUSE_WRITE = 16,
+ FUSE_STATFS = 17,
+ FUSE_RELEASE = 18,
+ FUSE_FSYNC = 20,
+ FUSE_SETXATTR = 21,
+ FUSE_GETXATTR = 22,
+ FUSE_LISTXATTR = 23,
+ FUSE_REMOVEXATTR = 24,
+ FUSE_FLUSH = 25,
+ FUSE_INIT = 26,
+ FUSE_OPENDIR = 27,
+ FUSE_READDIR = 28,
+ FUSE_RELEASEDIR = 29,
+ FUSE_FSYNCDIR = 30,
+ FUSE_GETLK = 31,
+ FUSE_SETLK = 32,
+ FUSE_SETLKW = 33,
+ FUSE_ACCESS = 34,
+ FUSE_CREATE = 35,
+ FUSE_INTERRUPT = 36,
+ FUSE_BMAP = 37,
+ FUSE_DESTROY = 38,
+};
+
+struct fuse_in_header {
+ uint32_t len;
+ uint32_t opcode;
+ uint64_t unique;
+ uint64_t nodeid;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t pid;
+ uint32_t padding;
+};
+
+struct fuse_init_in {
+ uint32_t major;
+ uint32_t minor;
+ uint32_t max_readahead;
+ uint32_t flags;
+};
+
+struct fuse_out_header {
+ uint32_t len;
+ uint32_t error;
+ uint64_t unique;
+};
+
+struct fuse_init_out {
+ uint32_t major;
+ uint32_t minor;
+ uint32_t max_readahead;
+ uint32_t flags;
+ uint32_t unused;
+ uint32_t max_write;
+};
+
+struct fuse_statfs_out {
+ struct fuse_kstatfs st;
+};
+
+struct fuse_attr {
+ uint64_t ino;
+ uint64_t size;
+ uint64_t blocks;
+ uint64_t atime;
+ uint64_t mtime;
+ uint64_t ctime;
+ uint32_t atimensec;
+ uint32_t mtimensec;
+ uint32_t ctimensec;
+ uint32_t mode;
+ uint32_t nlink;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t rdev;
+};
+
+struct fuse_attr_in {
+ uint32_t getattr_flags;
+ uint32_t dummy;
+ uint32_t fh;
+};
+
+struct fuse_attr_out {
+ uint64_t attr_valid;
+ uint32_t attr_valid_nsec;
+ uint32_t dummy;
+ struct fuse_attr attr;
+};
+
+struct fuse_access_in {
+ uint32_t mask;
+ uint32_t padding;
+};
+
+struct fuse_open_in {
+ uint32_t flags;
+ uint32_t mode;
+};
+
+struct fuse_open_out {
+ uint64_t fh;
+ uint32_t open_flags;
+ uint32_t padding;
+};
+
+struct fuse_release_in {
+ uint64_t fh;
+ uint32_t flags;
+ uint32_t release_flags;
+ uint64_t lock_owner;
+};
+
+struct fuse_read_in {
+ uint64_t fh;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t padding;
+};
+
+struct fuse_dirent {
+ uint64_t ino;
+ uint64_t off;
+ uint32_t namelen;
+ uint32_t type;
+ char name[0];
+};
+
+struct pseudo_dirent {
+ uint32_t d_namlen;
+};
+
+struct fuse_entry_out {
+ uint64_t nodeid;
+ uint64_t generation;
+
+ uint64_t entry_valid; /* Cache timeout for the name */
+ uint64_t attr_valid; /* Cache timeout for the attributes */
+ uint32_t entry_valid_nsec;
+ uint32_t attr_valid_nsec;
+ struct fuse_attr attr;
+};
+
+struct fuse_mkdir_in {
+ uint32_t mode;
+ uint32_t padding;
+};
+
+struct fuse_link_in {
+ uint64_t oldnodeid;
+};
+
+struct fuse_write_in {
+ uint64_t fh;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t write_flags;
+};
+
+struct fuse_write_out {
+ uint32_t size;
+ uint32_t padding;
+};
+
+#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
+#define FUSE_DIRENT_ALIGN(x) (((x)+sizeof(uint64_t)-1) &
~(sizeof(uint64_t)-1))
+#define FUSE_DIRENT_SIZE(d) \
+ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
+
+#endif /* __FUSEFS_H__ */
Index: sys/miscfs/fuse/fuse_lookup.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_lookup.c
diff -N sys/miscfs/fuse/fuse_lookup.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_lookup.c 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,212 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/dirent.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG_VNOP
+#define DPRINTF(fmt, arg...) printf("fuse vnop: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+extern int fusefs_lookup(void *);
+
+int
+fusefs_lookup(void *v)
+{
+ struct vop_lookup_args *ap = v;
+ struct vnode *vdp; /* vnode for directory being searched */
+ struct fuse_node *dp; /* inode for directory being searched */
+ struct fuse_mnt *fmp; /* file system that directory is in */
+ int lockparent; /* 1 => lockparent flag is set */
+ struct vnode *tdp; /* returned by VOP_VGET */
+ struct fuse_in_header hdr;
+ struct fuse_msg msg;
+ struct vnode **vpp = ap->a_vpp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct ucred *cred = cnp->cn_cred;
+ struct fuse_entry_out *feo = NULL;
+ int flags;
+ int nameiop = cnp->cn_nameiop;
+ /*struct proc *p = cnp->cn_proc;*/
+ int error = 0;
+ uint64_t nid;
+
+ flags = cnp->cn_flags;
+ *vpp = NULL;
+ vdp = ap->a_dvp;
+ dp = VTOI(vdp);
+ fmp = (struct fuse_mnt *)dp->ufs_ino.i_ump;
+ lockparent = flags & LOCKPARENT;
+
+ DPRINTF("lookup path %s\n", cnp->cn_pnbuf);
+ DPRINTF("lookup file %s\n", cnp->cn_nameptr);
+
+ if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0)
+ return (error);
+
+ if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
+    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+ return (EROFS);
+
+ if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
+ return (error);
+
+ if (flags & ISDOTDOT) {
+ /* got ".." */
+ nid = dp->parent;
+ if (nid == 0) {
+ return (ENOENT);
+ }
+ } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
+ /* got "." */
+ nid = dp->ufs_ino.i_number;
+ } else {
+ /* got a real entry */
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = cnp->cn_namelen + 1;
+
+ msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+ memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+ ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+ msg.type = msg_buff;
+ msg.rep.buff.len = 0;
+ msg.rep.buff.data_rcv = NULL;
+ msg.cb = &fuse_sync_resp;
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_LOOKUP,
+    dp->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse lookup", 0);
+
+ if (error)
+ return (error);
+
+ if (msg.error) {
+ if ((nameiop == CREATE || nameiop == RENAME) &&
+    (flags & ISLASTCN) ) {
+ if (vdp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+
+ cnp->cn_flags |= SAVENAME;
+
+ if (!lockparent) {
+ VOP_UNLOCK(vdp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+
+ error = EJUSTRETURN;
+ goto out;
+ }
+
+ error = ENOENT;
+ goto out;
+ }
+
+ feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+ nid = feo->nodeid;
+ }
+
+ if (nameiop == DELETE && (flags & ISLASTCN)) {
+ /*
+ * Write access to directory required to delete files.
+ */
+ if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0)
+ return (error);
+
+ cnp->cn_flags |= SAVENAME;
+ }
+
+ if (flags & ISDOTDOT) {
+ DPRINTF("lookup for ..\n");
+ VOP_UNLOCK(vdp, 0, p); /* race to get the inode */
+ cnp->cn_flags |= PDIRUNLOCK;
+
+ error = VFS_VGET(fmp->mp, nid, &tdp);
+
+ if (error) {
+ if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
+ cnp->cn_flags &= ~PDIRUNLOCK;
+
+ return (error);
+ }
+
+ if (lockparent && (flags & ISLASTCN)) {
+ if ((error = vn_lock(vdp, LK_EXCLUSIVE, p))) {
+ vput(tdp);
+ return (error);
+ }
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ }
+ *vpp = tdp;
+
+ } else if (nid == dp->ufs_ino.i_number) {
+ vref(vdp);
+ *vpp = vdp;
+ error = 0;
+ } else {
+ error = VFS_VGET(fmp->mp, nid, &tdp);
+
+ if (!error) {
+ tdp->v_type = IFTOVT(feo->attr.mode);
+ VTOI(tdp)->vtype = tdp->v_type;
+ }
+
+ fuse_internal_attr_fat2vat(fmp->mp, &feo->attr,
+    &(VTOI(tdp)->cached_attrs));
+ free(feo, M_FUSEFS);
+
+ if (error)
+ return (error);
+
+ if (vdp != NULL && vdp->v_type == VDIR) {
+ VTOI(tdp)->parent = dp->ufs_ino.i_number;
+ }
+ if (!lockparent || !(flags & ISLASTCN)) {
+ VOP_UNLOCK(vdp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+
+ *vpp = tdp;
+ }
+
+out:
+ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE &&
+    nameiop != DELETE )
+ cache_enter(vdp, *vpp, cnp);
+
+ return (error);
+}
Index: sys/miscfs/fuse/fuse_node.h
===================================================================
RCS file: sys/miscfs/fuse/fuse_node.h
diff -N sys/miscfs/fuse/fuse_node.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_node.h 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,64 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FUSE_NODE_H__
+#define __FUSE_NODE_H__
+
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <ufs/ufs/ufs_extern.h>
+
+enum fufh_type {
+ FUFH_INVALID = -1,
+ FUFH_RDONLY  = 0,
+ FUFH_WRONLY  = 1,
+ FUFH_RDWR    = 2,
+ FUFH_MAXTYPE = 3,
+};
+
+struct fuse_filehandle {
+ uint64_t fh_id;
+ enum fufh_type fh_type;
+};
+
+struct fuse_node {
+ struct inode ufs_ino;
+
+ /* fd of fuse session and parent ino_t*/
+ uint64_t parent;
+
+ /** I/O **/
+ struct     fuse_filehandle fufh[FUFH_MAXTYPE];
+
+ /** meta **/
+ struct vattr      cached_attrs;
+ off_t             filesize;
+ uint64_t          nlookup;
+ enum vtype        vtype;
+};
+
+#ifdef ITOV
+# undef ITOV
+#endif
+#define ITOV(ip) ((ip)->ufs_ino.i_vnode)
+
+#ifdef VTOI
+# undef VTOI
+#endif
+#define VTOI(vp) ((struct fuse_node *)(vp)->v_data)
+
+#endif /* __FUSE_NODE_H__ */
Index: sys/miscfs/fuse/fuse_subr.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_subr.c
diff -N sys/miscfs/fuse/fuse_subr.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_subr.c 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,140 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG_MSG
+#define DPRINTF(fmt, arg...) printf("fuse ipc: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+void
+fuse_make_in(struct mount *mp, struct fuse_in_header *hdr, int len,
+    enum fuse_opcode op, ino_t ino, struct proc *p)
+{
+ struct fuse_mnt *fmp;
+
+ fmp = VFSTOFUSEFS(mp);
+ fmp->unique++;
+
+ hdr->len = sizeof(*hdr) + len;
+ hdr->opcode = op;
+ hdr->nodeid = ino;
+ hdr->unique = fmp->unique;
+
+ DPRINTF("create unique %i\n", hdr->unique);
+
+ if (!p) {
+ hdr->pid = curproc->p_pid;
+ hdr->uid = 0;
+ hdr->gid = 0;
+ } else {
+ hdr->pid = p->p_pid;
+ hdr->uid = p->p_cred->p_ruid;
+ hdr->gid = p->p_cred->p_rgid;
+ }
+}
+
+void
+fuse_init_resp(struct fuse_msg *msg, struct fuse_out_header *hdr, void
*data)
+{
+ struct fuse_init_out *out = data;
+
+ DPRINTF("async init unique %i\n", msg->hdr->unique);
+ DPRINTF("init_out flags %i\n", out->flags);
+ DPRINTF("init_out major %i\n", out->major);
+ DPRINTF("init_out minor %i\n", out->minor);
+ DPRINTF("init_out max_readahead %i\n", out->max_readahead);
+ DPRINTF("init_out max_write %i\n", out->max_write);
+ DPRINTF("init_out unused %i\n", out->unused);
+
+ msg->fmp->sess_init = 1;
+ msg->fmp->max_write = out->max_readahead;
+}
+
+void
+fuse_sync_resp(struct fuse_msg *msg, struct fuse_out_header *hdr, void
*data)
+{
+ size_t len;
+
+ DPRINTF("unique %i\n", msg->hdr->unique);
+
+ if (msg->type != msg_buff)
+ DPRINTF("bad msg type\n");
+
+ if (data != NULL && msg->rep.buff.len != 0) {
+ len = hdr->len - sizeof(*hdr);
+ if (msg->rep.buff.len != len) {
+ DPRINTF("fusefs: packet size error on opcode %i\n",
+    msg->hdr->opcode);
+ }
+
+ if (msg->rep.buff.len > len)
+ printf("unused byte : 0x%x\n", msg->rep.buff.len - len);
+
+ msg->rep.buff.data_rcv = malloc(msg->rep.buff.len,  M_FUSEFS,
+    M_WAITOK | M_ZERO);
+ memcpy(msg->rep.buff.data_rcv, data, msg->rep.buff.len);
+
+ wakeup(msg);
+
+ } else if (data != NULL) {
+ len = hdr->len - sizeof(*hdr);
+ msg->rep.buff.data_rcv = malloc(len,  M_FUSEFS,
+    M_WAITOK | M_ZERO);
+ memcpy(msg->rep.buff.data_rcv, data, len);
+ msg->rep.buff.len = len;
+
+ wakeup(msg);
+ } else if (hdr->error) {
+ msg->error = hdr->error;
+ DPRINTF("error %i\n", msg->error);
+ wakeup(msg);
+ } else {
+ msg->error = -1;
+ DPRINTF("ack for msg\n");
+ wakeup(msg);
+ }
+}
+
+void
+fuse_sync_it(struct fuse_msg *msg, struct fuse_out_header *hdr, void *data)
+{
+ DPRINTF("unique %i\n", msg->hdr->unique);
+
+ if (msg->type != msg_intr)
+ printf("bad msg type\n");
+
+ if (data != NULL)
+ printf("normally data should be Null\n");
+
+ msg->rep.it_res = hdr->error;
+ DPRINTF("errno = %d\n", msg->rep.it_res);
+ wakeup(msg);
+}
Index: sys/miscfs/fuse/fuse_vfsops.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_vfsops.c
diff -N sys/miscfs/fuse/fuse_vfsops.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_vfsops.c 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,399 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/lock.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG_VFS
+#define DPRINTF(fmt, arg...) printf("fuse vfsop: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+int fusefs_mount(struct mount *, const char *, void *, struct nameidata *,
+    struct proc *);
+int fusefs_start(struct mount *, int, struct proc *);
+int fusefs_unmount(struct mount *, int, struct proc *);
+int fusefs_root(struct mount *, struct vnode **);
+int fusefs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *);
+int fusefs_statfs(struct mount *, struct statfs *, struct proc *);
+int fusefs_sync(struct mount *, int, struct ucred *, struct proc *);
+int fusefs_vget(struct mount *, ino_t, struct vnode **);
+int fusefs_fhtovp(struct mount *, struct fid *, struct vnode **);
+int fusefs_vptofh(struct vnode *, struct fid *);
+int fusefs_init(struct vfsconf *);
+int fusefs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
+    struct proc *);
+int fusefs_checkexp(struct mount *, struct mbuf *, int *,
+    struct ucred **);
+
+const struct vfsops fusefs_vfsops = {
+ fusefs_mount,
+ fusefs_start,
+ fusefs_unmount,
+ fusefs_root,
+ fusefs_quotactl,
+ fusefs_statfs,
+ fusefs_sync,
+ fusefs_vget,
+ fusefs_fhtovp,
+ fusefs_vptofh,
+ fusefs_init,
+ fusefs_sysctl,
+ fusefs_checkexp
+};
+
+int
+fusefs_mount(struct mount *mp, const char *path, void *data,
+    struct nameidata *ndp, struct proc *p)
+{
+ struct fuse_mnt *fmp;
+ struct fuse_msg *msg;
+ struct fuse_init_in *init;
+ struct fusefs_args args;
+ int error;
+
+ DPRINTF("mount\n");
+
+ if (mp->mnt_flag & MNT_UPDATE)
+ return (EOPNOTSUPP);
+
+ error = copyin(data, &args, sizeof(struct fusefs_args));
+ if (error)
+ return (error);
+
+ DPRINTF("fd = %d\n", args.fd);
+
+ fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO);
+ fmp->mp = mp;
+ fmp->sess_init = 0;
+ fmp->unique = 0;
+ mp->mnt_data = (qaddr_t)fmp;
+
+ mp->mnt_flag |= MNT_LOCAL;
+ vfs_getnewfsid(mp);
+
+ bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
+ strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
+ bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
+ bcopy("fusefs", mp->mnt_stat.f_mntfromname, sizeof("fusefs"));
+
+ msg = malloc(sizeof(struct fuse_msg), M_FUSEFS, M_WAITOK | M_ZERO);
+ msg->hdr = malloc(sizeof(struct fuse_in_header), M_FUSEFS,
+    M_WAITOK | M_ZERO);
+ init = malloc(sizeof(struct fuse_init_in), M_FUSEFS, M_WAITOK | M_ZERO);
+
+ init->major = FUSE_KERNEL_VERSION;
+ init->minor = FUSE_KERNEL_MINOR_VERSION;
+ init->max_readahead = 4096 * 16;
+ init->flags = 0;
+ msg->data = init;
+ msg->len = sizeof(*init);
+ msg->cb = &fuse_init_resp;
+ msg->fmp = fmp;
+ msg->type = msg_buff_async;
+
+ fuse_make_in(mp, msg->hdr, msg->len, FUSE_INIT, 0, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, msg, node);
+ wakeup(&fmq_in);
+
+ return (0);
+}
+
+int
+fusefs_start(struct mount *mp, int flags, struct proc *p)
+{
+ DPRINTF("start\n");
+ return (0);
+}
+
+int
+fusefs_unmount(struct mount *mp, int mntflags, struct proc *p)
+{
+ struct fuse_in_header hdr;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ extern int doforce;
+ struct fuse_msg *m;
+ int flags = 0;
+ int error;
+
+ fmp = VFSTOFUSEFS(mp);
+
+ if (!fmp->sess_init)
+ return (0);
+
+ fmp->sess_init = 0;
+
+ DPRINTF("unmount\n");
+ if (!(mntflags & MNT_FUSE_DOOMED)) {
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = 0;
+ msg.type = msg_intr;
+ msg.data = NULL;
+ msg.cb = &fuse_sync_it;
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_DESTROY, 0, p);
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse unmount", 0);
+
+ if (error)
+ return (error);
+
+ error = msg.rep.it_res;
+
+ if (error)
+ DPRINTF("error from fuse\n");
+ }
+
+ /* clear FIFO IN*/
+ while ((m = TAILQ_FIRST(&fmq_in))) {
+ DPRINTF("warning some msg where not processed....\n");
+ }
+
+ /* clear FIFO WAIT*/
+ while ((m = TAILQ_FIRST(&fmq_wait))) {
+ DPRINTF("warning some msg where not processed....\n");
+ }
+
+ if (mntflags & MNT_FORCE) {
+ /* fusefs can never be rootfs so don't check for it */
+ if (!doforce)
+ return (EINVAL);
+ flags |= FORCECLOSE;
+ }
+
+ if ((error = vflush(mp, 0, flags)))
+ return (error);
+
+ free(fmp, M_FUSEFS);
+
+ return (error);
+}
+
+int
+fusefs_root(struct mount *mp, struct vnode **vpp)
+{
+ struct vnode *nvp;
+ struct fuse_node *ip;
+ int error;
+
+ DPRINTF("root\n");
+
+ if ((error = VFS_VGET(mp, (ino_t)FUSE_ROOTINO, &nvp)) != 0)
+ return (error);
+
+ ip = VTOI(nvp);
+ nvp->v_type = VDIR;
+ ip->vtype = VDIR;
+
+ *vpp = nvp;
+ return (0);
+}
+
+int fusefs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
+    struct proc *p)
+{
+ DPRINTF("quotactl\n");
+ return (0);
+}
+
+int fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
+{
+ struct fuse_statfs_out *stat;
+ struct fuse_in_header hdr;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ int error;
+
+ DPRINTF("statfs\n");
+
+ fmp = VFSTOFUSEFS(mp);
+
+ if (fmp->sess_init) {
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = 0;
+ msg.data = NULL;
+ msg.rep.buff.data_rcv = NULL;
+ msg.rep.buff.len = sizeof(*stat);
+ msg.cb = &fuse_sync_resp;
+ msg.type = msg_buff;
+
+ fuse_make_in(mp, msg.hdr, msg.len, FUSE_STATFS, FUSE_ROOT_ID,
+    NULL);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse stat", 0);
+ if (error) {
+ if (msg.rep.buff.data_rcv)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ return (error);
+ }
+
+ stat = (struct fuse_statfs_out *)msg.rep.buff.data_rcv;
+
+ DPRINTF("statfs a: %i\n", stat->st.bavail);
+ DPRINTF("statfs a: %i\n", stat->st.bfree);
+ DPRINTF("statfs a: %i\n", stat->st.blocks);
+ DPRINTF("statfs a: %i\n", stat->st.bsize);
+ DPRINTF("statfs a: %i\n", stat->st.ffree);
+ DPRINTF("statfs a: %i\n", stat->st.files);
+ DPRINTF("statfs a: %i\n", stat->st.frsize);
+ DPRINTF("statfs a: %i\n", stat->st.namelen);
+ DPRINTF("statfs a: %i\n", stat->st.padding);
+
+ sbp->f_bavail = stat->st.bavail;
+ sbp->f_bfree = stat->st.bfree;
+ sbp->f_blocks = stat->st.blocks;
+ sbp->f_ffree = stat->st.ffree;
+ sbp->f_files = stat->st.files;
+ sbp->f_bsize = stat->st.frsize;
+ sbp->f_namemax = stat->st.namelen;
+
+ free(stat, M_FUSEFS);
+ } else {
+ sbp->f_bavail = 0;
+ sbp->f_bfree = 0;
+ sbp->f_blocks = 0;
+ sbp->f_ffree = 0;
+ sbp->f_files = 0;
+ sbp->f_bsize = 0;
+ sbp->f_namemax = 0;
+ }
+
+ return (0);
+}
+
+int fusefs_sync(struct mount *mp, int waitfor, struct ucred *cred,
+    struct proc *p)
+{
+ DPRINTF("sync\n");
+ return (0);
+}
+
+int fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
+{
+ struct fuse_mnt *fmp;
+ struct fuse_node *ip;
+ struct vnode *nvp;
+ int i;
+ int error;
+
+ DPRINTF("vget\n");
+
+retry:
+ fmp = VFSTOFUSEFS(mp);
+ /*
+ * check if vnode is in hash.
+ */
+ if ((*vpp = ufs_ihashget(fmp->dev, ino)) != NULLVP)
+ return (0);
+
+ /*
+ * if not create it
+ */
+ if ((error = getnewvnode(VT_FUSEFS, mp, &fusefs_vops, &nvp)) != 0) {
+ DPRINTF("getnewvnode error\n");
+ *vpp = NULLVP;
+ return (error);
+ }
+
+ ip = malloc(sizeof(*ip), M_FUSEFS, M_WAITOK | M_ZERO);
+ lockinit(&ip->ufs_ino.i_lock, PINOD, "fuseinode", 0, 0);
+ nvp->v_data = ip;
+ ip->ufs_ino.i_vnode = nvp;
+ ip->ufs_ino.i_dev = fmp->dev;
+ ip->ufs_ino.i_number = ino;
+ ip->parent = 0;
+
+ for (i = 0; i < FUFH_MAXTYPE; i++)
+ ip->fufh[i].fh_type = FUFH_INVALID;
+
+ error = ufs_ihashins(&ip->ufs_ino);
+ if (error) {
+ vrele(nvp);
+
+ if (error == EEXIST)
+ goto retry;
+
+ return (error);
+ }
+
+ ip->ufs_ino.i_ump = (struct ufsmount *)fmp;
+
+ if (ino == FUSE_ROOTINO)
+ nvp->v_flag |= VROOT;
+
+ *vpp = nvp;
+
+ return (0);
+}
+
+int fusefs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
+{
+ DPRINTF("fhtovp\n");
+ return (0);
+}
+
+int fusefs_vptofh(struct vnode *vp, struct fid *fhp)
+{
+ DPRINTF("vptofh\n");
+ return (0);
+}
+
+int fusefs_init(struct vfsconf *vfc)
+{
+ DPRINTF("init\n");
+
+ TAILQ_INIT(&fmq_in);
+ TAILQ_INIT(&fmq_wait);
+
+ return (0);
+}
+
+int fusefs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldplen,
+    void *newp, size_t newlen, struct proc *p)
+{
+ DPRINTF("sysctl\n");
+ return (0);
+}
+
+int fusefs_checkexp(struct mount *mp, struct mbuf *nam, int *extflagsp,
+    struct ucred **credanonp)
+{
+ DPRINTF("checkexp\n");
+ return (0);
+}
Index: sys/miscfs/fuse/fuse_vnops.c
===================================================================
RCS file: sys/miscfs/fuse/fuse_vnops.c
diff -N sys/miscfs/fuse/fuse_vnops.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fuse_vnops.c 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,1341 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/dirent.h>
+#include <sys/specdev.h>
+#include <sys/poll.h>
+#include <sys/lockf.h>
+
+#include "fuse_kernel.h"
+#include "fuse_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG_VNOP
+#define DPRINTF(fmt, arg...) printf("fuse vnop: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+
+/*
+ * Prototypes for fusefs vnode ops
+ */
+extern int fusefs_lookup(void *);
+int fusefs_open(void *);
+int fusefs_close(void *);
+int fusefs_access(void *);
+int fusefs_getattr(void *);
+int fusefs_setattr(void *);
+int fusefs_ioctl(void *);
+int fusefs_link(void *);
+int fusefs_symlink(void *);
+int fusefs_readdir(void *);
+int fusefs_readlink(void *);
+int fusefs_inactive(void *);
+int fusefs_reclaim(void *);
+int fusefs_print(void *);
+int fusefs_create(void *);
+int fusefs_mknod(void *);
+int fusefs_read(void *);
+int fusefs_write(void *);
+int fusefs_poll(void *);
+int fusefs_fsync(void *);
+int fusefs_remove(void *);
+int fusefs_rename(void *);
+int fusefs_mkdir(void *);
+int fusefs_rmdir(void *);
+int fusefs_strategy(void *);
+int fusefs_lock(void *);
+int fusefs_unlock(void *);
+int fusefs_islocked(void *);
+int fusefs_advlock(void *);
+int readdir_process_data(void *buff, int len, struct uio *uio);
+
+struct vops fusefs_vops = {
+ .vop_lookup = fusefs_lookup,
+ .vop_create = fusefs_create,
+ .vop_mknod = fusefs_mknod,
+ .vop_open = fusefs_open,
+ .vop_close = fusefs_close,
+ .vop_access = fusefs_access,
+ .vop_getattr = fusefs_getattr,
+ .vop_setattr = fusefs_setattr,
+ .vop_read = fusefs_read,
+ .vop_write = fusefs_write,
+ .vop_ioctl = fusefs_ioctl,
+ .vop_poll = fusefs_poll,
+ .vop_fsync = fusefs_fsync,
+ .vop_remove = fusefs_remove,
+ .vop_link = fusefs_link,
+ .vop_rename = fusefs_rename,
+ .vop_mkdir = fusefs_mkdir,
+ .vop_rmdir = fusefs_rmdir,
+ .vop_symlink = fusefs_symlink,
+ .vop_readdir = fusefs_readdir,
+ .vop_readlink = fusefs_readlink,
+ .vop_abortop = vop_generic_abortop,
+ .vop_inactive = fusefs_inactive,
+ .vop_reclaim = fusefs_reclaim,
+ .vop_lock = fusefs_lock,
+ .vop_unlock = fusefs_unlock,
+ .vop_bmap = vop_generic_bmap,
+ .vop_strategy = fusefs_strategy,
+ .vop_print = fusefs_print,
+ .vop_islocked = fusefs_islocked,
+ .vop_pathconf = spec_pathconf,
+ .vop_advlock = fusefs_advlock,
+};
+
+
+void
+fuse_internal_attr_fat2vat(struct mount *mp,
+                           struct fuse_attr *fat,
+                           struct vattr *vap)
+{
+ vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
+ vap->va_fileid = fat->ino;/* XXX cast from 64 bits to 32 */
+ vap->va_mode = fat->mode & ~S_IFMT;
+ vap->va_nlink = fat->nlink;
+ vap->va_uid = fat->uid;
+ vap->va_gid = fat->gid;
+ vap->va_rdev = fat->rdev;
+ vap->va_size = fat->size;
+ vap->va_atime.tv_sec = fat->atime;
+ vap->va_atime.tv_nsec = fat->atimensec;
+ vap->va_mtime.tv_sec = fat->mtime;
+ vap->va_mtime.tv_nsec = fat->mtimensec;
+ vap->va_ctime.tv_sec = fat->ctime;
+ vap->va_ctime.tv_nsec = fat->ctimensec;
+ vap->va_blocksize = PAGE_SIZE;
+ vap->va_type = IFTOVT(fat->mode);
+
+#if (S_BLKSIZE == 512)
+ /* Optimize this case */
+ vap->va_bytes = fat->blocks << 9;
+#else
+ vap->va_bytes = fat->blocks * S_BLKSIZE;
+#endif
+
+}
+
+int
+fusefs_open(void *v)
+{
+ struct vop_open_args *ap;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ enum fufh_type fufh_type;
+ int flags;
+ int error;
+ int isdir;
+
+ DPRINTF("fusefs_open\n");
+
+ ap = v;
+ ip = VTOI(ap->a_vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init) {
+ return (0);
+ }
+
+ DPRINTF("inode = %i mode=0x%x\n", ip->ufs_ino.i_number, ap->a_mode);
+
+ isdir = 0;
+ if (ip->vtype == VDIR) {
+ fufh_type = FUFH_RDONLY;
+ flags = O_RDONLY;
+ isdir = 1;
+ } else {
+ if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) {
+ fufh_type = FUFH_RDWR;
+ flags = O_RDWR;
+ } else if (ap->a_mode  & (FWRITE)) {
+ fufh_type = FUFH_WRONLY;
+ flags = O_WRONLY;
+ } else if (ap->a_mode & (FREAD)) {
+ fufh_type = FUFH_RDONLY;
+ flags = O_RDONLY;
+ }
+ }
+
+ /* already open i think all is ok */
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+ return (0);
+
+ error = fuse_file_open(fmp, ip, fufh_type, flags, isdir, ap->a_p);
+
+ if (error)
+ return (error);
+
+ DPRINTF("file open fd : %i\n", ip->fufh[fufh_type].fh_id);
+
+ return (error);
+}
+
+int
+fusefs_close(void *v)
+{
+ struct vop_close_args *ap;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ enum fufh_type fufh_type;
+ int isdir, flags, i;
+
+ DPRINTF("fusefs_close\n");
+
+ ap = v;
+ ip = VTOI(ap->a_vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init) {
+ return (0);
+ }
+
+ isdir = 0;
+ if (ip->vtype == VDIR) {
+ fufh_type = FUFH_RDONLY;
+ isdir = 1;
+
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+ return (fuse_file_close(fmp, ip, fufh_type, O_RDONLY,
+    isdir, ap->a_p));
+ } else {
+ if (ap->a_fflag & IO_NDELAY) {
+ return (0);
+ }
+
+ if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE)) {
+ fufh_type = FUFH_RDWR;
+ flags = O_RDWR;
+ } else if (ap->a_fflag  & (FWRITE)) {
+ fufh_type = FUFH_WRONLY;
+ flags = O_WRONLY;
+ } else if (ap->a_fflag & (FREAD)) {
+ fufh_type = FUFH_RDONLY;
+ flags = O_RDONLY;
+ }
+ }
+
+ /*
+ * if fh not valid lookup for another valid fh in vnode.
+ * panic if there's not fh valid
+ */
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) {
+ for (i = 0; i < FUFH_MAXTYPE; i++)
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+ break;
+ return (0);
+ }
+
+ return (0);
+}
+
+int
+fusefs_access(void *v)
+{
+ struct fuse_access_in access;
+ struct vop_access_args *ap;
+ struct fuse_in_header hdr;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ struct proc *p;
+ uint32_t mask = 0;
+ int error = 0;
+
+ DPRINTF("fusefs_access\n");
+
+ ap = v;
+ p = ap->a_p;
+ ip = VTOI(ap->a_vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_ACCESS))
+ goto system_check;
+
+ if (ap->a_vp->v_type == VLNK)
+ goto system_check;
+
+ if (ap->a_vp->v_type == VREG && (ap->a_mode & VWRITE & VEXEC))
+ goto system_check;
+
+ if ((ap->a_mode & VWRITE) && (fmp->mp->mnt_flag & MNT_RDONLY))
+ return (EACCES);
+
+ if ((ap->a_mode & VWRITE) != 0) {
+ mask |= 0x2;
+ }
+ if ((ap->a_mode & VREAD) != 0) {
+ mask |= 0x4;
+ }
+ if ((ap->a_mode & VEXEC) != 0) {
+ mask |= 0x1;
+ }
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ access.mask = mask;
+ msg.data = &access;
+ msg.len = sizeof(access);
+ msg.cb = &fuse_sync_it;
+ msg.fmp = fmp;
+ msg.type = msg_intr;
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_ACCESS,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse access", 0);
+
+ if (error)
+ return (error);
+
+ DPRINTF("it with value %x\n", msg.rep.it_res);
+ error = msg.rep.it_res;
+
+ if (error == ENOSYS) {
+ fmp->undef_op |= UNDEF_ACCESS;
+ goto system_check;
+ }
+
+ return (error);
+
+system_check:
+ DPRINTF("Use kernel access\n");
+
+ return (vaccess(ap->a_vp->v_type, ip->cached_attrs.va_mode & ALLPERMS,
+    ip->cached_attrs.va_uid, ip->cached_attrs.va_gid, ap->a_mode,
+    ap->a_cred));
+}
+
+int
+fusefs_getattr(void *v)
+{
+ struct vop_getattr_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fuse_mnt *fmp;
+ struct vattr *vap = ap->a_vap;
+ struct proc *p = ap->a_p;
+ struct fuse_in_header hdr;
+ struct fuse_attr_out *fat;
+ struct fuse_node *ip;
+ struct fuse_msg msg;
+ int error = 0;
+
+ DPRINTF("fusefs_getattr\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init) {
+ goto fake;
+ }
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = 0;
+ msg.data = NULL;
+ msg.rep.buff.len = sizeof(*fat);
+ msg.rep.buff.data_rcv = NULL;
+ msg.type = msg_buff;
+ msg.cb = &fuse_sync_resp;
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_GETATTR,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse getattr", 0);
+
+ if (error) {
+ if (msg.rep.buff.data_rcv != NULL)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ return (error);
+ }
+
+ fat = (struct fuse_attr_out *)msg.rep.buff.data_rcv;
+
+ DPRINTF("ino: %d\n", fat->attr.ino);
+ DPRINTF("size: %d\n", fat->attr.size);
+ DPRINTF("blocks: %d\n", fat->attr.blocks);
+ DPRINTF("atime: %d\n", fat->attr.atime);
+ DPRINTF("mtime: %d\n", fat->attr.mtime);
+ DPRINTF("ctime: %d\n", fat->attr.ctime);
+ DPRINTF("atimensec: %d\n", fat->attr.atimensec);
+ DPRINTF("mtimensec: %d\n", fat->attr.mtimensec);
+ DPRINTF("ctimensec: %d\n", fat->attr.ctimensec);
+ DPRINTF("mode: %d\n", fat->attr.mode);
+ DPRINTF("nlink: %d\n", fat->attr.nlink);
+ DPRINTF("uid: %d\n", fat->attr.uid);
+ DPRINTF("gid: %d\n", fat->attr.gid);
+ DPRINTF("rdev: %d\n", fat->attr.rdev);
+
+ fuse_internal_attr_fat2vat(fmp->mp, &fat->attr, vap);
+
+ memcpy(&ip->cached_attrs, vap, sizeof(*vap));
+ free(fat, M_FUSEFS);
+
+ return (error);
+fake:
+ bzero(vap, sizeof(*vap));
+ vap->va_type = vp->v_type;
+ return (0);
+}
+
+int
+fusefs_setattr(void *v)
+{
+ DPRINTF("fusefs_setattr\n");
+ return (0);
+}
+
+int
+fusefs_ioctl(void *v)
+{
+ DPRINTF("fusefs_ioctl\n");
+ return (ENOTTY);
+}
+
+int
+fusefs_link(void *v)
+{
+ struct vop_link_args *ap = v;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp = ap->a_vp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct fuse_in_header hdr;
+ struct fuse_entry_out *feo;
+ struct fuse_link_in fli;
+ struct fuse_mnt *fmp;
+ struct fuse_node *ip;
+ struct fuse_msg msg;
+ int error = 0;
+
+ DPRINTF("fusefs_link\n");
+
+ if (vp->v_type == VDIR) {
+ VOP_ABORTOP(dvp, cnp);
+ error = EISDIR;
+ goto out2;
+ }
+ if (dvp->v_mount != vp->v_mount) {
+ VOP_ABORTOP(dvp, cnp);
+ error = EXDEV;
+ goto out2;
+ }
+ if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
+ VOP_ABORTOP(dvp, cnp);
+ goto out2;
+ }
+
+ ip = VTOI(vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_LINK))
+ goto out1;
+
+ fli.oldnodeid = ip->ufs_ino.i_number;
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = sizeof(fli);
+ msg.data = &fli;
+ msg.rep.buff.len = sizeof(struct fuse_entry_out);
+ msg.rep.buff.data_rcv = NULL;
+ msg.type = msg_buff;
+ msg.cb = &fuse_sync_resp;
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_LINK,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse link", 0);
+
+ if (error) {
+ if (msg.rep.buff.data_rcv != NULL)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ goto out1;
+ }
+
+ if (msg.error) {
+ error = msg.error;
+
+ if (error == ENOSYS) {
+ fmp->undef_op |= UNDEF_LINK;
+ }
+
+ goto out1;
+ }
+
+ feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+ free(feo, M_FUSEFS);
+
+out1:
+ if (dvp != vp)
+ VOP_UNLOCK(vp, 0, p);
+out2:
+ vput(dvp);
+ return (error);
+}
+
+int
+fusefs_symlink(void *v)
+{
+ DPRINTF("fusefs_symlink\n");
+ return (0);
+}
+
+#define GENERIC_DIRSIZ(dp) \
+    ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3)
&~ 3))
+
+
+int
+readdir_process_data(void *buff, int len, struct uio *uio)
+{
+ struct fuse_dirent *fdir;
+ struct dirent dir;
+ int bytes;
+ int flen, error = 0;
+
+ if (len < FUSE_NAME_OFFSET) {
+ return (0);
+ }
+
+ while ( len > 0) {
+ if ( len < sizeof(*fdir)) {
+ error = 0;
+ break;
+ }
+
+ fdir = (struct fuse_dirent *)buff;
+ flen = FUSE_DIRENT_SIZE(fdir);
+
+ if (!fdir->namelen || fdir->namelen > MAXNAMLEN || len < flen) {
+ error = EINVAL;
+ break;
+ }
+
+ bytes = GENERIC_DIRSIZ((struct pseudo_dirent *) &fdir->namelen);
+ if (bytes > uio->uio_resid) {
+ error = 0;
+ break;
+ }
+
+ bzero(&dir, sizeof(dir));
+ dir.d_fileno = fdir->ino;
+ dir.d_reclen = bytes;
+ dir.d_type = fdir->type;
+ dir.d_namlen = fdir->namelen;
+ bcopy(fdir->name, dir.d_name, fdir->namelen);
+
+ uiomove(&dir, bytes , uio);
+ len -= flen;
+ /* ugly pointer arithmetic must find something else ...*/
+ buff = (void *)(((char *) buff) + flen);
+ uio->uio_offset = fdir->off;
+ }
+
+ return (error);
+}
+
+int
+fusefs_readdir(void *v)
+{
+ struct vop_readdir_args *ap = v;
+ struct fuse_read_in read;
+ struct fuse_in_header hdr;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ struct vnode *vp;
+ struct proc *p;
+ struct uio *uio;
+ int error = 0;
+
+ vp = ap->a_vp;
+ uio = ap->a_uio;
+ p = uio->uio_procp;
+
+ ip = VTOI(vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init) {
+ return (0);
+ }
+
+ DPRINTF("fusefs_readdir\n");
+ DPRINTF("uio resid 0x%x\n", uio->uio_resid);
+
+ if (uio->uio_resid == 0)
+ return (error);
+
+ while (uio->uio_resid > 0) {
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = sizeof(read);
+ msg.type = msg_buff;
+
+ msg.rep.buff.len= 0;
+ msg.rep.buff.data_rcv = NULL;
+ msg.data = &read;
+ msg.cb = &fuse_sync_resp;
+
+ if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) {
+      DPRINTF("dir not open\n");
+      /* TODO open the file */
+      return (error);
+ }
+ read.fh = ip->fufh[FUFH_RDONLY].fh_id;
+ read.offset = uio->uio_offset;
+ read.size = MIN(uio->uio_resid, PAGE_SIZE);
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READDIR,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ error = tsleep(&msg, PWAIT, "fuse getattr", 0);
+
+ if (error) {
+ if (msg.rep.buff.len != 0)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ return (error);
+ }
+
+ if (msg.error == -1) {
+ //ack for end of readdir
+ break;
+ }
+
+ if ((error = readdir_process_data(msg.rep.buff.data_rcv,
+    msg.rep.buff.len, uio))) {
+ if (msg.rep.buff.len != 0)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ break;
+ }
+
+ if (msg.rep.buff.len != 0)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ }
+
+ return (error);
+}
+
+int
+fusefs_inactive(void *v)
+{
+ struct vop_inactive_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
+ register struct fuse_node *ip = VTOI(vp);
+ int error = 0;
+
+ DPRINTF("fusefs_inactive\n");
+
+ VOP_UNLOCK(vp, 0, p);
+
+ /* not sure if it is ok to do like that ...*/
+ if (ip->cached_attrs.va_mode == 0)
+ vrecycle(vp, p);
+
+ return (error);
+}
+
+int
+fusefs_readlink(void *v)
+{
+ struct vop_readlink_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fuse_in_header hdr;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ struct uio *uio;
+ struct proc *p;
+ int error = 0;
+
+ DPRINTF("fusefs_readlink\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+ uio = ap->a_uio;
+ p = uio->uio_procp;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_READLINK)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = 0;
+ msg.data = NULL;
+ msg.type = msg_buff;
+ msg.rep.buff.len = 0;
+ msg.rep.buff.data_rcv = NULL;
+ msg.cb = &fuse_sync_resp;
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READLINK,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ if ((error = tsleep(&msg, PWAIT, "fuse readlink", 0)))
+ goto out;
+
+ if (msg.error) {
+ error = msg.error;
+
+ if (error == ENOSYS) {
+ fmp->undef_op |= UNDEF_READLINK;
+ }
+ goto out;
+ }
+
+ error = uiomove(msg.rep.buff.data_rcv, msg.rep.buff.len, uio);
+
+out:
+
+ if (msg.rep.buff.data_rcv)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ return (error);
+}
+
+int
+fusefs_reclaim(void *v)
+{
+ struct vop_reclaim_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fuse_node *ip = VTOI(vp);
+
+ DPRINTF("fusefs_reclaim\n");
+
+ /*
+ * Purge old data structures associated with the inode.
+ */
+ ip->parent = 0;
+
+ /*
+ * Remove the inode from its hash chain.
+ */
+ ufs_ihashrem(&ip->ufs_ino);
+ cache_purge(vp);
+
+ /*close file if exist
+ if (ip->ufs_ino.i_dev) {
+ vrele(ip->i_devvp);
+ ip->i_devvp = 0;
+ }*/
+
+ free(ip, M_FUSEFS);
+ vp->v_data = NULL;
+ return (0);
+}
+
+int
+fusefs_print(void *v)
+{
+ struct vop_print_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fuse_node *ip = VTOI(vp);
+
+ /*
+ * Complete the information given by vprint().
+ */
+ printf("tag VT_FUSE, hash id %u ", ip->ufs_ino.i_number);
+ lockmgr_printinfo(&ip->ufs_ino.i_lock);
+ printf("\n");
+ return (0);
+}
+
+int
+fusefs_create(void *v)
+{
+ struct vop_create_args *ap = v;
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode **vpp = ap->a_vpp;
+ struct vnode *dvp = ap->a_dvp;
+ struct vattr *vap = ap->a_vap;
+ struct proc *p = cnp->cn_proc;
+ struct fuse_entry_out *feo;
+ struct fuse_in_header hdr;
+ struct vnode *tdp = NULL;
+ struct fuse_open_in foi;
+ struct fuse_mnt *fmp;
+ struct fuse_node *ip;
+ struct fuse_msg msg;
+ int error = 0;
+ mode_t mode;
+
+ DPRINTF("fusefs_create(cnp %08x, vap %08x\n", cnp, vap);
+
+ ip = VTOI(dvp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+ mode = MAKEIMODE(vap->va_type, vap->va_mode);
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_CREATE)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = sizeof(foi) + cnp->cn_namelen + 1;
+ msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+ msg.type = msg_buff;
+ msg.rep.buff.len = sizeof(struct fuse_entry_out) +
+    sizeof(struct fuse_open_out);
+ msg.rep.buff.data_rcv = NULL;
+ msg.cb = &fuse_sync_resp;
+
+ foi.mode = mode;
+ foi.flags = O_CREAT | O_RDWR;
+
+ memcpy(msg.data, &foi, sizeof(foi));
+ memcpy((char *)msg.data + sizeof(foi), cnp->cn_nameptr,
+    cnp->cn_namelen);
+ ((char *)msg.data)[sizeof(foi) + cnp->cn_namelen] = '\0';
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_CREATE,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ if ((error = tsleep(&msg, PWAIT, "fuse create", 0)))
+ goto out;
+
+ if (msg.error) {
+ error = msg.error;
+
+ if (error == ENOSYS) {
+ fmp->undef_op |= UNDEF_CREATE;
+ }
+ goto out;
+ }
+
+ feo = msg.rep.buff.data_rcv;
+ if ((error = VFS_VGET(fmp->mp, feo->nodeid, &tdp)))
+ goto out;
+
+ tdp->v_type = IFTOVT(feo->attr.mode);
+ VTOI(tdp)->vtype = tdp->v_type;
+
+ if (dvp != NULL && dvp->v_type == VDIR)
+ VTOI(tdp)->parent = ip->ufs_ino.i_number;
+
+ *vpp = tdp;
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+
+out:
+ vput(ap->a_dvp);
+
+ if (msg.rep.buff.data_rcv)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+
+ return (error);
+}
+
+int
+fusefs_mknod(void *v)
+{
+ struct vop_mknod_args *ap = v;
+
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+ vput(ap->a_dvp);
+ return (EINVAL);
+}
+
+int
+fusefs_read(void *v)
+{
+ struct vop_read_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct uio *uio = ap->a_uio;
+ struct proc *p = uio->uio_procp;
+ struct fuse_in_header hdr;
+ struct fuse_read_in fri;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ int error=0;
+
+ DPRINTF("fusefs_read\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ DPRINTF("read inode=%i, offset=%%llu, resid=%x\n",
+    ip->ufs_ino.i_number, uio->uio_offset, uio->uio_resid);
+
+ if (uio->uio_resid == 0)
+ return (error);
+ if (uio->uio_offset < 0)
+ return (EINVAL);
+
+ while (uio->uio_resid > 0) {
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = sizeof(fri);
+ msg.data = &fri;
+ msg.type = msg_buff;
+ msg.rep.buff.len = 0;
+ msg.rep.buff.data_rcv = NULL;
+ msg.cb = &fuse_sync_resp;
+
+ fri.fh = ip->fufh[FUFH_RDONLY].fh_id;
+ fri.offset = uio->uio_offset;
+ fri.size = MIN(uio->uio_resid, fmp->max_write);
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_READ,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ if ((error = tsleep(&msg, PWAIT, "fuse read", 0)))
+ break;
+
+ if (msg.error) {
+ DPRINTF("read error %i\n", msg.error);
+ }
+
+ if ((error = uiomove(msg.rep.buff.data_rcv,
+    MIN(fri.size, msg.rep.buff.len), uio))) {
+ break;
+ }
+
+ if (msg.rep.buff.len < fri.size)
+ break;
+
+ if (msg.rep.buff.data_rcv) {
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ msg.rep.buff.data_rcv = NULL;
+ }
+ }
+
+ if (msg.rep.buff.data_rcv)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ return (error);
+}
+
+int
+fusefs_write(void *v)
+{
+ struct vop_write_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct uio *uio = ap->a_uio;
+ struct proc *p = uio->uio_procp;
+ struct fuse_in_header hdr;
+ struct fuse_write_in *fwi;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ size_t len, diff;
+ int error=0;
+
+ DPRINTF("fusefs_write\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ DPRINTF("write inode=%i, offset=%llu, resid=%x\n",
+    ip->ufs_ino.i_number, uio->uio_offset, uio->uio_resid);
+
+ if (uio->uio_resid == 0)
+ return (error);
+
+ while (uio->uio_resid > 0) {
+ len = MIN(uio->uio_resid, fmp->max_write);
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = sizeof(*fwi) + len;
+ msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+ msg.type = msg_buff;
+ msg.rep.buff.len = sizeof(struct fuse_write_out);
+ msg.rep.buff.data_rcv = NULL;
+ msg.cb = &fuse_sync_resp;
+
+ fwi = (struct fuse_write_in *)msg.data;
+ fwi->fh = ip->fufh[FUFH_WRONLY].fh_id;
+ fwi->offset = uio->uio_offset;
+ fwi->size = len;
+
+ if ((error = uiomove((char *)msg.data + sizeof(*fwi), len,
+    uio))) {
+ DPRINTF("uio error %i", error);
+ break;
+ }
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_WRITE,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ if ((error = tsleep(&msg, PWAIT, "fuse write", 0)))
+ break;
+
+ if (msg.error) {
+ DPRINTF("write error %i\n", msg.error);
+ }
+
+ diff = len -
+    ((struct fuse_write_out *)msg.rep.buff.data_rcv)->size;
+ if (diff < 0) {
+ error = EINVAL;
+ break;
+ }
+
+ uio->uio_resid += diff;
+ uio->uio_offset -= diff;
+
+ if (msg.rep.buff.data_rcv) {
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ msg.rep.buff.data_rcv = NULL;
+ }
+ }
+
+ if (msg.rep.buff.data_rcv)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+ return (error);
+}
+
+int
+fusefs_poll(void *v)
+{
+ struct vop_poll_args *ap = v;
+
+ DPRINTF("fusefs_poll\n");
+
+ /*
+ * We should really check to see if I/O is possible.
+ */
+ return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
+}
+
+int
+fusefs_fsync(void *v)
+{
+ DPRINTF("fusefs_fsync\n");
+ return (0);
+}
+
+int
+fusefs_rename(void *v)
+{
+ DPRINTF("fusefs_rename\n");
+ return (0);
+}
+
+int
+fusefs_mkdir(void *v)
+{
+ struct vop_mkdir_args *ap = v;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode **vpp = ap->a_vpp;
+ struct componentname *cnp = ap->a_cnp;
+ struct vattr *vap = ap->a_vap;
+ struct proc *p = cnp->cn_proc;
+ struct fuse_mkdir_in fmdi;
+ struct vnode *tdp = NULL;
+ struct fuse_in_header hdr;
+ struct fuse_entry_out *feo;
+ struct fuse_node *ip;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ int error = 0;
+
+ DPRINTF("fusefs_mkdir %s\n", cnp->cn_nameptr);
+
+ ip = VTOI(dvp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+ fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKDIR)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = sizeof(fmdi) + cnp->cn_namelen + 1;
+ msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+ msg.type = msg_buff;
+ msg.rep.buff.len = sizeof(struct fuse_entry_out);
+ msg.rep.buff.data_rcv = NULL;
+ msg.cb = &fuse_sync_resp;
+
+ memcpy(msg.data, &fmdi, sizeof(fmdi));
+ memcpy((char *)msg.data + sizeof(fmdi), cnp->cn_nameptr,
+    cnp->cn_namelen);
+ ((char *)msg.data)[sizeof(fmdi) + cnp->cn_namelen] = '\0';
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_MKDIR,
+    ip->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ if ((error = tsleep(&msg, PWAIT, "fuse mkdir", 0)))
+ goto out;
+
+ if (msg.error) {
+ error = msg.error;
+
+ if (error == ENOSYS) {
+ fmp->undef_op |= UNDEF_MKDIR;
+ }
+ goto out;
+ }
+
+ feo = (struct fuse_entry_out *)msg.rep.buff.data_rcv;
+
+ if ((error = VFS_VGET(fmp->mp, feo->nodeid, &tdp)))
+ goto out;
+
+ tdp->v_type = IFTOVT(feo->attr.mode);
+ VTOI(tdp)->vtype = tdp->v_type;
+
+ if (dvp != NULL && dvp->v_type == VDIR)
+ VTOI(tdp)->parent = ip->ufs_ino.i_number;
+
+ *vpp = tdp;
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
+
+out:
+ vput(dvp);
+
+ if (msg.rep.buff.data_rcv)
+ free(msg.rep.buff.data_rcv, M_FUSEFS);
+
+ return (error);
+}
+
+int
+fusefs_rmdir(void *v)
+{
+ struct vop_rmdir_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct fuse_node *ip, *dp;
+ struct fuse_in_header hdr;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ int error;
+
+ DPRINTF("fusefs_rmdir\n");
+ DPRINTF("len :%i, cnp: %c %c %c\n", cnp->cn_namelen, cnp->cn_nameptr[0],
+    cnp->cn_nameptr[1], cnp->cn_nameptr[2]);
+
+ ip = VTOI(vp);
+ dp = VTOI(dvp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ /*
+ * No rmdir "." please.
+ */
+ if (dp == ip) {
+ vrele(dvp);
+ vput(vp);
+ return (EINVAL);
+ }
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_RMDIR)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = cnp->cn_namelen + 1;
+ msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+ msg.type = msg_intr;
+ msg.cb = &fuse_sync_it;
+
+ memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+ ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_RMDIR,
+    dp->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ if ((error = tsleep(&msg, PWAIT, "fuse rmdir", 0)))
+ goto out;
+
+ if (msg.error) {
+ error = msg.error;
+
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_RMDIR;
+ if (error != ENOTEMPTY)
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+ goto out;
+ }
+
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+ cache_purge(dvp);
+ vput(dvp);
+ dvp = NULL;
+
+ cache_purge(ITOV(ip));
+out:
+ if (dvp)
+ vput(dvp);
+ VN_KNOTE(vp, NOTE_DELETE);
+ vput(vp);
+ return (error);
+}
+
+int
+fusefs_remove(void *v)
+{
+ struct vop_remove_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct fuse_node *ip;
+ struct fuse_node *dp;
+ struct fuse_in_header hdr;
+ struct fuse_mnt *fmp;
+ struct fuse_msg msg;
+ int error = 0;
+
+ DPRINTF("fusefs_remove\n");
+ DPRINTF("len :%i, cnp: %c %c %c\n", cnp->cn_namelen, cnp->cn_nameptr[0],
+    cnp->cn_nameptr[1], cnp->cn_nameptr[2]);
+
+ ip = VTOI(vp);
+ dp = VTOI(dvp);
+ fmp = (struct fuse_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_REMOVE)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ bzero(&msg, sizeof(msg));
+ msg.hdr = &hdr;
+ msg.len = cnp->cn_namelen + 1;
+ msg.data = malloc(msg.len, M_FUSEFS, M_WAITOK | M_ZERO);
+ msg.type = msg_intr;
+ msg.cb = &fuse_sync_it;
+
+ memcpy(msg.data, cnp->cn_nameptr, cnp->cn_namelen);
+ ((char *)msg.data)[cnp->cn_namelen] = '\0';
+
+ fuse_make_in(fmp->mp, msg.hdr, msg.len, FUSE_UNLINK,
+    dp->ufs_ino.i_number, p);
+
+ TAILQ_INSERT_TAIL(&fmq_in, &msg, node);
+ wakeup(&fmq_in);
+
+ if ((error = tsleep(&msg, PWAIT, "fuse remove", 0)))
+ goto out;
+
+ if (msg.error) {
+ error = msg.error;
+
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_REMOVE;
+ goto out;
+ }
+
+ VN_KNOTE(vp, NOTE_DELETE);
+ VN_KNOTE(dvp, NOTE_WRITE);
+out:
+ if (dvp == vp)
+ vrele(vp);
+ else
+ vput(vp);
+ vput(dvp);
+ return (error);
+}
+
+int
+fusefs_strategy(void *v)
+{
+ DPRINTF("fusefs_strategy\n");
+ return (0);
+}
+
+int
+fusefs_lock(void *v)
+{
+ struct vop_lock_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ DPRINTF("fuse_lock\n");
+ return (lockmgr(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags, NULL));
+}
+
+int
+fusefs_unlock(void *v)
+{
+ struct vop_unlock_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ DPRINTF("fuse_unlock\n");
+ return (lockmgr(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags | LK_RELEASE,
+    NULL));
+}
+
+int
+fusefs_islocked(void *v)
+{
+ struct vop_islocked_args *ap = v;
+
+ DPRINTF("fuse_islock\n");
+ return (lockstatus(&VTOI(ap->a_vp)->ufs_ino.i_lock));
+}
+
+int
+fusefs_advlock(void *v)
+{
+ struct vop_advlock_args *ap = v;
+ struct fuse_node *ip = VTOI(ap->a_vp);
+
+ DPRINTF("fuse_advlock\n");
+ return (lf_advlock(&ip->ufs_ino.i_lockf, ip->filesize, ap->a_id,
+    ap->a_op, ap->a_fl, ap->a_flags));
+}
Index: sys/miscfs/fuse/fusefs.h
===================================================================
RCS file: sys/miscfs/fuse/fusefs.h
diff -N sys/miscfs/fuse/fusefs.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/miscfs/fuse/fusefs.h 8 Mar 2013 15:40:48 -0000
@@ -0,0 +1,115 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FUSEFS_H__
+#define __FUSEFS_H__
+
+struct fuse_msg;
+
+struct fuse_mnt {
+ struct mount *mp;
+ uint32_t undef_op;
+ uint32_t max_write;
+ int sess_init;
+ int unique;
+ dev_t dev;
+};
+
+#define UNDEF_ACCESS 1<<0
+#define UNDEF_MKDIR 1<<1
+#define UNDEF_CREATE 1<<2
+#define UNDEF_LINK 1<<3
+#define UNDEF_READLINK 1<<4
+#define UNDEF_RMDIR 1<<5
+#define UNDEF_REMOVE 1<<6
+
+typedef void (*fuse_cb)(struct fuse_msg *,struct fuse_out_header *,
void *);
+
+struct rcv_buf {
+ void *data_rcv;
+ size_t len;
+};
+
+enum msg_type {
+ msg_intr,
+ msg_buff,
+ msg_buff_async,
+};
+
+struct fuse_msg {
+ struct fuse_in_header *hdr;
+ struct fuse_mnt *fmp;
+ void *data;
+ int len;
+ int error;
+
+ enum msg_type type;
+ union {
+ struct rcv_buf buff;
+ uint32_t it_res;
+ } rep;
+
+ fuse_cb cb;
+ TAILQ_ENTRY(fuse_msg) node;
+};
+
+extern struct vops fusefs_vops;
+
+/*
+ * In and Out fifo for fuse communication
+ */
+TAILQ_HEAD(fuse_msg_head, fuse_msg);
+
+extern struct fuse_msg_head fmq_in;
+extern struct fuse_msg_head fmq_wait;
+
+/*
+ * fuse helpers
+ */
+void fuse_make_in(struct mount *, struct fuse_in_header *, int,
+  enum fuse_opcode, ino_t, struct proc *);
+void fuse_init_resp(struct fuse_msg *, struct fuse_out_header *, void *);
+void fuse_sync_resp(struct fuse_msg *, struct fuse_out_header *, void *);
+void fuse_sync_it(struct fuse_msg *, struct fuse_out_header *, void *);
+
+/*
+ * files helpers.
+ */
+
+int fuse_file_open(struct fuse_mnt *, struct fuse_node *, enum
fufh_type, int,
+    int, struct proc *);
+int fuse_file_close(struct fuse_mnt *, struct fuse_node *, enum
fufh_type, int,
+    int, struct proc *);
+void fuse_internal_attr_fat2vat(struct mount *, struct fuse_attr *,
+    struct vattr *);
+
+/*
+ * The root inode is the root of the file system.  Inode 0 can't be
used for
+ * normal purposes.
+ */
+#define FUSE_ROOTINO ((ino_t)1)
+#define VFSTOFUSEFS(mp) ((struct fuse_mnt *)((mp)->mnt_data))
+
+#define MNT_FUSE_DOOMED 0x10000000
+/*
+#define FUSE_DEBUG_VNOP
+#define FUSE_DEBUG_VFS
+#define FUSE_DEV_DEBUG
+#define FUSE_DEBUG_MSG
+*/
+
+#endif /* __FUSEFS_H__ */
Index: sys/sys/conf.h
===================================================================
RCS file: /cvs/src/sys/sys/conf.h,v
retrieving revision 1.119
diff -u -p -u -p -r1.119 conf.h
--- sys/sys/conf.h 23 Aug 2012 06:12:49 -0000 1.119
+++ sys/sys/conf.h 8 Mar 2013 15:40:48 -0000
@@ -509,6 +509,13 @@ extern struct cdevsw cdevsw[];
  (dev_type_stop((*))) enodev, 0, selfalse, \
  (dev_type_mmap((*))) enodev }

+/* open, close, read, write, poll, ioctl */
+#define cdev_fuse_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
+ (dev_type_mmap((*))) enodev }
+
 #endif

 /*
@@ -657,6 +664,7 @@ cdev_decl(urio);
 cdev_decl(hotplug);
 cdev_decl(gpio);
 cdev_decl(amdmsr);
+cdev_decl(fuse);

 #endif

Index: sys/sys/malloc.h
===================================================================
RCS file: /cvs/src/sys/sys/malloc.h,v
retrieving revision 1.101
diff -u -p -u -p -r1.101 malloc.h
--- sys/sys/malloc.h 7 Feb 2013 11:06:42 -0000 1.101
+++ sys/sys/malloc.h 8 Mar 2013 15:40:48 -0000
@@ -118,7 +118,8 @@
 #define M_TTYS 62 /* allocated tty structures */
 #define M_EXEC 63 /* argument lists & other mem used by exec */
 #define M_MISCFSMNT 64 /* miscfs mount structures */
-/* 65-73 - free */
+#define M_FUSEFS 65 /* fusefs mount structures */
+/* 66-73 - free */
 #define M_PFKEY 74 /* pfkey data */
 #define M_TDB 75 /* Transforms database */
 #define M_XDATA 76 /* IPsec data */
@@ -247,7 +248,7 @@
  "ttys", /* 62 M_TTYS */ \
  "exec", /* 63 M_EXEC */ \
  "miscfs mount", /* 64 M_MISCFSMNT */ \
- NULL, \
+ "fusefs mount", /* 65 M_FUSEFS */ \
  NULL, \
  NULL, \
  NULL, \
Index: sys/sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.108
diff -u -p -u -p -r1.108 mount.h
--- sys/sys/mount.h 5 Sep 2012 17:01:06 -0000 1.108
+++ sys/sys/mount.h 8 Mar 2013 15:40:48 -0000
@@ -258,6 +258,15 @@ struct procfs_args {
 #define PROCFS_ARGSVERSION      1
 #define PROCFSMNT_LINUXCOMPAT   0x01

+/*
+ * Arguments to mount fusefs filesystems
+ */
+struct fusefs_args {
+ char *name;
+ char *url;
+ int fd;
+ int flags;
+};

 /*
  * file system statistics
@@ -325,6 +334,7 @@ struct statfs {
 #define MOUNT_NCPFS "ncpfs" /* NetWare Network File System */
 #define MOUNT_NTFS "ntfs" /* NTFS */
 #define MOUNT_UDF "udf" /* UDF */
+#define MOUNT_FUSEFS "fuse" /* FUSE */

 /*
  * Structure per mounted file system.  Each mounted file system has an
Index: sys/sys/vnode.h
===================================================================
RCS file: /cvs/src/sys/sys/vnode.h,v
retrieving revision 1.113
diff -u -p -u -p -r1.113 vnode.h
--- sys/sys/vnode.h 8 Oct 2012 15:43:08 -0000 1.113
+++ sys/sys/vnode.h 8 Mar 2013 15:40:48 -0000
@@ -71,13 +71,13 @@ enum vtype { VNON, VREG, VDIR, VBLK, VCH
 enum vtagtype {
  VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_MSDOSFS,
  VT_PORTAL, VT_PROCFS, VT_AFS, VT_ISOFS, VT_ADOSFS,
- VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF,
+ VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF, VT_FUSEFS
 };

 #define VTAG_NAMES \
     "NON", "UFS", "NFS", "MFS", "MSDOSFS", \
     "PORTAL", "PROCFS", "AFS", "ISOFS", "ADOSFS", \
-    "EXT2FS", "VFS", "NTFS", "UDF"
+    "EXT2FS", "VFS", "NTFS", "UDF", "FUSEFS"

 /*
  * Each underlying filesystem allocates its own private area and hangs

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Gregor Best
Hi,

> [...]
> I will spend the next days working on the NetBSD librefuse, I will try
> to get it working with my kernel code and will come back here when I
> have something that works.
> [...]

Are there any news on this? If you need a hand testing stuff and
tracking down bugs, I'd be very happy to help.

--
    Gregor Best

attachment0 (203 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
On Fri, Apr 19, 2013 at 10:59 PM, Gregor Best <[hidden email]> wrote:

> Hi,
>
>> [...]
>> I will spend the next days working on the NetBSD librefuse, I will try
>> to get it working with my kernel code and will come back here when I
>> have something that works.
>> [...]
>
> Are there any news on this? If you need a hand testing stuff and
> tracking down bugs, I'd be very happy to help.
>
> --
>     Gregor Best

I am still working on it with the good advices of some devs (mpi@,
gilles@, todd@, armani@).

I Hope to have something re-submitable on tech@ in 1 or 2 weeks.

Cheers,
--
Sylvestre Gallon

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fuse (and sshfs) support for OpenBSD

Sylvestre Gallon
In reply to this post by Sylvestre Gallon
Hi tech@,

You will find in this mail a patch for fuse support in kernel. I will send 2
other mails for the userland and the ports patch. There is still work to do
on my fuse implementation but as I understand there is an hackathon occuring
at the moment and mpi@ tells me that it could be a good idea to send you
something before the end of this event, even if my implementation is not
perfect yet.

Here is the procedure to patch the kernel :

* apply the patch
    root # cd /usr/src/sys
    root # ftp http://www.pmbsd.org/patch-fuse-sys (you will also find
               patch-fuse-sys inlined in this mail)
    root # patch -p0 < patch-fuse-sys

* upgrade your system mount.h and fusebuf.h
    root # cp /usr/src/sys/sys/mount.h /usr/include/sys/mount.h
    root # cp /usr/src/sys/sys/fusebuf.h /usr/include/sys/fusebuf.h

* build a new kernel and install it

* create the fuse device
    root # mknod /dev/fuse0 c 93 0

Since my last patch a lot of architectural change were done. On mpi@'s
advices I base my implementation on something called fusebuf(9). A fusebuf
is a mbuf(9) like api for transfers between kernel and the fuse(3) library.
If you want more details on fusebufs there is a manpage draft on my diff. I've
also changed the fuse(4) device code to get clother to other OpenBSD drivers.

The new implementation also use pool(9) for allocating fusebufs, arc4random(9)
for uuid generation and kqueue(2) on the fuse device.

You will see that the code is now specific to OpenBSD and differs from FreeBSD.
For the moment I have tried sshfs and all works well except the rename(2)
vnop. I need some time to understand how works rename and fix it... I will try
to test other fuse clients as soon as I've fixed my todolist.

Thanks for your time, and thanks a lot to mpi@ gilles@ todd@ and armani@ for
their precious help.

Cheers,

Sylvestre

Index: arch/alpha/alpha/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/alpha/alpha/conf.c,v
retrieving revision 1.70
diff -u -p -u -p -r1.70 conf.c
--- arch/alpha/alpha/conf.c 15 Mar 2013 09:10:52 -0000 1.70
+++ arch/alpha/alpha/conf.c 3 Jun 2013 13:35:23 -0000
@@ -130,6 +130,7 @@ cdev_decl(pci);
 #include "hotplug.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -204,6 +205,7 @@ struct cdevsw cdevsw[] =
  cdev_pppx_init(NPPPX,pppx), /* 64: pppx */
  cdev_urio_init(NURIO,urio), /* 65: USB Diamond Rio 500 */
  cdev_usbdev_init(NUSCANNER,uscanner), /* 66: USB scanners */
+ cdev_fuse_init(NFUSE,fuse), /* 67: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/amd64/amd64/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/conf.c,v
retrieving revision 1.40
diff -u -p -u -p -r1.40 conf.c
--- arch/amd64/amd64/conf.c 15 Mar 2013 09:10:52 -0000 1.40
+++ arch/amd64/amd64/conf.c 3 Jun 2013 13:35:28 -0000
@@ -179,6 +179,7 @@ cdev_decl(pci);
 #include "gpio.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -286,6 +287,7 @@ struct cdevsw cdevsw[] =
  cdev_vscsi_init(NVSCSI,vscsi), /* 89: vscsi */
  cdev_disk_init(1,diskmap), /* 90: disk mapper */
  cdev_pppx_init(NPPPX,pppx),     /* 91: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 92: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/hp300/hp300/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/hp300/hp300/conf.c,v
retrieving revision 1.54
diff -u -p -u -p -r1.54 conf.c
--- arch/hp300/hp300/conf.c 23 Aug 2012 06:12:49 -0000 1.54
+++ arch/hp300/hp300/conf.c 3 Jun 2013 13:35:33 -0000
@@ -111,6 +111,7 @@ cdev_decl(fd);
 #include "vscsi.h"
 #include "pppx.h"
 #include "hotplug.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -171,6 +172,7 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 54: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 55: pppx */
  cdev_hotplug_init(NHOTPLUG,hotplug), /* 56: devices hot plugging */
+ cdev_fuse_init(NFUSE,fuse), /* 57: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/hppa/hppa/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/hppa/hppa/conf.c,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 conf.c
--- arch/hppa/hppa/conf.c 23 Aug 2012 06:12:49 -0000 1.55
+++ arch/hppa/hppa/conf.c 3 Jun 2013 13:35:33 -0000
@@ -120,6 +120,7 @@ cdev_decl(pci);
 #include "uscanner.h"
 
 #include "bthub.h"
+#include "fuse.h"
 
 struct cdevsw   cdevsw[] =
 {
@@ -186,6 +187,7 @@ struct cdevsw   cdevsw[] =
  cdev_bthub_init(NBTHUB,bthub), /* 55: bthub */
  cdev_disk_init(1,diskmap), /* 56: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 57: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 58: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/hppa64/hppa64/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/hppa64/hppa64/conf.c,v
retrieving revision 1.22
diff -u -p -u -p -r1.22 conf.c
--- arch/hppa64/hppa64/conf.c 23 Aug 2012 06:12:49 -0000 1.22
+++ arch/hppa64/hppa64/conf.c 3 Jun 2013 13:35:33 -0000
@@ -120,6 +120,7 @@ cdev_decl(pci);
 #include "uscanner.h"
 
 #include "bthub.h"
+#include "fuse.h"
 
 struct cdevsw   cdevsw[] =
 {
@@ -186,6 +187,7 @@ struct cdevsw   cdevsw[] =
  cdev_bthub_init(NBTHUB,bthub), /* 55: bthub */
  cdev_disk_init(1,diskmap), /* 56: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 57: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 58: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/i386/i386/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/conf.c,v
retrieving revision 1.142
diff -u -p -u -p -r1.142 conf.c
--- arch/i386/i386/conf.c 15 Mar 2013 09:10:52 -0000 1.142
+++ arch/i386/i386/conf.c 3 Jun 2013 13:35:33 -0000
@@ -183,6 +183,7 @@ cdev_decl(pci);
 #include "amdmsr.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -291,6 +292,7 @@ struct cdevsw cdevsw[] =
  cdev_vscsi_init(NVSCSI,vscsi), /* 90: vscsi */
  cdev_disk_init(1,diskmap), /* 91: disk mapper */
  cdev_pppx_init(NPPPX,pppx),     /* 92: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 93: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/landisk/landisk/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/landisk/landisk/conf.c,v
retrieving revision 1.24
diff -u -p -u -p -r1.24 conf.c
--- arch/landisk/landisk/conf.c 15 Mar 2013 09:10:52 -0000 1.24
+++ arch/landisk/landisk/conf.c 3 Jun 2013 13:35:33 -0000
@@ -255,6 +255,7 @@ struct bdevsw bdevsw[] = {
 #include "scif.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] = {
  cdev_cn_init(1,cn), /*  0: virtual console */
@@ -364,6 +365,7 @@ struct cdevsw cdevsw[] = {
  cdev_bthub_init(NBTHUB,bthub), /* 100: bthub */
  cdev_disk_init(1,diskmap), /* 101: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 102: pppx */
+ cdev_fuse_init(NFUSE,fuse), /* 103: fuse */
 };
 
 int nblkdev = nitems(bdevsw);
Index: arch/loongson/loongson/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/loongson/loongson/conf.c,v
retrieving revision 1.14
diff -u -p -u -p -r1.14 conf.c
--- arch/loongson/loongson/conf.c 23 Aug 2012 06:12:49 -0000 1.14
+++ arch/loongson/loongson/conf.c 3 Jun 2013 13:35:33 -0000
@@ -130,6 +130,7 @@ cdev_decl(pci);
 #include "bthub.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -210,6 +211,7 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 70: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 71: pppx */
  cdev_usbdev_init(NUSCANNER,uscanner), /* 72: USB scanners */
+ cdev_fuse_init(NFUSE,fuse), /* 73: fuse */
 };
 
 int nchrdev = nitems(cdevsw);
Index: arch/sgi/sgi/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/conf.c,v
retrieving revision 1.31
diff -u -p -u -p -r1.31 conf.c
--- arch/sgi/sgi/conf.c 23 Aug 2012 06:12:49 -0000 1.31
+++ arch/sgi/sgi/conf.c 3 Jun 2013 13:35:33 -0000
@@ -130,6 +130,7 @@ cdev_decl(pci);
 
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -210,6 +211,7 @@ struct cdevsw cdevsw[] =
  cdev_pppx_init(NPPPX,pppx), /* 70: pppx */
  cdev_notdef(), /* 71: */
  cdev_usbdev_init(NUSCANNER,uscanner), /* 72: USB scanners */
+ cdev_fuse_init(NFUSE,fuse), /* 73: fuse */
 };
 
 int nchrdev = nitems(cdevsw);
Index: arch/socppc/socppc/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/socppc/socppc/conf.c,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 conf.c
--- arch/socppc/socppc/conf.c 6 Apr 2012 15:10:40 -0000 1.16
+++ arch/socppc/socppc/conf.c 3 Jun 2013 13:35:33 -0000
@@ -119,6 +119,7 @@ cdev_decl(pci);
 #include "vscsi.h"
 #include "pppx.h"
 #include "hotplug.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] = {
  cdev_cn_init(1,cn), /* 0: virtual console */
@@ -212,6 +213,7 @@ struct cdevsw cdevsw[] = {
  cdev_disk_init(1,diskmap), /* 82: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 83: pppx */
  cdev_hotplug_init(NHOTPLUG,hotplug), /* 84: devices hot plugging */
+ cdev_fuse_init(NFUSE,fuse), /* 85: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/sparc/sparc/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc/sparc/conf.c,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 conf.c
--- arch/sparc/sparc/conf.c 23 Aug 2012 06:12:49 -0000 1.61
+++ arch/sparc/sparc/conf.c 3 Jun 2013 13:35:33 -0000
@@ -124,6 +124,7 @@ int nblkdev = nitems(bdevsw);
 #include "vscsi.h"
 #include "pppx.h"
 #include "hotplug.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -214,7 +215,7 @@ struct cdevsw cdevsw[] =
  cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */
  cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */
  cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexer */
- cdev_notdef(), /* 82 */
+ cdev_fuse_init(NFUSE, fuse), /* 82: fuse */
  cdev_notdef(), /* 83 */
  cdev_notdef(), /* 84 */
  cdev_notdef(), /* 85 */
Index: arch/sparc64/sparc64/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/sparc64/conf.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 conf.c
--- arch/sparc64/sparc64/conf.c 8 Dec 2012 20:38:10 -0000 1.66
+++ arch/sparc64/sparc64/conf.c 3 Jun 2013 13:35:33 -0000
@@ -117,6 +117,7 @@ cdev_decl(pci);
 #include "hotplug.h"
 #include "vscsi.h"
 #include "pppx.h"
+#include "fuse.h"
 
 struct bdevsw bdevsw[] =
 {
@@ -289,7 +290,8 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 130: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 131: pppx */
  cdev_gen_init(NVLDCP,vldcp), /* 132: vldcp */
- cdev_vdsp_init(NVDSP,vdsp) /* 133: vdsp */
+ cdev_vdsp_init(NVDSP,vdsp), /* 133: vdsp */
+ cdev_fuse_init(NFUSE,fuse), /* 134: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: arch/vax/vax/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/vax/vax/conf.c,v
retrieving revision 1.68
diff -u -p -u -p -r1.68 conf.c
--- arch/vax/vax/conf.c 23 Aug 2012 06:12:49 -0000 1.68
+++ arch/vax/vax/conf.c 3 Jun 2013 13:35:33 -0000
@@ -175,6 +175,7 @@ cdev_decl(dl);
 #include "vscsi.h"
 #include "pppx.h"
 #include "audio.h"
+#include "fuse.h"
 
 struct cdevsw cdevsw[] =
 {
@@ -260,6 +261,7 @@ struct cdevsw cdevsw[] =
  cdev_disk_init(1,diskmap), /* 79: disk mapper */
  cdev_pppx_init(NPPPX,pppx), /* 80: pppx */
  cdev_audio_init(NAUDIO,audio), /* 81: /dev/audio */
+ cdev_fuse_init(NFUSE,fuse), /* 82: fuse */
 };
 int nchrdev = nitems(cdevsw);
 
Index: conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/conf/GENERIC,v
retrieving revision 1.196
diff -u -p -u -p -r1.196 GENERIC
--- conf/GENERIC 15 Apr 2013 15:32:19 -0000 1.196
+++ conf/GENERIC 3 Jun 2013 13:35:33 -0000
@@ -46,6 +46,7 @@ option NFSSERVER # Network File System
 option CD9660 # ISO 9660 + Rock Ridge file system
 option UDF # UDF (DVD) file system
 option MSDOSFS # MS-DOS file system
+option FUSE # Userland file system
 option FIFO # FIFOs; RECOMMENDED
 
 option SOCKET_SPLICE # Socket Splicing for TCP
@@ -74,6 +75,8 @@ scsibus* at softraid?
 
 vscsi0 at root # Userland backed Virtual SCSI
 scsibus* at vscsi?
+
+pseudo-device fuse 10 # filesystem in user land
 
 pseudo-device pf # packet filter
 pseudo-device pflog # pf log if
Index: conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.546
diff -u -p -u -p -r1.546 files
--- conf/files 29 May 2013 22:23:01 -0000 1.546
+++ conf/files 3 Jun 2013 13:35:33 -0000
@@ -545,6 +545,14 @@ pseudo-device systrace
 pseudo-device ksyms
 file dev/ksyms.c ksyms needs-flag
 
+pseudo-device fuse
+file miscfs/fuse/fuse_device.c fuse needs-flag
+file miscfs/fuse/fuse_file.c fuse
+file miscfs/fuse/fuse_lookup.c fuse
+file miscfs/fuse/fuse_vfsops.c fuse
+file miscfs/fuse/fuse_vnops.c fuse
+file miscfs/fuse/fusebuf.c fuse
+
 pseudo-device pf: ifnet
 file net/pf.c pf needs-flag
 file net/pf_norm.c pf
Index: kern/vfs_init.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_init.c,v
retrieving revision 1.31
diff -u -p -u -p -r1.31 vfs_init.c
--- kern/vfs_init.c 28 Mar 2013 03:27:46 -0000 1.31
+++ kern/vfs_init.c 3 Jun 2013 13:35:33 -0000
@@ -86,6 +86,10 @@ extern  const struct vfsops ntfs_vfsops;
 extern  const struct vfsops udf_vfsops;
 #endif
 
+#ifdef FUSE
+extern const struct vfsops fusefs_vfsops;
+#endif
+
 /* Set up the filesystem operations for vnodes. */
 static struct vfsconf vfsconflist[] = {
 #ifdef FFS
@@ -122,6 +126,10 @@ static struct vfsconf vfsconflist[] = {
 
 #ifdef UDF
  { &udf_vfsops, MOUNT_UDF, 13, 0, MNT_LOCAL, NULL },
+#endif
+
+#ifdef FUSE
+ { &fusefs_vfsops, MOUNT_FUSEFS, 18, 0, MNT_LOCAL, NULL },
 #endif
 };
 
Index: miscfs/fuse/fuse_device.c
===================================================================
RCS file: miscfs/fuse/fuse_device.c
diff -N miscfs/fuse/fuse_device.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_device.c 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,512 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/poll.h>
+#include <sys/pool.h>
+#include <sys/statvfs.h>
+#include <sys/vnode.h>
+#include <sys/fusebuf.h>
+
+#include "fusefs_node.h"
+#include "fusefs.h"
+
+#define FUSE_UNIT(dev) (minor(dev))
+#define FUSE_DEV2SC(a) (&fuse_softc[FUSE_UNIT(a)])
+#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
+
+#ifdef FUSE_DEBUG
+#define DPRINTF(fmt, arg...) printf("%s: " fmt, DEVNAME(sc), ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+SIMPLEQ_HEAD(fusebuf_head, fusebuf);
+
+struct fuse_softc {
+ struct fusefs_mnt *sc_fmp;
+ struct device sc_dev;
+ int sc_opened;
+
+ struct fusebuf_head sc_fbufs_in;
+ struct fusebuf_head sc_fbufs_wait;
+
+ /* kq fields */
+ struct selinfo sc_rsel;
+};
+
+#define FUSE_OPEN 1
+#define FUSE_CLOSE 0
+#define FUSE_DONE 2
+
+struct fuse_softc *fuse_softc;
+static int numfuse = 0;
+int stat_fbufs_in = 0;
+int stat_fbufs_wait = 0;
+int stat_opened_fusedev = 0;
+
+void fuseattach(int);
+int fuseopen(dev_t, int, int, struct proc *);
+int fuseclose(dev_t, int, int, struct proc *);
+int fuseioctl(dev_t, u_long, caddr_t, int, struct proc *);
+int fuseread(dev_t, struct uio *, int);
+int fusewrite(dev_t, struct uio *, int);
+int fusepoll(dev_t, int, struct proc *);
+int fusekqfilter(dev_t dev, struct knote *kn);
+int filt_fuse_read(struct knote *, long);
+void filt_fuse_rdetach(struct knote *);
+
+const static struct filterops fuse_rd_filtops = {
+ 1,
+ NULL,
+ filt_fuse_rdetach,
+ filt_fuse_read
+};
+
+const static struct filterops fuse_seltrue_filtops = {
+ 1,
+ NULL,
+ filt_fuse_rdetach,
+ filt_seltrue
+};
+
+#ifdef FUSE_DEBUG
+static void
+fuse_dump_buff(char *buff, int len)
+{
+ char text[17];
+ int i;
+
+ bzero(text, 17);
+ for (i = 0; i < len ; i++) {
+
+ if (i != 0 && (i % 16) == 0) {
+ printf(": %s\n", text);
+ bzero(text, 17);
+ }
+
+ printf("%.2x ", buff[i] & 0xff);
+
+ if (buff[i] > ' ' && buff[i] < '~')
+ text[i%16] = buff[i] & 0xff;
+ else
+ text[i%16] = '.';
+ }
+
+ if ((i % 16) != 0)
+ while ((i % 16) != 0) {
+ printf("   ");
+ i++;
+ }
+
+ printf(": %s\n", text);
+}
+#endif
+
+/*
+ * if fbuf == NULL cleanup all msgs else remove fbuf from
+ * sc_fbufs_in and sc_fbufs_wait.
+ */
+void
+fuse_device_cleanup(dev_t dev, struct fusebuf *fbuf)
+{
+ struct fuse_softc *sc;
+ struct fusebuf *f;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return;
+
+ sc = FUSE_DEV2SC(dev);
+ sc->sc_fmp = NULL;
+
+ /* clear FIFO IN*/
+ while ((f = SIMPLEQ_FIRST(&sc->sc_fbufs_in))) {
+ if (fbuf == f || fbuf == NULL) {
+ DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n");
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_fbufs_in, fb_next);
+ stat_fbufs_in--;
+ if (fbuf == NULL)
+ pool_put(&fusefs_fbuf_pool, f);
+ }
+ }
+
+ /* clear FIFO WAIT*/
+ while ((f = SIMPLEQ_FIRST(&sc->sc_fbufs_wait))) {
+ if (fbuf == f || fbuf == NULL) {
+ DPRINTF("umount unprocessed msg in sc_fbufs_wait\n");
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_fbufs_wait, fb_next);
+ stat_fbufs_wait--;
+ if (fbuf == NULL)
+ pool_put(&fusefs_fbuf_pool, f);
+ }
+ }
+}
+
+void
+fuse_device_queue_fbuf(dev_t dev, struct fusebuf *fbuf)
+{
+ struct fuse_softc *sc;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return;
+
+ sc = FUSE_DEV2SC(dev);
+ SIMPLEQ_INSERT_TAIL(&sc->sc_fbufs_in, fbuf, fb_next);
+ stat_fbufs_in++;
+ selwakeup(&sc->sc_rsel);
+}
+
+void
+fuse_device_set_fmp(struct fusefs_mnt *fmp)
+{
+ struct fuse_softc *sc;
+
+ if (FUSE_UNIT(fmp->dev) >= numfuse)
+ return;
+
+ sc = FUSE_DEV2SC(fmp->dev);
+ sc->sc_fmp = fmp;
+}
+
+void
+fuseattach(int num)
+{
+ char *mem;
+ u_long size;
+ int i;
+
+ if (num <= 0)
+ return;
+ size = num * sizeof(struct fuse_softc);
+ mem = malloc(size, M_FUSEFS, M_NOWAIT | M_ZERO);
+
+ if (mem == NULL) {
+ printf("fuse: WARNING no memory for fuse device\n");
+ return;
+ }
+ fuse_softc = (struct fuse_softc *)mem;
+ for (i = 0; i < num; i++) {
+ struct fuse_softc *sc = &fuse_softc[i];
+
+ SIMPLEQ_INIT(&sc->sc_fbufs_in);
+ SIMPLEQ_INIT(&sc->sc_fbufs_wait);
+ sc->sc_dev.dv_unit = i;
+ snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname),
+    "fuse%d", i);
+ device_ref(&sc->sc_dev);
+ }
+ numfuse = num;
+}
+
+int
+fuseopen(dev_t dev, int flags, int fmt, struct proc * p)
+{
+ struct fuse_softc *sc;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return (ENXIO);
+
+ sc = FUSE_DEV2SC(dev);
+
+ if (sc->sc_opened != FUSE_CLOSE || sc->sc_fmp)
+ return (EBUSY);
+
+ sc->sc_opened = FUSE_OPEN;
+ stat_opened_fusedev++;
+
+ return (0);
+}
+
+int
+fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
+{
+ struct fuse_softc *sc;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return (ENXIO);
+
+ sc = FUSE_DEV2SC(dev);
+ if (sc->sc_fmp) {
+ printf("libfuse close the device without umount\n");
+ sc->sc_fmp->sess_init = 0;
+ sc->sc_fmp = NULL;
+ }
+
+ sc->sc_opened = FUSE_CLOSE;
+ stat_opened_fusedev--;
+ return (0);
+}
+
+int
+fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
+{
+ struct fuse_softc *sc;
+ int error = 0;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return (ENXIO);
+
+ sc = FUSE_DEV2SC(dev);
+ switch (cmd) {
+ default:
+ DPRINTF("bad ioctl number %d\n", cmd);
+ return (ENODEV);
+ }
+
+ return (error);
+}
+
+int
+fuseread(dev_t dev, struct uio *uio, int ioflag)
+{
+ struct fuse_softc *sc;
+ struct fusebuf *fbuf;
+ int error = 0;
+ char *F_dat;
+ int remain;
+ int size;
+ size_t len;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return (ENXIO);
+
+ sc = FUSE_DEV2SC(dev);
+ if (sc->sc_opened != FUSE_OPEN)
+ return (ENODEV);
+
+ if (SIMPLEQ_EMPTY(&sc->sc_fbufs_in)) {
+
+ if (ioflag & O_NONBLOCK)
+ return (EAGAIN);
+
+ goto end;
+ }
+ fbuf = SIMPLEQ_FIRST(&sc->sc_fbufs_in);
+
+ /*
+ * If it was not taken by last read
+ * fetch the fb_hdr.
+ */
+ len = sizeof(struct fb_hdr);
+ if (fbuf->fb_resid == -1) {
+ /* we get the whole header or nothing */
+ if (uio->uio_resid < len)
+ return (EINVAL);
+
+ error = uiomove(fbuf, len, uio);
+ if (error)
+ goto end;
+
+#ifdef FUSE_DEBUG
+ fuse_dump_buff((char *)fbuf, len);
+#endif
+ fbuf->fb_resid = 0;
+ }
+
+ /* fetch F_dat if there is something present */
+ if ((fbuf->fb_len > 0) && uio->uio_resid) {
+ size = MIN(fbuf->fb_len - fbuf->fb_resid, uio->uio_resid);
+ F_dat = (char *)&fbuf->F_dat;
+
+ error = uiomove(&F_dat[fbuf->fb_resid], size, uio);
+ if (error)
+ goto end;
+
+#ifdef FUSE_DEBUG
+ fuse_dump_buff(&F_dat[fbuf->fb_resid], size);
+#endif
+ fbuf->fb_resid += size;
+ }
+
+ remain = (fbuf->fb_len - fbuf->fb_resid);
+ DPRINTF("size remaining : %i\n", remain);
+
+ /*
+ * fbuf moves from a simpleq to another
+ */
+ if (remain == 0) {
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_fbufs_in, fb_next);
+ stat_fbufs_in--;
+ SIMPLEQ_INSERT_TAIL(&sc->sc_fbufs_wait, fbuf, fb_next);
+ stat_fbufs_wait++;
+ }
+
+end:
+ return (error);
+}
+
+int
+fusewrite(dev_t dev, struct uio *uio, int ioflag)
+{
+ struct fusebuf *lastfbuf;
+ struct fuse_softc *sc;
+ struct fusebuf *fbuf;
+ struct fb_hdr hdr;
+ int error = 0;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return (ENXIO);
+
+ sc = FUSE_DEV2SC(dev);
+ if (uio->uio_resid < sizeof(hdr)) {
+ return (EINVAL);
+ }
+
+ /*
+ * get out header
+ */
+ if ((error = uiomove(&hdr, sizeof(hdr), uio)) != 0)
+ return (error);
+
+ SIMPLEQ_FOREACH(fbuf, &sc->sc_fbufs_wait, fb_next) {
+ if (fbuf->fb_uuid == hdr.fh_uuid) {
+ DPRINTF("catch unique %lu\n", fbuf->fb_uuid);
+ break;
+ }
+
+ lastfbuf = fbuf;
+ }
+
+#ifdef FUSE_DEBUG
+ fuse_dump_buff((char *)&hdr, sizeof(hdr));
+#endif
+
+ if (fbuf != NULL) {
+ memcpy(&fbuf->fb_hdr, &hdr, sizeof(fbuf->fb_hdr));
+
+ if (uio->uio_resid != hdr.fh_len ||
+    (uio->uio_resid != 0 && hdr.fh_err) ||
+    SIMPLEQ_EMPTY(&sc->sc_fbufs_wait) ) {
+ printf("corrupted fuse header or queue empty\n");
+ return (EINVAL);
+ }
+
+ if (uio->uio_resid > 0  && fbuf->fb_len > 0) {
+ error = uiomove(&fbuf->F_dat, fbuf->fb_len, uio);
+ if (error)
+ return error;
+#ifdef FUSE_DEBUG
+ fuse_dump_buff((char *)&fbuf->F_dat, fbuf->fb_len);
+#endif
+ }
+
+ if (!error) {
+ switch (fbuf->fb_type) {
+ case FBT_INIT:
+ sc->sc_fmp->sess_init = 1;
+ break ;
+ case FBT_DESTROY:
+ sc->sc_fmp = NULL;
+ break ;
+ }
+
+ wakeup(fbuf);
+ }
+
+ /* the fbuf could not be the HEAD fbuf */
+ if (fbuf == SIMPLEQ_FIRST(&sc->sc_fbufs_wait))
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_fbufs_wait, fb_next);
+ else
+ SIMPLEQ_REMOVE_AFTER(&sc->sc_fbufs_wait, lastfbuf,
+    fb_next);
+ stat_fbufs_wait--;
+
+ if (fbuf->fb_type == FBT_INIT)
+ pool_put(&fusefs_fbuf_pool, fbuf);
+
+ } else
+ error = EINVAL;
+
+ return (error);
+}
+
+int
+fusepoll(dev_t dev, int events, struct proc *p)
+{
+ struct fuse_softc *sc;
+ int revents = 0;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return (ENXIO);
+
+ sc = FUSE_DEV2SC(dev);
+ if (events & (POLLIN | POLLRDNORM))
+ if (!SIMPLEQ_EMPTY(&sc->sc_fbufs_in))
+ revents |= events & (POLLIN | POLLRDNORM);
+
+ if (events & (POLLOUT | POLLWRNORM))
+ revents |= events & (POLLOUT | POLLWRNORM);
+
+ if (revents == 0)
+ if (events & (POLLIN | POLLRDNORM))
+ selrecord(p, &sc->sc_rsel);
+
+ return (revents);
+}
+
+int
+fusekqfilter(dev_t dev, struct knote *kn)
+{
+ struct fuse_softc *sc;
+ struct klist *klist;
+
+ if (FUSE_UNIT(dev) >= numfuse)
+ return (ENXIO);
+
+ sc = FUSE_DEV2SC(dev);
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ klist = &sc->sc_rsel.si_note;
+ kn->kn_fop = &fuse_rd_filtops;
+ break;
+ case EVFILT_WRITE:
+ klist = &sc->sc_rsel.si_note;
+ kn->kn_fop = &fuse_seltrue_filtops;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ kn->kn_hook = sc;
+
+ SLIST_INSERT_HEAD(klist, kn, kn_selnext);
+
+ return (0);
+}
+
+void
+filt_fuse_rdetach(struct knote *kn)
+{
+ struct fuse_softc *sc = kn->kn_hook;
+ struct klist *klist = &sc->sc_rsel.si_note;
+
+ SLIST_REMOVE(klist, kn, knote, kn_selnext);
+}
+
+int
+filt_fuse_read(struct knote *kn, long hint)
+{
+ struct fuse_softc *sc = kn->kn_hook;
+ int event = 0;
+
+ if (!SIMPLEQ_EMPTY(&sc->sc_fbufs_in))
+ event = 1;
+
+ return (event);
+}
Index: miscfs/fuse/fuse_file.c
===================================================================
RCS file: miscfs/fuse/fuse_file.c
diff -N miscfs/fuse/fuse_file.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_file.c 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,87 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/pool.h>
+#include <sys/statvfs.h>
+#include <sys/vnode.h>
+#include <sys/fusebuf.h>
+
+#include "fusefs_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG_VNOP
+#define DPRINTF(fmt, arg...) printf("fuse vnop: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+int
+fusefs_file_open(struct fusefs_mnt *fmp, struct fusefs_node *ip,
+    enum fufh_type fufh_type, int flags, int isdir, struct proc *p)
+{
+ struct fusebuf *fbuf;
+ int error = 0;
+
+ fbuf = fb_setup(FUSEFDSIZE, ip->ufs_ino.i_number,
+    ((isdir) ? FBT_OPENDIR : FBT_OPEN), p);
+ fbuf->fb_io_flags = flags;
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+ }
+
+ ip->fufh[fufh_type].fh_id = fbuf->fb_io_fd;
+ ip->fufh[fufh_type].fh_type = fufh_type;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (0);
+}
+
+int
+fusefs_file_close(struct fusefs_mnt *fmp, struct fusefs_node * ip,
+    enum fufh_type fufh_type, int flags, int isdir, struct proc *p)
+{
+ struct fusebuf *fbuf;
+ int error = 0;
+
+ fbuf = fb_setup(FUSEFDSIZE, ip->ufs_ino.i_number,
+    ((isdir) ? FBT_RELEASEDIR : FBT_RELEASE), p);
+ fbuf->fb_io_fd  = ip->fufh[fufh_type].fh_id;
+ fbuf->fb_io_flags = flags;
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error)
+ printf("fuse file error %d\n", error);
+
+ ip->fufh[fufh_type].fh_id = (uint64_t)-1;
+ ip->fufh[fufh_type].fh_type = FUFH_INVALID;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+}
+
+uint64_t
+fusefs_fd_get(struct fusefs_node *ip, enum fufh_type type)
+{
+ if (ip->fufh[type].fh_type == FUFH_INVALID)
+ type = FUFH_RDWR;
+
+ return (ip->fufh[type].fh_id);
+}
Index: miscfs/fuse/fuse_lookup.c
===================================================================
RCS file: miscfs/fuse/fuse_lookup.c
diff -N miscfs/fuse/fuse_lookup.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_lookup.c 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,215 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/pool.h>
+#include <sys/statvfs.h>
+#include <sys/vnode.h>
+#include <sys/fusebuf.h>
+
+#include "fusefs_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG_VNOP
+#define DPRINTF(fmt, arg...) printf("fuse vnop: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+int fusefs_lookup(void *);
+
+int
+fusefs_lookup(void *v)
+{
+ struct vop_lookup_args *ap = v;
+ struct vnode *vdp; /* vnode for directory being searched */
+ struct fusefs_node *dp; /* inode for directory being searched */
+ struct fusefs_mnt *fmp; /* file system that directory is in */
+ int lockparent; /* 1 => lockparent flag is set */
+ struct vnode *tdp; /* returned by VOP_VGET */
+ struct fusebuf *fbuf = NULL;
+ struct vnode **vpp = ap->a_vpp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct ucred *cred = cnp->cn_cred;
+ int flags;
+ int nameiop = cnp->cn_nameiop;
+ int error = 0;
+ uint64_t nid;
+
+ flags = cnp->cn_flags;
+ *vpp = NULL;
+ vdp = ap->a_dvp;
+ dp = VTOI(vdp);
+ fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump;
+ lockparent = flags & LOCKPARENT;
+
+ DPRINTF("lookup path %s\n", cnp->cn_pnbuf);
+ DPRINTF("lookup file %s\n", cnp->cn_nameptr);
+
+ if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0)
+ return (error);
+
+ if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
+    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+ return (EROFS);
+
+ if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
+ return (error);
+
+ if (flags & ISDOTDOT) {
+ /* got ".." */
+ nid = dp->parent;
+ if (nid == 0)
+ return (ENOENT);
+ } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
+ nid = dp->ufs_ino.i_number;
+ } else {
+ /* got a real entry */
+ fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1,
+    dp->ufs_ino.i_number, FBT_LOOKUP, p);
+
+ memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
+ fbuf->fb_dat[cnp->cn_namelen] = '\0';
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ /* tsleep return */
+ if (error == EWOULDBLOCK)
+ goto out;
+
+ if (error) {
+ if ((nameiop == CREATE || nameiop == RENAME) &&
+    (flags & ISLASTCN) ) {
+ if (vdp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+
+ cnp->cn_flags |= SAVENAME;
+
+ if (!lockparent) {
+ VOP_UNLOCK(vdp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+
+ error = EJUSTRETURN;
+ goto out;
+ }
+
+ error = ENOENT;
+ goto out;
+ }
+
+ nid = fbuf->fb_vattr.va_fileid;
+ }
+
+ if (nameiop == DELETE && (flags & ISLASTCN)) {
+ /*
+ * Write access to directory required to delete files.
+ */
+ error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc);
+ if (error != 0) {
+ if (fbuf)
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+ }
+
+ cnp->cn_flags |= SAVENAME;
+ }
+
+ if (nameiop == RENAME && (flags & ISLASTCN)) {
+ /*
+ * Write access to directory required to delete files.
+ */
+ if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0)
+ return (error);
+
+ if (nid == VTOI(vdp)->ufs_ino.i_number) {
+ error = EISDIR;
+ goto out;
+ }
+
+ cnp->cn_flags |= SAVENAME;
+
+ goto out;
+ }
+
+ if (flags & ISDOTDOT) {
+ VOP_UNLOCK(vdp, 0, p); /* race to get the inode */
+ cnp->cn_flags |= PDIRUNLOCK;
+
+ error = VFS_VGET(fmp->mp, nid, &tdp);
+
+ if (error) {
+ if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
+ cnp->cn_flags &= ~PDIRUNLOCK;
+
+ return (error);
+ }
+
+ if (lockparent && (flags & ISLASTCN)) {
+ if ((error = vn_lock(vdp, LK_EXCLUSIVE, p))) {
+ vput(tdp);
+ return (error);
+ }
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ }
+ *vpp = tdp;
+
+ } else if (nid == dp->ufs_ino.i_number) {
+ vref(vdp);
+ *vpp = vdp;
+ error = 0;
+ } else {
+ error = VFS_VGET(fmp->mp, nid, &tdp);
+
+ if (!error) {
+ tdp->v_type = IFTOVT(fbuf->fb_vattr.va_mode);
+ VTOI(tdp)->vtype = tdp->v_type;
+ }
+
+ update_vattr(fmp->mp, &fbuf->fb_vattr);
+ memcpy(&(VTOI(tdp)->cached_attrs), &fbuf->fb_vattr,
+    sizeof(struct vattr));
+
+ if (error) {
+ if (fbuf)
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+ }
+
+ if (vdp != NULL && vdp->v_type == VDIR)
+ VTOI(tdp)->parent = dp->ufs_ino.i_number;
+
+ if (!lockparent || !(flags & ISLASTCN)) {
+ VOP_UNLOCK(vdp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+
+ *vpp = tdp;
+ }
+
+out:
+ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE &&
+    nameiop != DELETE )
+ cache_enter(vdp, *vpp, cnp);
+
+ if (fbuf)
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+}
Index: miscfs/fuse/fuse_vfsops.c
===================================================================
RCS file: miscfs/fuse/fuse_vfsops.c
diff -N miscfs/fuse/fuse_vfsops.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_vfsops.c 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,324 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/pool.h>
+#include <sys/statvfs.h>
+#include <sys/sysctl.h>
+#include <sys/vnode.h>
+#include <sys/fusebuf.h>
+
+#include "fusefs_node.h"
+#include "fusefs.h"
+
+int fusefs_mount(struct mount *, const char *, void *, struct nameidata *,
+    struct proc *);
+int fusefs_start(struct mount *, int, struct proc *);
+int fusefs_unmount(struct mount *, int, struct proc *);
+int fusefs_root(struct mount *, struct vnode **);
+int fusefs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *);
+int fusefs_statfs(struct mount *, struct statfs *, struct proc *);
+int fusefs_sync(struct mount *, int, struct ucred *, struct proc *);
+int fusefs_vget(struct mount *, ino_t, struct vnode **);
+int fusefs_fhtovp(struct mount *, struct fid *, struct vnode **);
+int fusefs_vptofh(struct vnode *, struct fid *);
+int fusefs_init(struct vfsconf *);
+int fusefs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
+    struct proc *);
+int fusefs_checkexp(struct mount *, struct mbuf *, int *,
+    struct ucred **);
+
+const struct vfsops fusefs_vfsops = {
+ fusefs_mount,
+ fusefs_start,
+ fusefs_unmount,
+ fusefs_root,
+ fusefs_quotactl,
+ fusefs_statfs,
+ fusefs_sync,
+ fusefs_vget,
+ fusefs_fhtovp,
+ fusefs_vptofh,
+ fusefs_init,
+ fusefs_sysctl,
+ fusefs_checkexp
+};
+
+struct pool fusefs_fbuf_pool;
+
+int
+fusefs_mount(struct mount *mp, const char *path, void *data,
+    struct nameidata *ndp, struct proc *p)
+{
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ struct fusefs_args args;
+ int error;
+
+ if (mp->mnt_flag & MNT_UPDATE)
+ return (EOPNOTSUPP);
+
+ error = copyin(data, &args, sizeof(struct fusefs_args));
+ if (error)
+ return (error);
+
+ fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO);
+ fmp->mp = mp;
+ fmp->sess_init = 0;
+ fmp->dev = args.dev;
+ printf("fusefs: mount dev %i\n", fmp->dev);
+ mp->mnt_data = fmp;
+
+ mp->mnt_flag |= MNT_LOCAL;
+ vfs_getnewfsid(mp);
+
+ bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
+ strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
+ bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
+ bcopy("fusefs", mp->mnt_stat.f_mntfromname, sizeof("fusefs"));
+
+ fuse_device_set_fmp(fmp);
+ fbuf = fb_setup(0, 0, FBT_INIT, p);
+
+ /* cannot tsleep on mount */
+ fuse_device_queue_fbuf(fmp->dev, fbuf);
+
+ return (0);
+}
+
+int
+fusefs_start(struct mount *mp, int flags, struct proc *p)
+{
+ return (0);
+}
+
+int
+fusefs_unmount(struct mount *mp, int mntflags, struct proc *p)
+{
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ extern int doforce;
+ int flags = 0;
+ int error;
+
+ fmp = VFSTOFUSEFS(mp);
+
+ if (fmp->sess_init) {
+
+ fmp->sess_init = 0;
+ fbuf = fb_setup(0, 0, FBT_DESTROY, p);
+
+ error = fb_queue(fmp->dev, fbuf);
+ pool_put(&fusefs_fbuf_pool, fbuf);
+
+ if (error)
+ printf("error from fuse\n");
+
+ } else {
+ fuse_device_cleanup(fmp->dev, NULL);
+ }
+
+ if (mntflags & MNT_FORCE) {
+ /* fusefs can never be rootfs so don't check for it */
+ if (!doforce)
+ return (EINVAL);
+
+ flags |= FORCECLOSE;
+ }
+
+ if ((error = vflush(mp, 0, flags)))
+ return (error);
+
+ free(fmp, M_FUSEFS);
+
+ return (error);
+}
+
+int
+fusefs_root(struct mount *mp, struct vnode **vpp)
+{
+ struct vnode *nvp;
+ struct fusefs_node *ip;
+ int error;
+
+ if ((error = VFS_VGET(mp, (ino_t)FUSE_ROOTINO, &nvp)) != 0)
+ return (error);
+
+ ip = VTOI(nvp);
+ nvp->v_type = VDIR;
+ ip->vtype = VDIR;
+
+ *vpp = nvp;
+ return (0);
+}
+
+int fusefs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
+    struct proc *p)
+{
+ return (0);
+}
+
+int fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
+{
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ int error;
+
+ fmp = VFSTOFUSEFS(mp);
+
+ if (fmp->sess_init) {
+ fbuf = fb_setup(0, FUSE_ROOT_ID, FBT_STATFS, p);
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+ }
+
+ sbp->f_bavail = fbuf->fb_stat.f_bavail;
+ sbp->f_bfree = fbuf->fb_stat.f_bfree;
+ sbp->f_blocks = fbuf->fb_stat.f_blocks;
+ sbp->f_files = fbuf->fb_stat.f_files;
+ sbp->f_ffree = fbuf->fb_stat.f_ffree;
+ sbp->f_bsize = fbuf->fb_stat.f_frsize;
+ sbp->f_namemax = fbuf->fb_stat.f_namemax;
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ } else {
+ sbp->f_bavail = 0;
+ sbp->f_bfree = 0;
+ sbp->f_blocks = 0;
+ sbp->f_ffree = 0;
+ sbp->f_files = 0;
+ sbp->f_bsize = 0;
+ sbp->f_namemax = 0;
+ }
+
+ return (0);
+}
+
+int fusefs_sync(struct mount *mp, int waitfor, struct ucred *cred,
+    struct proc *p)
+{
+ return (0);
+}
+
+int fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
+{
+ struct fusefs_mnt *fmp;
+ struct fusefs_node *ip;
+ struct vnode *nvp;
+ int i;
+ int error;
+retry:
+ fmp = VFSTOFUSEFS(mp);
+ /*
+ * check if vnode is in hash.
+ */
+ if ((*vpp = ufs_ihashget(fmp->dev, ino)) != NULLVP)
+ return (0);
+
+ /*
+ * if not create it
+ */
+ if ((error = getnewvnode(VT_FUSEFS, mp, &fusefs_vops, &nvp)) != 0) {
+ printf("fuse: getnewvnode error\n");
+ *vpp = NULLVP;
+ return (error);
+ }
+
+ ip = malloc(sizeof(*ip), M_FUSEFS, M_WAITOK | M_ZERO);
+ lockinit(&ip->ufs_ino.i_lock, PINOD, "fuseinode", 0, 0);
+ nvp->v_data = ip;
+ ip->ufs_ino.i_vnode = nvp;
+ ip->ufs_ino.i_dev = fmp->dev;
+ ip->ufs_ino.i_number = ino;
+ ip->parent = 0;
+
+ for (i = 0; i < FUFH_MAXTYPE; i++)
+ ip->fufh[i].fh_type = FUFH_INVALID;
+
+ error = ufs_ihashins(&ip->ufs_ino);
+ if (error) {
+ vrele(nvp);
+
+ if (error == EEXIST)
+ goto retry;
+
+ return (error);
+ }
+
+ ip->ufs_ino.i_ump = (struct ufsmount *)fmp;
+
+ if (ino == FUSE_ROOTINO)
+ nvp->v_flag |= VROOT;
+
+ *vpp = nvp;
+
+ return (0);
+}
+
+int fusefs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
+{
+ return (0);
+}
+
+int fusefs_vptofh(struct vnode *vp, struct fid *fhp)
+{
+ return (0);
+}
+
+int fusefs_init(struct vfsconf *vfc)
+{
+ pool_init(&fusefs_fbuf_pool, sizeof(struct fusebuf), 0, 0, 0,
+    "fmsg", &pool_allocator_nointr);
+
+ return (0);
+}
+
+int fusefs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
+    void *newp, size_t newlen, struct proc *p)
+{
+ extern int stat_fbufs_in, stat_fbufs_wait, stat_opened_fusedev;
+
+ /* all sysctl names at this level are terminal */
+ if (namelen != 1)
+ return (ENOTDIR); /* overloaded */
+
+ switch (name[0]) {
+ case FUSEFS_NB_OPENDEVS:
+ return (sysctl_rdint(oldp, oldlenp, newp,
+    stat_opened_fusedev));
+ case FUSEFS_INFBUFS:
+ return (sysctl_rdint(oldp, oldlenp, newp, stat_fbufs_in));
+ case FUSEFS_WAITFBUFS:
+ return (sysctl_rdint(oldp, oldlenp, newp, stat_fbufs_wait));
+ case FUSEFS_POOL_NBPAGES:
+ return (sysctl_rdint(oldp, oldlenp, newp,
+    fusefs_fbuf_pool.pr_npages));
+ default:
+ return (EOPNOTSUPP);
+ }
+}
+
+int fusefs_checkexp(struct mount *mp, struct mbuf *nam, int *extflagsp,
+    struct ucred **credanonp)
+{
+ return (0);
+}
Index: miscfs/fuse/fuse_vnops.c
===================================================================
RCS file: miscfs/fuse/fuse_vnops.c
diff -N miscfs/fuse/fuse_vnops.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fuse_vnops.c 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,1354 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/dirent.h>
+#include <sys/fcntl.h>
+#include <sys/lockf.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/poll.h>
+#include <sys/pool.h>
+#include <sys/specdev.h>
+#include <sys/statvfs.h>
+#include <sys/vnode.h>
+#include <sys/fusebuf.h>
+
+#include "fusefs_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG_VNOP
+#define DPRINTF(fmt, arg...) printf("fuse vnop: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+/* Prototypes for fusefs vnode ops */
+int fusefs_lookup(void *);
+int fusefs_open(void *);
+int fusefs_close(void *);
+int fusefs_access(void *);
+int fusefs_getattr(void *);
+int fusefs_setattr(void *);
+int fusefs_ioctl(void *);
+int fusefs_link(void *);
+int fusefs_symlink(void *);
+int fusefs_readdir(void *);
+int fusefs_readlink(void *);
+int fusefs_inactive(void *);
+int fusefs_reclaim(void *);
+int fusefs_print(void *);
+int fusefs_create(void *);
+int fusefs_mknod(void *);
+int fusefs_read(void *);
+int fusefs_write(void *);
+int fusefs_poll(void *);
+int fusefs_remove(void *);
+int fusefs_rename(void *);
+int fusefs_mkdir(void *);
+int fusefs_rmdir(void *);
+int fusefs_strategy(void *);
+int fusefs_lock(void *);
+int fusefs_unlock(void *);
+int fusefs_islocked(void *);
+int fusefs_advlock(void *);
+
+struct vops fusefs_vops = {
+ .vop_lookup = fusefs_lookup,
+ .vop_create = fusefs_create,
+ .vop_mknod = fusefs_mknod,
+ .vop_open = fusefs_open,
+ .vop_close = fusefs_close,
+ .vop_access = fusefs_access,
+ .vop_getattr = fusefs_getattr,
+ .vop_setattr = fusefs_setattr,
+ .vop_read = fusefs_read,
+ .vop_write = fusefs_write,
+ .vop_ioctl = fusefs_ioctl,
+ .vop_poll = fusefs_poll,
+ .vop_fsync = nullop,
+ .vop_remove = fusefs_remove,
+ .vop_link = fusefs_link,
+ .vop_rename = fusefs_rename,
+ .vop_mkdir = fusefs_mkdir,
+ .vop_rmdir = fusefs_rmdir,
+ .vop_symlink = fusefs_symlink,
+ .vop_readdir = fusefs_readdir,
+ .vop_readlink = fusefs_readlink,
+ .vop_abortop = vop_generic_abortop,
+ .vop_inactive = fusefs_inactive,
+ .vop_reclaim = fusefs_reclaim,
+ .vop_lock = fusefs_lock,
+ .vop_unlock = fusefs_unlock,
+ .vop_bmap = vop_generic_bmap,
+ .vop_strategy = fusefs_strategy,
+ .vop_print = fusefs_print,
+ .vop_islocked = fusefs_islocked,
+ .vop_pathconf = spec_pathconf,
+ .vop_advlock = fusefs_advlock,
+};
+
+void
+update_vattr(struct mount *mp, struct vattr *v)
+{
+ v->va_fsid = mp->mnt_stat.f_fsid.val[0];
+ v->va_type = IFTOVT(v->va_mode);
+#if (S_BLKSIZE == 512)
+ v->va_bytes = v->va_bytes << 9;
+#else
+ v->va_bytes = v->va_bytes * S_BLKSIZE;
+#endif
+ v->va_mode = v->va_mode & ~S_IFMT;
+}
+
+int
+fusefs_open(void *v)
+{
+ struct vop_open_args *ap;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ enum fufh_type fufh_type = FUFH_RDONLY;
+ int flags = O_RDONLY;
+ int error;
+ int isdir;
+
+ DPRINTF("fusefs_open\n");
+
+ ap = v;
+ ip = VTOI(ap->a_vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init)
+ return (0);
+
+ DPRINTF("inode = %i mode=0x%x\n", ip->ufs_ino.i_number, ap->a_mode);
+
+ isdir = 0;
+ if (ip->vtype == VDIR)
+ isdir = 1;
+ else {
+ if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) {
+ fufh_type = FUFH_RDWR;
+ flags = O_RDWR;
+ } else if (ap->a_mode  & (FWRITE)) {
+ fufh_type = FUFH_WRONLY;
+ flags = O_WRONLY;
+ }
+ }
+
+ /* already open i think all is ok */
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+ return (0);
+
+ error = fusefs_file_open(fmp, ip, fufh_type, flags, isdir, ap->a_p);
+ if (error)
+ return (error);
+
+ DPRINTF("file open fd : %i\n", ip->fufh[fufh_type].fh_id);
+
+ return (error);
+}
+
+int
+fusefs_close(void *v)
+{
+ struct vop_close_args *ap;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ enum fufh_type fufh_type = FUFH_RDONLY;
+ int isdir, i;
+
+ DPRINTF("fusefs_close\n");
+
+ ap = v;
+ ip = VTOI(ap->a_vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init)
+ return (0);
+
+ if (ip->vtype == VDIR) {
+ isdir = 1;
+
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+ return (fusefs_file_close(fmp, ip, fufh_type, O_RDONLY,
+    isdir, ap->a_p));
+ } else {
+ if (ap->a_fflag & IO_NDELAY)
+ return (0);
+
+ if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE))
+ fufh_type = FUFH_RDWR;
+ else if (ap->a_fflag  & (FWRITE))
+ fufh_type = FUFH_WRONLY;
+ }
+
+ /*
+ * if fh not valid lookup for another valid fh in vnode.
+ * Do we need panic if there's not a valid fh ?
+ */
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) {
+ for (i = 0; i < FUFH_MAXTYPE; i++)
+ if (ip->fufh[fufh_type].fh_type != FUFH_INVALID)
+ break;
+ return (0);
+ }
+
+ return (0);
+}
+
+int
+fusefs_access(void *v)
+{
+ struct vop_access_args *ap;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ struct proc *p;
+ uint32_t mask = 0;
+ int error = 0;
+
+ DPRINTF("fusefs_access\n");
+
+ ap = v;
+ p = ap->a_p;
+ ip = VTOI(ap->a_vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_ACCESS))
+ goto system_check;
+
+ if (ap->a_vp->v_type == VLNK)
+ goto system_check;
+
+ if (ap->a_vp->v_type == VREG && (ap->a_mode & VWRITE & VEXEC))
+ goto system_check;
+
+ if ((ap->a_mode & VWRITE) && (fmp->mp->mnt_flag & MNT_RDONLY))
+ return (EACCES);
+
+ if ((ap->a_mode & VWRITE) != 0)
+ mask |= 0x2;
+
+ if ((ap->a_mode & VREAD) != 0)
+ mask |= 0x4;
+
+ if ((ap->a_mode & VEXEC) != 0)
+ mask |= 0x1;
+
+ fbuf = fb_setup(FUSEFDSIZE, ip->ufs_ino.i_number, FBT_ACCESS, p);
+ fbuf->fb_io_mode = mask;
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error) {
+ if (error == ENOSYS) {
+ fmp->undef_op |= UNDEF_ACCESS;
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto system_check;
+ }
+
+ DPRINTF("access error %i\n", error);
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+ }
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+
+system_check:
+ return (vaccess(ap->a_vp->v_type, ip->cached_attrs.va_mode & ALLPERMS,
+    ip->cached_attrs.va_uid, ip->cached_attrs.va_gid, ap->a_mode,
+    ap->a_cred));
+}
+
+int
+fusefs_getattr(void *v)
+{
+ struct vop_getattr_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fusefs_mnt *fmp;
+ struct vattr *vap = ap->a_vap;
+ struct proc *p = ap->a_p;
+ struct fusefs_node *ip;
+ struct fusebuf *fbuf;
+ int error = 0;
+
+ DPRINTF("fusefs_getattr\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init)
+ goto fake;
+
+ fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_GETATTR, p);
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error) {
+ DPRINTF("getattr error\n");
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+ }
+
+ /* check if we got a response */
+ if (fbuf->fb_len == 0) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto fake;
+ }
+
+ update_vattr(fmp->mp, &fbuf->fb_vattr);
+ memcpy(vap, &fbuf->fb_vattr, sizeof(*vap));
+ memcpy(&ip->cached_attrs, vap, sizeof(*vap));
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+fake:
+ bzero(vap, sizeof(*vap));
+ vap->va_type = vp->v_type;
+ return (0);
+}
+
+int
+fusefs_setattr(void *v)
+{
+ struct vop_setattr_args *ap = v;
+ struct vattr *vap = ap->a_vap;
+ struct vnode *vp = ap->a_vp;
+ struct fusefs_node *ip = VTOI(vp);
+ struct proc *p = ap->a_p;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ struct fb_io *io;
+ int error = 0;
+
+ DPRINTF("fusefs_setattr\n");
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+ /*
+ * Check for unsettable attributes.
+ */
+ if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
+ (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
+ (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
+ ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL))
+ return (EINVAL);
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_SETATTR))
+ return (ENXIO);
+
+ fbuf = fb_setup(FUSEFDSIZE + sizeof(*io), ip->ufs_ino.i_number,
+    FBT_SETATTR, p);
+ io = fbtod(fbuf, struct fb_io *);
+ io->fi_flags = 0;
+
+ if (vap->va_uid != (uid_t)VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+ error = EROFS;
+ goto out;
+ }
+ fbuf->fb_vattr.va_uid = vap->va_uid;
+ io->fi_flags |= FUSE_FATTR_UID;
+ }
+
+ if (vap->va_gid != (gid_t)VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+ error = EROFS;
+ goto out;
+ }
+ fbuf->fb_vattr.va_gid = vap->va_gid;
+ io->fi_flags |= FUSE_FATTR_GID;
+ }
+
+ if (vap->va_size != VNOVAL) {
+ switch (vp->v_type) {
+ case VDIR:
+ error = EISDIR;
+ goto out;
+ case VLNK:
+ case VREG:
+ if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+ error = EROFS;
+ goto out;
+ }
+ default:
+ break;
+ }
+
+ /*XXX to finish*/
+ }
+
+ if (vap->va_atime.tv_sec != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+ error = EROFS;
+ goto out;
+ }
+ fbuf->fb_vattr.va_atime.tv_sec = vap->va_atime.tv_sec;
+ fbuf->fb_vattr.va_atime.tv_nsec = vap->va_atime.tv_nsec;
+ io->fi_flags |= FUSE_FATTR_ATIME;
+ }
+
+ if (vap->va_mtime.tv_sec != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+ error = EROFS;
+ goto out;
+ }
+ fbuf->fb_vattr.va_mtime.tv_sec = vap->va_mtime.tv_sec;
+ fbuf->fb_vattr.va_mtime.tv_nsec = vap->va_mtime.tv_nsec;
+ io->fi_flags |= FUSE_FATTR_MTIME;
+ }
+
+ if (vap->va_mode != (mode_t)VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+ error = EROFS;
+ goto out;
+ }
+ fbuf->fb_vattr.va_mode = vap->va_mode & ALLPERMS;
+ io->fi_flags |= FUSE_FATTR_MODE;
+ }
+
+ if (!io->fi_flags) {
+ goto out;
+ }
+
+ if (io->fi_flags & FUSE_FATTR_SIZE && vp->v_type == VDIR) {
+ error = EISDIR;
+ goto out;
+ }
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_SETATTR;
+ goto out;
+ }
+
+ update_vattr(fmp->mp, &fbuf->fb_vattr);
+ memcpy(vap, &fbuf->fb_vattr, sizeof(*vap));
+
+out:
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+}
+
+int
+fusefs_ioctl(void *v)
+{
+ DPRINTF("fusefs_ioctl\n");
+ return (ENOTTY);
+}
+
+int
+fusefs_link(void *v)
+{
+ struct vop_link_args *ap = v;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp = ap->a_vp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct fusefs_mnt *fmp;
+ struct fusefs_node *ip;
+ struct fusefs_node *dip;
+ struct fusebuf *fbuf;
+ int error = 0;
+
+ DPRINTF("fusefs_link\n");
+
+ if (vp->v_type == VDIR) {
+ VOP_ABORTOP(dvp, cnp);
+ error = EISDIR;
+ goto out2;
+ }
+ if (dvp->v_mount != vp->v_mount) {
+ VOP_ABORTOP(dvp, cnp);
+ error = EXDEV;
+ goto out2;
+ }
+ if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
+ VOP_ABORTOP(dvp, cnp);
+ goto out2;
+ }
+
+ ip = VTOI(vp);
+ dip = VTOI(dvp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_LINK))
+ goto out1;
+
+ fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1,
+    dip->ufs_ino.i_number, FBT_LINK, p);
+
+ fbuf->fb_io_ino = ip->ufs_ino.i_number;
+ memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
+ fbuf->fb_dat[cnp->cn_namelen] = '\0';
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_LINK;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out1;
+ }
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+
+out1:
+ if (dvp != vp)
+ VOP_UNLOCK(vp, 0, p);
+out2:
+ vput(dvp);
+ return (error);
+}
+
+int
+fusefs_symlink(void *v)
+{
+ struct vop_symlink_args *ap = v;
+ struct vnode **vpp = ap->a_vpp;
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode *dvp = ap->a_dvp;
+ struct proc *p = cnp->cn_proc;
+ char *target = ap->a_target;
+ struct fusefs_node *dp;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ struct vnode *tdp;
+ int error = 0;
+ int len;
+
+ DPRINTF("fusefs_symlink\n");
+ dp = VTOI(dvp);
+ fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump;
+
+ if (!fmp->sess_init  || (fmp->undef_op & UNDEF_SYMLINK)) {
+ error = ENOSYS;
+ goto bad;
+ }
+
+ len = strlen(target) + 1;
+
+ fbuf = fb_setup(FUSEFDSIZE + len + cnp->cn_namelen + 1,
+    dp->ufs_ino.i_number, FBT_SYMLINK, p);
+
+ memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
+ fbuf->fb_dat[cnp->cn_namelen] = '\0';
+ memcpy(&fbuf->fb_dat[cnp->cn_namelen + 1], target, len);
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_SYMLINK;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto bad;
+ }
+
+ if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto bad;
+ }
+
+ tdp->v_type = VLNK;
+ VTOI(tdp)->vtype = tdp->v_type;
+ VTOI(tdp)->parent = dp->ufs_ino.i_number;
+
+ *vpp = tdp;
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ vput(tdp);
+bad:
+ vput(dvp);
+ return (error);
+}
+
+int
+fusefs_readdir(void *v)
+{
+ struct vop_readdir_args *ap = v;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ struct vnode *vp;
+ struct proc *p;
+ struct uio *uio;
+ int error = 0;
+
+ vp = ap->a_vp;
+ uio = ap->a_uio;
+ p = uio->uio_procp;
+
+ ip = VTOI(vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init)
+ return (0);
+
+ DPRINTF("fusefs_readdir\n");
+ DPRINTF("uio resid 0x%x\n", uio->uio_resid);
+
+ if (uio->uio_resid < sizeof(struct dirent))
+ return (EINVAL);
+
+ while (uio->uio_resid > 0) {
+ fbuf = fb_setup(FUSEFDSIZE, ip->ufs_ino.i_number, FBT_READDIR,
+    p);
+
+ if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) {
+ /* TODO open the file */
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+ }
+ fbuf->fb_io_fd = ip->fufh[FUFH_RDONLY].fh_id;
+ fbuf->fb_io_off = uio->uio_offset;
+ fbuf->fb_io_len = MIN(uio->uio_resid, FUSELEN);
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ break;
+ }
+
+ /*ack end of readdir */
+ if (fbdatsize(fbuf) == 0) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ break;
+ }
+
+ if ((error = uiomove(fbuf->fb_dat, fbdatsize(fbuf), uio))) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ break;
+ }
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ }
+
+ return (error);
+}
+
+int
+fusefs_inactive(void *v)
+{
+ struct vop_inactive_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
+ struct fusefs_node *ip = VTOI(vp);
+ struct fusefs_filehandle *fufh = NULL;
+ struct fusefs_mnt *fmp;
+ int error = 0;
+ int type;
+
+ DPRINTF("fusefs_inactive\n");
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ for (type = 0; type < FUFH_MAXTYPE; type++) {
+ fufh = &(ip->fufh[type]);
+ if (fufh->fh_type != FUFH_INVALID)
+ fusefs_file_close(fmp, ip, fufh->fh_type, type,
+    (ip->vtype == VDIR), ap->a_p);
+ }
+
+ VOP_UNLOCK(vp, 0, p);
+
+ /* not sure if it is ok to do like that ...*/
+ if (ip->cached_attrs.va_mode == 0)
+ vrecycle(vp, p);
+
+ return (error);
+}
+
+int
+fusefs_readlink(void *v)
+{
+ struct vop_readlink_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ struct uio *uio;
+ struct proc *p;
+ int error = 0;
+
+ DPRINTF("fusefs_readlink\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+ uio = ap->a_uio;
+ p = uio->uio_procp;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_READLINK)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READLINK, p);
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_READLINK;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out;
+ }
+
+ error = uiomove(fbuf->fb_dat, fbdatsize(fbuf), uio);
+ pool_put(&fusefs_fbuf_pool, fbuf);
+out:
+ return (error);
+}
+
+int
+fusefs_reclaim(void *v)
+{
+ struct vop_reclaim_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fusefs_node *ip = VTOI(vp);
+ struct fusefs_filehandle *fufh = NULL;
+ struct fusefs_mnt *fmp;
+ int type;
+
+ DPRINTF("fusefs_reclaim\n");
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ /*close opened files*/
+ for (type = 0; type < FUFH_MAXTYPE; type++) {
+ fufh = &(ip->fufh[type]);
+ if (fufh->fh_type != FUFH_INVALID) {
+ printf("FUSE: vnode being reclaimed is valid");
+ fusefs_file_close(fmp, ip, fufh->fh_type, type,
+    (ip->vtype == VDIR), ap->a_p);
+ }
+ }
+ /*
+ * Purge old data structures associated with the inode.
+ */
+ ip->parent = 0;
+
+ /*
+ * Remove the inode from its hash chain.
+ */
+ ufs_ihashrem(&ip->ufs_ino);
+ cache_purge(vp);
+
+ free(ip, M_FUSEFS);
+ vp->v_data = NULL;
+ return (0);
+}
+
+int
+fusefs_print(void *v)
+{
+ struct vop_print_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct fusefs_node *ip = VTOI(vp);
+
+ /* Complete the information given by vprint(). */
+ printf("tag VT_FUSE, hash id %u ", ip->ufs_ino.i_number);
+ lockmgr_printinfo(&ip->ufs_ino.i_lock);
+ printf("\n");
+ return (0);
+}
+
+int
+fusefs_create(void *v)
+{
+ struct vop_create_args *ap = v;
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode **vpp = ap->a_vpp;
+ struct vnode *dvp = ap->a_dvp;
+ struct vattr *vap = ap->a_vap;
+ struct proc *p = cnp->cn_proc;
+ struct vnode *tdp = NULL;
+ struct fusefs_mnt *fmp;
+ struct fusefs_node *ip;
+ struct fusebuf *fbuf;
+ int error = 0;
+ mode_t mode;
+
+ DPRINTF("fusefs_create(cnp %08x, vap %08x\n", cnp, vap);
+
+ ip = VTOI(dvp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+ mode = MAKEIMODE(vap->va_type, vap->va_mode);
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_CREATE)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1,
+    ip->ufs_ino.i_number, FBT_CREATE, p);
+
+ fbuf->fb_io_mode = mode;
+ fbuf->fb_io_flags = O_CREAT | O_RDWR;
+
+ memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
+ fbuf->fb_dat[cnp->cn_namelen] = '\0';
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_CREATE;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out;
+ }
+
+ if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out;
+ }
+
+ tdp->v_type = IFTOVT(fbuf->fb_io_mode);
+ VTOI(tdp)->vtype = tdp->v_type;
+
+ if (dvp != NULL && dvp->v_type == VDIR)
+ VTOI(tdp)->parent = ip->ufs_ino.i_number;
+
+ *vpp = tdp;
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+ pool_put(&fusefs_fbuf_pool, fbuf);
+
+out:
+ vput(ap->a_dvp);
+ return (error);
+}
+
+int
+fusefs_mknod(void *v)
+{
+ struct vop_mknod_args *ap = v;
+
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+ vput(ap->a_dvp);
+ return (EINVAL);
+}
+
+int
+fusefs_read(void *v)
+{
+ struct vop_read_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct uio *uio = ap->a_uio;
+ struct proc *p = uio->uio_procp;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf = NULL;
+ size_t size;
+ int error=0;
+
+ DPRINTF("fusefs_read\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ DPRINTF("read inode=%i, offset=%llu, resid=%x\n",
+    ip->ufs_ino.i_number, uio->uio_offset, uio->uio_resid);
+
+ if (uio->uio_resid == 0)
+ return (error);
+ if (uio->uio_offset < 0)
+ return (EINVAL);
+
+ while (uio->uio_resid > 0) {
+ fbuf = fb_setup(FUSEFDSIZE, ip->ufs_ino.i_number, FBT_READ, p);
+
+ size = MIN(uio->uio_resid, FUSELEN);
+ fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_RDONLY);
+ fbuf->fb_io_off = uio->uio_offset;
+ fbuf->fb_io_len = size;
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error)
+ break;
+
+ error = uiomove(fbuf->fb_dat, MIN(size, fbdatsize(fbuf)), uio);
+ if (error)
+ break;
+
+ if (fbdatsize(fbuf) < size)
+ break;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ fbuf = NULL;
+ }
+
+ if (fbuf)
+ pool_put(&fusefs_fbuf_pool, fbuf);
+
+ return (error);
+}
+
+int
+fusefs_write(void *v)
+{
+ struct vop_write_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct uio *uio = ap->a_uio;
+ struct proc *p = uio->uio_procp;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf = NULL;
+ size_t len, diff;
+ int error=0;
+
+ DPRINTF("fusefs_write\n");
+
+ ip = VTOI(vp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ DPRINTF("write inode=%i, offset=%llu, resid=%x\n",
+    ip->ufs_ino.i_number, uio->uio_offset, uio->uio_resid);
+
+ if (uio->uio_resid == 0)
+ return (error);
+
+ while (uio->uio_resid > 0) {
+ len = MIN(uio->uio_resid, FUSELEN);
+ fbuf = fb_setup(FUSEFDSIZE + len, ip->ufs_ino.i_number,
+    FBT_WRITE, p);
+
+ fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_WRONLY);
+ fbuf->fb_io_off = uio->uio_offset;
+ fbuf->fb_io_len = len;
+
+ if ((error = uiomove(fbuf->fb_dat, len, uio))) {
+ DPRINTF("uio error %i", error);
+ break;
+ }
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error)
+ break;
+
+ diff = len - fbuf->fb_io_len;
+ if (diff < 0) {
+ error = EINVAL;
+ break;
+ }
+
+ uio->uio_resid += diff;
+ uio->uio_offset -= diff;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ fbuf = NULL;
+ }
+
+ if (fbuf)
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ return (error);
+}
+
+int
+fusefs_poll(void *v)
+{
+ struct vop_poll_args *ap = v;
+
+ DPRINTF("fusefs_poll\n");
+
+ /*
+ * We should really check to see if I/O is possible.
+ */
+ return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
+}
+
+int
+fusefs_rename(void *v)
+{
+ struct vop_rename_args *ap = v;
+ struct vnode *tvp = ap->a_tvp;
+ struct vnode *tdvp = ap->a_tdvp;
+ struct vnode *fvp = ap->a_fvp;
+ struct vnode *fdvp = ap->a_fdvp;
+ struct componentname *tcnp = ap->a_tcnp;
+ struct componentname *fcnp = ap->a_fcnp;
+ struct proc *p = fcnp->cn_proc;
+ struct fusefs_node *ip, *dp;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ int error = 0;
+
+ DPRINTF("fusefs_rename\n");
+
+#ifdef DIAGNOSTIC
+ if ((tcnp->cn_flags & HASBUF) == 0 ||
+    (fcnp->cn_flags & HASBUF) == 0)
+ panic("fusefs_rename: no name");
+#endif
+ /*
+ * Check for cross-device rename.
+ */
+ if ((fvp->v_mount != tdvp->v_mount) ||
+    (tvp && (fvp->v_mount != tvp->v_mount))) {
+ error = EXDEV;
+abortit:
+ VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
+ if (tdvp == tvp)
+ vrele(tdvp);
+ else
+ vput(tdvp);
+ if (tvp)
+ vput(tvp);
+ VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
+ vrele(fdvp);
+ vrele(fvp);
+ return (error);
+ }
+
+ /*
+ * If source and dest are the same, do nothing.
+ */
+ if (tvp == fvp) {
+ if (fvp->v_type == VDIR) {
+ error = EINVAL;
+ goto abortit;
+ }
+
+ DPRINTF("THE SAME!!!\n");
+ /* Release destination completely. */
+ VOP_ABORTOP(tdvp, tcnp);
+ vput(tdvp);
+ vput(tvp);
+
+ /* Delete source. */
+ vrele(fdvp);
+ vrele(fvp);
+ fcnp->cn_flags &= ~MODMASK;
+ fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
+ if ((fcnp->cn_flags & SAVESTART) == 0)
+ panic("fusefs_rename: lost from startdir");
+ fcnp->cn_nameiop = DELETE;
+ vfs_relookup(fdvp, &fvp, fcnp);
+ return (VOP_REMOVE(fdvp, fvp, fcnp));
+ }
+
+ /* */
+ if ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p)) != 0)
+ goto abortit;
+ dp = VTOI(fdvp);
+ ip = VTOI(fvp);
+
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+ /*
+ *If fuse connection down RENAME undef
+ */
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_RMDIR)) {
+ VOP_UNLOCK(fvp, 0, p);
+ error = ENOSYS;
+ goto abortit;
+ }
+
+ /*
+ * Be sure we are not renaming ".", "..", or an alias of ".". This
+ * leads to a crippled directory tree.  It's pretty tough to do a
+ * "ls" or "pwd" with the "." directory entry missing, and "cd .."
+ * doesn't work if the ".." entry is missing.
+ */
+ if (ip->vtype == VDIR) {
+ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
+ if (!error && tvp)
+ error = VOP_ACCESS(tvp, VWRITE, tcnp->cn_cred,
+    tcnp->cn_proc);
+ if (error) {
+ VOP_UNLOCK(fvp, 0, p);
+ error = EACCES;
+ goto abortit;
+ }
+ /*
+ * Avoid ".", "..", and aliases of "." for obvious reasons.
+ */
+ if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
+    dp == ip ||
+    (fcnp->cn_flags & ISDOTDOT) ||
+    (tcnp->cn_flags & ISDOTDOT)) {
+ VOP_UNLOCK(fvp, 0, p);
+ error = EINVAL;
+ goto abortit;
+ }
+ }
+ vrele(fdvp);
+ VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */
+
+ /*
+ * When the target exists, both the directory
+ * and target vnodes are returned locked.
+ */
+ dp = VTOI(tdvp);
+
+ fbuf = fb_setup(FUSEFDSIZE + fcnp->cn_namelen + tcnp->cn_namelen + 2,
+    dp->ufs_ino.i_number, FBT_RENAME, p);
+
+ memcpy(fbuf->fb_dat, fcnp->cn_nameptr, fcnp->cn_namelen);
+ fbuf->fb_dat[fcnp->cn_namelen] = '\0';
+ memcpy(fbuf->fb_dat + fcnp->cn_namelen + 1, tcnp->cn_nameptr,
+    tcnp->cn_namelen);
+ fbuf->fb_dat[fcnp->cn_namelen + tcnp->cn_namelen + 1] = '\0';
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error) {
+ if (error == ENOSYS) {
+ fmp->undef_op |= UNDEF_RENAME;
+ }
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ VOP_UNLOCK(fvp, 0, p);
+ goto abortit;
+ }
+
+ VN_KNOTE(fvp, NOTE_RENAME);
+ VOP_UNLOCK(fvp, 0, p);
+
+ if (dp)
+ vput(fdvp);
+
+ vrele(ap->a_fvp);
+ return (error);
+}
+
+int
+fusefs_mkdir(void *v)
+{
+ struct vop_mkdir_args *ap = v;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode **vpp = ap->a_vpp;
+ struct componentname *cnp = ap->a_cnp;
+ struct vattr *vap = ap->a_vap;
+ struct proc *p = cnp->cn_proc;
+ struct vnode *tdp = NULL;
+ struct fusefs_node *ip;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ int error = 0;
+
+ DPRINTF("fusefs_mkdir %s\n", cnp->cn_nameptr);
+
+ ip = VTOI(dvp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKDIR)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1, ip->ufs_ino.i_number,
+    FBT_MKDIR, p);
+
+ fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode);
+ memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
+ fbuf->fb_dat[cnp->cn_namelen] = '\0';
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_MKDIR;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out;
+ }
+
+ if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out;
+ }
+
+ tdp->v_type = IFTOVT(fbuf->fb_io_mode);
+ VTOI(tdp)->vtype = tdp->v_type;
+
+ if (dvp != NULL && dvp->v_type == VDIR)
+ VTOI(tdp)->parent = ip->ufs_ino.i_number;
+
+ *vpp = tdp;
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
+ pool_put(&fusefs_fbuf_pool, fbuf);
+out:
+ vput(dvp);
+ return (error);
+}
+
+int
+fusefs_rmdir(void *v)
+{
+ struct vop_rmdir_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct fusefs_node *ip, *dp;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ int error;
+
+ DPRINTF("fusefs_rmdir\n");
+
+ ip = VTOI(vp);
+ dp = VTOI(dvp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ /*
+ * No rmdir "." please.
+ */
+ if (dp == ip) {
+ vrele(dvp);
+ vput(vp);
+ return (EINVAL);
+ }
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_RMDIR)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+ fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1, dp->ufs_ino.i_number,
+    FBT_RMDIR, p);
+ memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
+ fbuf->fb_dat[cnp->cn_namelen] = '\0';
+
+ error = fb_queue(fmp->dev, fbuf);
+
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_RMDIR;
+ if (error != ENOTEMPTY)
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out;
+ }
+
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
+ cache_purge(dvp);
+ vput(dvp);
+ dvp = NULL;
+
+ cache_purge(ITOV(ip));
+ pool_put(&fusefs_fbuf_pool, fbuf);
+out:
+ if (dvp)
+ vput(dvp);
+ VN_KNOTE(vp, NOTE_DELETE);
+ vput(vp);
+ return (error);
+}
+
+int
+fusefs_remove(void *v)
+{
+ struct vop_remove_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct fusefs_node *ip;
+ struct fusefs_node *dp;
+ struct fusefs_mnt *fmp;
+ struct fusebuf *fbuf;
+ int error = 0;
+
+ DPRINTF("fusefs_remove\n");
+
+ ip = VTOI(vp);
+ dp = VTOI(dvp);
+ fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+ if (!fmp->sess_init || (fmp->undef_op & UNDEF_REMOVE)) {
+ error = ENOSYS;
+ goto out;
+ }
+
+ fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1, dp->ufs_ino.i_number,
+    FBT_UNLINK, p);
+ memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
+ fbuf->fb_dat[cnp->cn_namelen] = '\0';
+
+ error = fb_queue(fmp->dev, fbuf);
+ if (error) {
+ if (error == ENOSYS)
+ fmp->undef_op |= UNDEF_REMOVE;
+
+ pool_put(&fusefs_fbuf_pool, fbuf);
+ goto out;
+ }
+
+ VN_KNOTE(vp, NOTE_DELETE);
+ VN_KNOTE(dvp, NOTE_WRITE);
+ pool_put(&fusefs_fbuf_pool, fbuf);
+out:
+ if (dvp == vp)
+ vrele(vp);
+ else
+ vput(vp);
+ vput(dvp);
+ return (error);
+}
+
+int
+fusefs_strategy(void *v)
+{
+ DPRINTF("fusefs_strategy\n");
+ return (0);
+}
+
+int
+fusefs_lock(void *v)
+{
+ struct vop_lock_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ DPRINTF("fusefs_lock\n");
+ return (lockmgr(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags, NULL));
+}
+
+int
+fusefs_unlock(void *v)
+{
+ struct vop_unlock_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ DPRINTF("fusefs_unlock\n");
+ return (lockmgr(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags | LK_RELEASE,
+    NULL));
+}
+
+int
+fusefs_islocked(void *v)
+{
+ struct vop_islocked_args *ap = v;
+
+ DPRINTF("fusefs_islocked\n");
+ return (lockstatus(&VTOI(ap->a_vp)->ufs_ino.i_lock));
+}
+
+int
+fusefs_advlock(void *v)
+{
+ struct vop_advlock_args *ap = v;
+ struct fusefs_node *ip = VTOI(ap->a_vp);
+
+ DPRINTF("fusefs_advlock\n");
+ return (lf_advlock(&ip->ufs_ino.i_lockf, ip->filesize, ap->a_id,
+    ap->a_op, ap->a_fl, ap->a_flags));
+}
Index: miscfs/fuse/fusebuf.c
===================================================================
RCS file: miscfs/fuse/fusebuf.c
diff -N miscfs/fuse/fusebuf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fusebuf.c 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,70 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/mount.h>
+#include <sys/pool.h>
+#include <sys/proc.h>
+#include <sys/statvfs.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <sys/fusebuf.h>
+
+#include <dev/rndvar.h>
+
+#include "fusefs_node.h"
+#include "fusefs.h"
+
+#ifdef FUSE_DEBUG
+#define DPRINTF(fmt, arg...) printf("fuse ipc: " fmt, ##arg)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+struct fusebuf *
+fb_setup(size_t len, ino_t ino, int op, struct proc *p)
+{
+ struct fusebuf *fbuf;
+
+ fbuf = pool_get(&fusefs_fbuf_pool, PR_WAITOK | PR_ZERO);
+ fbuf->fb_len = len;
+ fbuf->fb_err = 0;
+ fbuf->fb_uuid = arc4random();
+ fbuf->fb_type = op;
+ fbuf->fb_ino = ino;
+ fbuf->fb_resid = -1;
+
+ DPRINTF("create unique %lu\n", fbuf->fb_uuid);
+
+ return (fbuf);
+}
+
+int
+fb_queue(dev_t dev, struct fusebuf *fbuf)
+{
+ int error = 0;
+
+ fuse_device_queue_fbuf(dev, fbuf);
+
+ if ((error = tsleep(fbuf, PWAIT, "fuse msg", TSLEEP_TIMEOUT * hz))) {
+ fuse_device_cleanup(dev, fbuf);
+ return (error);
+ }
+
+ return (fbuf->fb_err);
+}
Index: miscfs/fuse/fusefs.h
===================================================================
RCS file: miscfs/fuse/fusefs.h
diff -N miscfs/fuse/fusefs.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fusefs.h 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,85 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FUSEFS_H__
+#define __FUSEFS_H__
+
+struct fuse_msg;
+
+struct fusefs_mnt {
+ struct mount *mp;
+ uint32_t undef_op;
+ uint32_t max_write;
+ int sess_init;
+ dev_t dev;
+};
+
+#define UNDEF_ACCESS 1<<0
+#define UNDEF_MKDIR 1<<1
+#define UNDEF_CREATE 1<<2
+#define UNDEF_LINK 1<<3
+#define UNDEF_READLINK 1<<4
+#define UNDEF_RMDIR 1<<5
+#define UNDEF_REMOVE 1<<6
+#define UNDEF_SETATTR 1<<7
+#define UNDEF_RENAME 1<<8
+#define UNDEF_SYMLINK 1<<9
+
+extern struct vops fusefs_vops;
+extern struct pool fusefs_fbuf_pool;
+
+/* sysctl defines */
+#define FUSEFS_NB_OPENDEVS 1 /* # of fuse devices opened */
+#define FUSEFS_INFBUFS 2 /* # of in fbufs */
+#define FUSEFS_WAITFBUFS 3 /* # of fbufs waiting for a response */
+#define FUSEFS_POOL_NBPAGES 4 /* # total fusefs size */
+#define FUSEFS_MAXID 5 /* number of valid fusefs ids */
+
+#define FUSEFS_NAMES { \
+ { 0, 0}, \
+ { "fusefs_open_devices", CTLTYPE_INT }, \
+ { "fusefs_fbufs_in", CTLTYPE_INT }, \
+ { "fusefs_fbufs_wait", CTLTYPE_INT }, \
+ { "fusefs_pool_pages", CTLTYPE_INT }, \
+}
+
+/* fuse helpers */
+#define TSLEEP_TIMEOUT 5
+void update_vattr(struct mount *mp, struct vattr *v);
+
+/* files helpers. */
+int fusefs_file_open(struct fusefs_mnt *, struct fusefs_node *, enum fufh_type,
+    int, int, struct proc *);
+int fusefs_file_close(struct fusefs_mnt *, struct fusefs_node *,
+    enum fufh_type, int, int, struct proc *);
+
+/* device helpers. */
+void fuse_device_cleanup(dev_t, struct fusebuf *);
+void fuse_device_queue_fbuf(dev_t, struct fusebuf *);
+void fuse_device_set_fmp(struct fusefs_mnt *);
+
+/*
+ * The root inode is the root of the file system.  Inode 0 can't be used for
+ * normal purposes.
+ */
+#define FUSE_ROOTINO ((ino_t)1)
+#define VFSTOFUSEFS(mp) ((struct fusefs_mnt *)((mp)->mnt_data))
+
+/* #define FUSE_DEBUG_VNOP
+#define FUSE_DEBUG */
+
+#endif /* __FUSEFS_H__ */
Index: miscfs/fuse/fusefs_node.h
===================================================================
RCS file: miscfs/fuse/fusefs_node.h
diff -N miscfs/fuse/fusefs_node.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ miscfs/fuse/fusefs_node.h 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,66 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2012-2013 Sylvestre Gallon <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _FUSEFS_NODE_H_
+#define _FUSEFS_NODE_H_
+
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <ufs/ufs/ufs_extern.h>
+
+enum fufh_type {
+ FUFH_INVALID = -1,
+ FUFH_RDONLY  = 0,
+ FUFH_WRONLY  = 1,
+ FUFH_RDWR    = 2,
+ FUFH_MAXTYPE = 3,
+};
+
+struct fusefs_filehandle {
+ uint64_t fh_id;
+ enum fufh_type fh_type;
+};
+
+struct fusefs_node {
+ struct inode ufs_ino;
+
+ /* fd of fuse session and parent ino_t*/
+ uint64_t parent;
+
+ /** I/O **/
+ struct     fusefs_filehandle fufh[FUFH_MAXTYPE];
+
+ /** meta **/
+ struct vattr      cached_attrs;
+ off_t             filesize;
+ uint64_t          nlookup;
+ enum vtype        vtype;
+};
+
+#ifdef ITOV
+# undef ITOV
+#endif
+#define ITOV(ip) ((ip)->ufs_ino.i_vnode)
+
+#ifdef VTOI
+# undef VTOI
+#endif
+#define VTOI(vp) ((struct fusefs_node *)(vp)->v_data)
+
+uint64_t fusefs_fd_get(struct fusefs_node *, enum fufh_type);
+
+#endif /* _FUSEFS_NODE_H_ */
Index: sys/conf.h
===================================================================
RCS file: /cvs/src/sys/sys/conf.h,v
retrieving revision 1.121
diff -u -p -u -p -r1.121 conf.h
--- sys/conf.h 19 Apr 2013 15:02:41 -0000 1.121
+++ sys/conf.h 3 Jun 2013 13:35:33 -0000
@@ -509,6 +509,13 @@ extern struct cdevsw cdevsw[];
  (dev_type_stop((*))) enodev, 0, selfalse, \
  (dev_type_mmap((*))) enodev }
 
+/* open, close, read, write, poll, ioctl */
+#define cdev_fuse_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
+ (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) }
+
 #endif
 
 /*
@@ -655,6 +662,7 @@ cdev_decl(urio);
 cdev_decl(hotplug);
 cdev_decl(gpio);
 cdev_decl(amdmsr);
+cdev_decl(fuse);
 
 #endif
 
Index: sys/fusebuf.h
===================================================================
RCS file: sys/fusebuf.h
diff -N sys/fusebuf.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/fusebuf.h 3 Jun 2013 13:35:33 -0000
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2013 Sylvestre Gallon
+ * Copyright (c) 2013 Martin Pieuchot
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SYS_FUSEBUF_H_
+#define _SYS_FUSEBUF_H_
+
+/*
+ * Fusebufs are of a single size, PAGE_SIZE, and cannot be bigger.This
+ * restriction is due to the fact that we allocate the fusebuf(9) with
+ * pool_get(9) and that it does not support size >= to PAGE_SIZE
+ */
+
+#define FUSEFDSIZE sizeof(((struct fusebuf *)0)->F_dat.FD)
+#define FUSELEN (PAGE_SIZE - sizeof(struct fb_hdr) - sizeof(union uFD))
+
+/* header at beginning of each fusebuf(9): */
+struct fb_hdr {
+ SIMPLEQ_ENTRY(fusebuf) fh_next; /* next buffer in chain */
+ size_t fh_len; /* Amount of data */
+ size_t fh_resid; /* Needed for partial rw */
+ uint32_t fh_err; /* Err code to pass back */
+ int fh_type; /* type of data */
+ ino_t fh_ino; /* Inode of this fusebuf(9) */
+ uint64_t fh_uuid; /* Uuid to track the answer */
+};
+
+/* header for fuse file operations (like read/write/mkdir): */
+struct fb_io {
+ uint64_t fi_fd; /* fd where the io is performed */
+ ino_t           fi_ino; /* ino for the io */
+ off_t fi_off; /* offset for the io */
+ size_t fi_len; /* Length of data */
+ mode_t fi_mode; /* mode for fd */
+ uint32_t fi_flags; /* flags on transfer */
+};
+
+/*
+ * An operation is issued by the kernel through fuse(4) when the
+ * userland file system needs to execute an action (mkdir(2),
+ * link(2), etc).
+ *
+ * F_databuf can be superior to FUSELEN for fusefs_read, fusefs_writes and
+ * fusefs_readdir. If it is the case the transfer will be split in N
+ * fusebuf(9) with a changing offset in FD_io.
+ *
+ * When the userland file system answers to this operation it uses
+ * the same ID (fh_uuid).
+ */
+struct fusebuf {
+ struct fb_hdr fb_hdr;
+ struct {
+ union uFD {
+ struct statvfs FD_stat; /* vfs statfs */
+ struct vattr FD_vattr; /* for attr vnops */
+ struct fb_io FD_io; /* for file io vnops */
+
+ } FD;
+ char F_databuf[FUSELEN];
+ } F_dat;
+};
+
+#define fb_next fb_hdr.fh_next
+#define fb_len fb_hdr.fh_len
+#define fb_resid fb_hdr.fh_resid
+#define fb_err fb_hdr.fh_err
+#define fb_type fb_hdr.fh_type
+#define fb_ino fb_hdr.fh_ino
+#define fb_uuid fb_hdr.fh_uuid
+
+#define fb_stat F_dat.FD.FD_stat
+#define fb_vattr F_dat.FD.FD_vattr
+#define fb_io_fd F_dat.FD.FD_io.fi_fd
+#define fb_io_ino F_dat.FD.FD_io.fi_ino
+#define fb_io_off F_dat.FD.FD_io.fi_off
+#define fb_io_len F_dat.FD.FD_io.fi_len
+#define fb_io_mode F_dat.FD.FD_io.fi_mode
+#define fb_io_flags F_dat.FD.FD_io.fi_flags
+#define fb_dat F_dat.F_databuf
+
+/*
+ * Macros for type conversion
+ * fbtod(fb,t) - convert fusebuf(9) pointer to data pointer of correct
+ * type
+ */
+#define fbtod(fb,t) ((t)((fb)->fb_dat))
+
+/* helper to get F_databuf size */
+#define fbdatsize(fb) ((fb)->fb_len - FUSEFDSIZE)
+
+/* flags needed by setattr */
+#define FUSE_FATTR_MODE (1 << 0)
+#define FUSE_FATTR_UID (1 << 1)
+#define FUSE_FATTR_GID (1 << 2)
+#define FUSE_FATTR_SIZE (1 << 3)
+#define FUSE_FATTR_ATIME (1 << 4)
+#define FUSE_FATTR_MTIME (1 << 5)
+#define FUSE_FATTR_FH (1 << 6)
+
+/* fusebuf(9) types */
+#define FBT_LOOKUP 0
+#define FBT_GETATTR 1
+#define FBT_SETATTR 2
+#define FBT_READLINK 3
+#define FBT_SYMLINK 4
+#define FBT_MKNOD 5
+#define FBT_MKDIR 6
+#define FBT_UNLINK 7
+#define FBT_RMDIR 8
+#define FBT_RENAME 9
+#define FBT_LINK 10
+#define FBT_OPEN 11
+#define FBT_READ 12
+#define FBT_WRITE 13
+#define FBT_STATFS 14
+#define FBT_RELEASE 16
+#define FBT_FSYNC 17
+#define FBT_FLUSH 18
+#define FBT_INIT 19
+#define FBT_OPENDIR 20
+#define FBT_READDIR 21
+#define FBT_RELEASEDIR 22
+#define FBT_FSYNCDIR 23
+#define FBT_ACCESS 24
+#define FBT_CREATE 25
+#define FBT_DESTROY 26
+
+#ifdef _KERNEL
+
+/* The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+/* fusebuf(9) prototypes */
+struct fusebuf *fb_setup(size_t, ino_t, int, struct proc *);
+int fb_queue(dev_t, struct fusebuf *);
+
+#endif /* _KERNEL */
+#endif /* _SYS_FUSEBUF_H_ */
Index: sys/malloc.h
===================================================================
RCS file: /cvs/src/sys/sys/malloc.h,v
retrieving revision 1.105
diff -u -p -u -p -r1.105 malloc.h
--- sys/malloc.h 3 May 2013 18:26:07 -0000 1.105
+++ sys/malloc.h 3 Jun 2013 13:35:34 -0000
@@ -120,7 +120,8 @@
 #define M_TTYS 62 /* allocated tty structures */
 #define M_EXEC 63 /* argument lists & other mem used by exec */
 #define M_MISCFSMNT 64 /* miscfs mount structures */
-/* 65-73 - free */
+#define M_FUSEFS 65 /* fusefs mount structures */
+/* 66-73 - free */
 #define M_PFKEY 74 /* pfkey data */
 #define M_TDB 75 /* Transforms database */
 #define M_XDATA 76 /* IPsec data */
@@ -249,7 +250,7 @@
  "ttys", /* 62 M_TTYS */ \
  "exec", /* 63 M_EXEC */ \
  "miscfs mount", /* 64 M_MISCFSMNT */ \
- NULL, \
+ "fusefs mount", /* 65 M_FUSEFS */ \
  NULL, \
  NULL, \
  NULL, \
Index: sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.109
diff -u -p -u -p -r1.109 mount.h
--- sys/mount.h 15 Apr 2013 15:32:19 -0000 1.109
+++ sys/mount.h 3 Jun 2013 13:35:34 -0000
@@ -258,6 +258,15 @@ struct procfs_args {
 #define PROCFS_ARGSVERSION      1
 #define PROCFSMNT_LINUXCOMPAT   0x01
 
+/*
+ * Arguments to mount fusefs filesystems
+ */
+struct fusefs_args {
+ char *name;
+ char *url;
+ dev_t dev;
+ int flags;
+};
 
 /*
  * file system statistics
@@ -360,6 +369,7 @@ struct statfs53 {
 #define MOUNT_NCPFS "ncpfs" /* NetWare Network File System */
 #define MOUNT_NTFS "ntfs" /* NTFS */
 #define MOUNT_UDF "udf" /* UDF */
+#define MOUNT_FUSEFS "fuse" /* FUSE */
 
 /*
  * Structure per mounted file system.  Each mounted file system has an
Index: sys/vnode.h
===================================================================
RCS file: /cvs/src/sys/sys/vnode.h,v
retrieving revision 1.115
diff -u -p -u -p -r1.115 vnode.h
--- sys/vnode.h 6 Apr 2013 04:38:13 -0000 1.115
+++ sys/vnode.h 3 Jun 2013 13:35:34 -0000
@@ -69,13 +69,13 @@ enum vtype { VNON, VREG, VDIR, VBLK, VCH
 enum vtagtype {
  VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_MSDOSFS,
  VT_PORTAL, VT_PROCFS, VT_AFS, VT_ISOFS, VT_ADOSFS,
- VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF,
+ VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF, VT_FUSEFS
 };
 
 #define VTAG_NAMES \
     "NON", "UFS", "NFS", "MFS", "MSDOSFS", \
     "PORTAL", "PROCFS", "AFS", "ISOFS", "ADOSFS", \
-    "EXT2FS", "VFS", "NTFS", "UDF"
+    "EXT2FS", "VFS", "NTFS", "UDF", "FUSEFS"
 
 /*
  * Each underlying filesystem allocates its own private area and hangs

12
Loading...