Skip to content

Releases: billziss-gh/winfuse

WinFuse 2020 Beta - FUSE for WSL1

24 Aug 01:08
v0.2
Compare
Choose a tag to compare
Pre-release

FUSE for WSL1

This release of WinFuse finally brings FUSE support for WSL1!

Linux FUSE file systems that use the libfuse high-level or low-level interface should work without any modifications. Linux FUSE file systems that interface with /dev/fuse directly should still work, unless they perform their own mounting and do not use fusermount; such file systems may need some modifications in order to work (see LIMITATIONS below).

It is recommended that you try this release in a VM. Although there are no known system stability issues, bugchecks, leaks, system hangs and other system problems are still a possibility.

In the screen cap below you can see unmodified Linux SSHFS running under WSL1 and used to browse the source code of WinFuse. The file system is presented as the Windows drive Z: and also mounted on mnt. (You can use a FUSE file system running under WSL1 to make a drive available to the rest of Windows.)

WslFuse

INSTALLATION

This installation requires Windows 10 2004 64-bit. It should also work in Windows 10 1909 64-bit. Prior versions of Windows 10 are not supported.

  • Install WinFsp.
    • WinFsp 2020.2 Beta2 (v1.8B2) is required.
    • Installation Path: C:\Program Files (x86)\WinFsp
    • Registry Path: HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp
    • Driver: winfsp
  • Install LxDK.
    • LxDK 2020 Beta2 (v0.3) is required.
    • Installation Path: C:\Program Files\LxDK
    • Registry Path: HKEY_LOCAL_MACHINE\SOFTWARE\LxDK
    • Driver: lxldr
  • Install WinFuse.
    • Installation Path: C:\Program Files\WinFuse
    • Registry Path: HKEY_LOCAL_MACHINE\SOFTWARE\WinFuse
    • Drivers: winfuse, wslfuse
  • Reboot your machine to ensure that the necessary driver for WSL1 has been loaded.
  • The installation process should be streamlined in later versions of WinFuse.

NOTE: Please use the indicated minimum required versions or system instability is possible.

How to use in WSL1

  • Launch a WSL1 session.

  • Execute the command below to install a custom fusermount and create /dev/fuse. Unfortunately the /dev/fuse node cannot be created permanently at this time, so you may have to execute this command at the beginning of every WSL1 session (see LIMITATIONS below).

    $ sudo sh '/mnt/c/Program Files/WinFuse/opt/wslfuse/install.sh'
    FUSE for WSL1 user space components installed
    
  • Start your file system. For example:

    $ sshfs -d -o umask=000 USER@SERVER: mnt
    ...
    

LIMITATIONS

This release has a few limitations that are listed below. Some of these limitations may be lifted in the future.

/dev/fuse creation

Currently the /dev/fuse node must be created in the beginning of every WSL1 session. (The easiest way to do this is to execute the command sudo sh '/mnt/c/Program Files/WinFuse/opt/wslfuse/install.sh'.) The reasons are the following:

  • The LXCORE driver provides an (undocumented) DDI for creating file system entries (VfsInitializeStartupEntries). Unfortunately the WSL1 init process remounts the /dev file system immediately after the wslfuse driver gets a chance to create its /dev/fuse entry. For this reason it is not possible to create /dev/fuse from kernel mode.

  • The WSL1 init process executes /bin/sh and passes control to the user without first attempting to execute any system-wide scripts or configuration (such as systemd). For this reason it is not possible to create /dev/fuse when the WSL session starts.

Mount protocol

Linux programs typically call mount(2) to mount a file system. Unfortunately LXCORE does not provide any obvious way to intercept the mount and umount system calls nor does it provide any way to add a new "FUSE" file system type. For this reason, fusermount emulates mounting and unmounting using special ioctl's on /dev/fuse.

The mount protocol is as follows:

  • Open /dev/fuse for read/write.
  • Issue an WSLFUSE_IOCTL_CREATEVOLUME ioctl. This creates a WinFsp disk or network volume (typically named \Device\Volume{GUID} in the NTOS namespace).
  • Execute a Windows helper application named /usr/bin/fusermount-helper.exe, which uses Windows rules to assign a drive to the WinFsp volume (e.g. Z: -> \Device\Volume{GUID}). This is needed so that the drive can be created in the correct Windows session namespace.
  • Issue an WSLFUSE_IOCTL_WINMOUNT ioctl. This informs the wslfuse driver about the drive chosen by fusermount-helper.exe.
  • Use sendmsg(2) to send the open file descriptor for /dev/fuse to the FUSE file system. The FUSE file system can now use the file descriptor (e.g. via libfuse) to receive/send FUSE requests/responses. Note that at this point we have not mounted the file system in WSL1 yet.
  • Fork a new process to perform the actual mount(2) using drvfs as the file system type and exit the original fusermount process. This is done to avoid a potential deadlock. For the full details see here. It is of course possible for this mount to fail, but the FUSE file system will continue to service file system operations for the drive created earlier.
  • The new process will also issue an WSLFUSE_IOCTL_LXMOUNT ioctl to associate the new mount id (taken from /proc/self/mountinfo) with the newly created volume.
  • Please see the source code of fusermount for addtional details.

Obviously this protocol is rather complex and not very robust. It may be simplified in the future.

Mount options

There are additional options that can be passed to fusermount to control the mount process. For example the option -oVolume=X: can be used to control the drive to be created for a new FUSE file system instance. Unfortunately libfuse does not currently recognize any of these options; as a workaround I have hijacked the -ocontext=CONTEXT option, which libfuse does accept to pass additional options. For example, to create a new network drive X: accessible via the UNC prefix \\myfs\share, use:

$ ./myfs -ocontext=Volume=X:,context=VolumePrefix=/myfs/share ...

Permission model

The wslfuse driver uses a scheme used by Cygwin and (in the past) Services for UNIX to map Unix UID's and permissions to Windows SID's and ACL's. Unfortunately this scheme is not compatible with WSL1, which can result in permission problems. If you experience such problems try running your file system with the option -o umask=000.

Future versions of WinFuse should rectify this problem.

WinFuse 2020 Alpha1

18 Dec 20:52
Compare
Choose a tag to compare
WinFuse 2020 Alpha1 Pre-release
Pre-release

This release requires WinFsp 2019.3 or later. Prior versions will not work.

WinFuse is a suite of software components that allows FUSE file systems to run on Windows. It consists of a kernel driver that exposes the low-level FUSE protocol and a Windows port of the libfuse library compiled as a DLL.

This is the first release of WinFuse and it should be considered of ALPHA quality. Although I am not aware of any such issues, bugchecks, leaks, system hangs and other system problems are a possibility. For this reason I recommend that you try WinFuse in a VM.

I would really appreciate it if you give WinFuse a try and report any problems. This is especially so if you have a low-level FUSE file system that you cannot easily port to Windows; well now you can. Your feedback is very welcome.

Finally note that this release contains the winfuse kernel driver, which exposes the FUSE protocol in the Windows kernel (via DeviceIoControl). It does not contain the wslfuse kernel driver, which will expose the FUSE protocol in WSL1 (via /dev/fuse).

WinFuse