Wednesday, October 1, 2008

Getting GVfs and FUSE right

One of the cool things about the new IO library (GIO) in the GNOME stack is that it’s extensible. One set of extensions for GIO is provided by the GVfs package. The main (but not only) purpose of GVfs is to provide access to Virtual File Systems by having the file system backend (e.g. file system driver) running in a separate daemon process in user space - sort of similar to what the Filesystems in Userspace (FUSE) framework provides on Linux and, nowadays, most UNIX operating systems. GVfs currently includes backends for SFTP, FTP, OBEX for Bluetooth, Digital cameras and MTP devices (through libgphoto2), Compact Disc Audio, Webdav, HTTP and archive files (through libarchive) to name the most important ones.

One key difference between FUSE and GVfs, is that GVfs file system drivers are not constrained by the rather old-fashioned, limited and design-by-committee POSIX API. Instead, GIO provides (and exposes for implementation to file system drivers) a modern and powerful API that provides asynchronous IO, file monitoring (like inotify) and high-level operations as part of the standard API. The GIO API is at the right level of the stack, it’s part of the GLib tarball. This means that any application that today uses GTK+ has access to GIO. This is a pretty big deal, if you depend on GTK+ 2.14 on newer, you’ll also depend on GIO.

However, since it’s rather naive (not to mention arrogant) to think that people are going to be using only GTK+ applications, GVfs also ships with a FUSE daemon. This daemon provides a POSIX interface to the virtual file systems provided by GVfs. All the fancy high-level operations available when using GIO won’t be available (there’s no POSIX equivalent function to map to) of course, but the basic POSIX stuff (e.g. open(2), read(2) etc.) will work just fine. The way it works is that the GVfs FUSE daemon provides a mount in $HOME/.gvfs where each top-level directory represents a GVfs mount:

$ ls -1 $HOME/.gvfs
gphoto2 mount on usb%3A004,002
sftp on
sftp on quad.local

For example, this means all the good old command line tools still work

$ stat /home/davidz/.gvfs/sftp\ on\ quad.local/home/davidz/.bashrc
File: `/home/davidz/.gvfs/sftp on quad.local/home/davidz/.bashrc'
Size: 313 Blocks: 0 IO Block: 4096 regular file
Device: 14h/20d Inode: 44 Links: 1
Access: (0600/-rw-------) Uid: ( 500/ davidz) Gid: ( 500/ davidz)
Access: 2008-10-01 14:35:28.000000000 -0400
Modify: 2008-04-25 11:55:02.000000000 -0400
Change: 2008-04-25 11:55:02.000000000 -0400

$ convert /home/davidz/.gvfs/gphoto2\ mount\ on\ usb%3A004\,002/DCIM/100NIKON/DSCN0001.JPG -dither out.jpg

and so forth. Lots of command-line people like this, at least they always like to complain when we didn’t have this back in the GnomeVFS days.

But it gets better. Today I committed a patch to GIO to ensure that GIO applications launching applications (such as the Nautilus file manager or the Evolution mailer) will always pass a FUSE path instead of the GIO URI. One implication of this is that if you launch a non-GIO application (such as mplayer or a KDE application) from Nautilus, that application will Just Work(tm) even if the file lives on a GVfs share.

I think this is a pretty big deal; now it just doesn’t matter what VFS system of the week is used in the application, it’s all POSIX as far as applications are concerned. Sure, there’s a small performance hit by having to go through the GVfs FUSE daemon (a couple of extra context switches) but for run-of-the-mill desktop applications this is insignificant. Also, as explained here it’s currently not a very smart idea to pass an URI to an application; there’s the problem we don’t have proper standards defining the URI’s we use; there’s also the problem of having to authenticate over and over again.

Finally, if the application itself is using GIO, this patch ensures we map back to a GIO URI and, thus, we bypass the FUSE daemon. This is best illustrated by the following screenshot:

Bastien in VFS heaven

Bastien in VFS heaven

As you can see from the terminal window, Eye of GNOME is being passed a FUSE path from Nautilus. But thanks to the aforementioned patch, this is getting mapped back to a GIO URI as shown in the properties dialog.

This feature won’t be available in GNOME until 2.26 (and GLib 2.20) - we’re concerned some broken applications might be examining the URI before it’s mapped back so we’re reluctant to provide it in GLib 2.18 / GNOME 2.24 for now. FWIW, we’ve been shipping patches for this feature since Fedora 9 and the feature will be in Fedora 10 as well. Other vendors are encouraged to ship these patches as well.