Download location (HTTP):       http://linux.bononline.nl/linux/mount.md5key.new/fuse-workspace/src


Fuse workspace

Summary

Fuse workspace is an FUSE filesystem, aimed to provide the desktop user easy access to all kind of resources, like
local USB devices and remote Windows (and/or Samba) shares, FTP servers, SSH directories.

At this moment the filesystem is mounted at a subdirectory of the users homedirectory (default: $HOME/Workspace). I'm working
on other use, like mounting it over the users homedirectory (possible through the use of openat and related systemcalls),
and (like GoboLinux) creating an entire new chrooted environment where all system related directories are hidden.


The development started with a simple module named fuse-workspace, using the high level interface, and with hardcoded paths.
Fuse-workspace-union worked with parameters, and was able to cooperate with the automounter to do the mounting.
These two modules were using the high level interface of FUSE. The limitations of this high level interface (the most
important one: asynchronous io is not possible, take the uid/gid of the activating user is another one)
were the reason for me to develop the new module, fuse-workspace-ll.

A brief summary what is does:

fuse-workspace-ll --bind-directory=%directory to bind%
                  --conf-directory=%configuration directory%
                  --autofs-mount-directory=%directory where the autofs mounts resources for this user%
                  --autofs-cache-directory=%directory with cache of resource records%
                  $HOME/Workspace

--bind-directory: the contents of this directory is mirrored at the mountpoint, here: $HOME/Workspace.

Note: this looks like a bind mount, but is different. A bind mount makes the same data available on another
directory, where this module is just another fs mounted at $HOME/Workspace, which happens to get it's input
from the --bind-directory parameter.

--conf-directory: configuration directory, to change the behaviour of the fs. For example:
When fuse-workspace-ll finds a symlink in the --bind-directory (%directory to bind%/path), it will look in
the configuration for the existence of a directory (%configuration directory%/path). If found, it will transform
the symlink into a directory.
The configuration is also used for caching of .directory files. When dealing with a symlink to an autofs managed
directory, a lookup of this .directory file is taking from the configuration.

--autofs-mount-directory: directory used by the automounter in the mount.md5key setup to mount resources for this user
Look for more info about mount.md5key:

http://linux.bononline.nl/linux/mount.md5key.new/mount.md5key

Simular to the check of a directory to be present in the configuration when dealing with a symlink, another check is
done to test it's pointing to this autofs mount directory. If true, the symlink is transformed as a directory.

To make the third configuration possible (to create a chrooted environment aka GoboLinux) it does additional:
- when dealing with a directory which is direct under the mountpoint, look for the .hide file in the configuration.
If present, it will be skipped in readdir calls. The stat call is left as is. The effect is that it looks like
the directory is not there, but can still be used. You can cd into it, and then look at the contents. Because the readdir
restriction only applies to "top level" directories, the readdir call has no restrictions here.
Also it's possible to mount a directory here. For example the directory proc:

mdkir %directory to bind%/proc
mkdir %configuration directory%/proc
touch %configuration directory%/proc/.hide

Now this makes it possible to mount the proc filesystem at the %mountpoint of workspace%/proc, with full functionality
but it is hidden. This also counts for sys, dev and even bin and usr.

Motivation

The reason for me to develop this module, is that I want all kind of resources like USB devices but also
Windows and/or Samba shares direct available in one place in my homedirectory. As you may know, hardware is
available under the directory /media, managed by HAL (or DeviceKit), and SMB (=Windows) shares at /mnt,
mounted by the automounter or via connectionhelpers like kio slaves. You can access them with your application,
where your homedirectory is always your starting point. In my opinion, browsing through the system to get to
these locations is not userfriendly.

A solution is to create symbolic links to these directories like:

$HOME/Workspace/Devices -> /media
$HOME/Workspace/Network/Windows\ Network/Workgroup/aserver/ashare -> %location in /mnt managed by autofs to mount this share


But the big disadvantage of symbolic links, is that most applications do, when following the link, forget where you
came from, and the user is browing system (=foreign, not userfriendly) directories like /mnt or /media, what should not happen!
Going back still means browsing through unknown directories and extra work, making things unnecessary complicated, read userunfriendy.

This module now makes these system directories (thus /media and /mnt and subdirs of those) available under the directory where
it's mounted, for example $HOME/Workspace. It works just like bind mounts, mirroring the contents of mounted devices and network
shares direct in a subdirectory in your homedirectory. Any application can use these "mirrored" mountpoints, they are just
subdirectories under the directory where this module is mounted, preferably somewhere in your homedirectory.
Also much better than solutions like the kio slaves, where there is even no mountpoint where you can browse to.
This construction makes use of the automounter and mount.cifs to access shares of Windows/Samba shares and other resources: it's
using the automounter as mount helper. More about that:


- mount.md5key: http://linux.bononline.nl/linux/mount.md5key.new/mount.md5key


Earlier I've tried to do that with a construction based on the automounter alone (so without the fuse module). To create browseable maps,
which made sense to the user, the automounter maps were not straightforward, but complicated multi-mount maps, not easy to manage.
I had trouble with stability, when an user logged out (and a mountpoint was added to an already running automounter).


This looked like:

$HOME/Connections/Devices

and

$HOME/Connections/Network

In the auto.master file these mountpoints are linked to dynamically created maps. For me as user sbon this looks like:

/home/sbon/Connections/Devices /var/run/autofs/session/auto.local.map.sbon --ghost --timeout=0
/home/sbon/Connections/Network /var/run/autofs/session/auto.network.map.sbon --ghost

The files auto.local.map.sbon and auto.network.map.sbon contain respectively instructions to mount local hardware (like USB devices) and
network resources (like Samba/Windows shares).

For more information, look at:


- autofsmanaged: http://linux.bononline.nl/linux/autofsmanaged


This worked ok, but had the disadvantage of instability. After adding the new mountpoints to the master file of autofs, auto.master,
the automount daemon gets a reload signal, to make the changes visible. Sometimes this caused the automounter to crash.

Another approach

The source of the FUSE package contains the example program fusexmp, which acts like an bind/mirror mount: it mounts the root, thus /,
at the mountpoint. The whole idea is here to not mount the root (/), but another directory belonging to the user (mirror).

The Fuse interface makes it very easy to program this.
In Fuse, the path relative to the mountdirectory is very important. It's an argument of all of the Fuse functions, like getattr, readdir etcetera.

The Fuse example program processes this path without any modification, causing the various functions to look at the root /, causes the root / is mirrored.

Now fuse-workspace does puts the directory $HOME/.fuse/bind before this path, making this module to mirror the directory $HOME/.fuse/bind.

Copy of image at http://fuse.sourceforge.net


The second important thing I changed here is the ability to make a symbolic link to a directory look like a directory.
A symbolic link to for example the directory where HAL mounted an USB device, is presented as directory. This looks like an bind mount.


To achieve this, this module does the following things:

a. mirrors the directory which is an command line option of --bind-directory=, default /var/lib/workspace/%USERID/bind

b. my fs mirrors everything it finds, in case of a symbolic link it will do several things. First it will check the target of the link
is a md5key as used in the mount.md5key construction, an autofs managed mountpoint to a resource. To make this work, two extra options
are necessary: --autofs-mount-directory (default /mnt/mount.md5key/%USERID%/mount) and --autofs-cache-directory (default /var/cache/mount.md5key(
When the target is pointing to this directory (for this user) and the basename of the target exists in the cache directory, the symlink
a directory is presented into a directory

c. if the path (relative to the mountpoint of the module) also exists in the configuration directory, it's presented as a directory.
To make this work the option --conf-directory is necessary (default /var/lib/workspace/%USERID%/conf).
If b. and c. do not apply, leave it unchanged as a symbolic link.

This feature makes it LOOK LIKE everything is present in one place under the directory where this module is mounted, while in fact
it's a trick. But there is nothing wrong with that.

d. Futher, if the file path/.directory is looked up, and path is pointing to an autofs managed directory with md5keys (like in b.)
it will lookup the file in the cache, which is related to the target. So if path is pointing to:

/mnt/mount.md5key/%USERID%/mount/%md5key%

it will look for the file .directory in the cachedirectory, which defaults to:

/var/cache/mount.md5key/%md5key%

If it exists there take that one, else return an error for not finding the file.

This construction it here to prevent mounting of shares by the automounter when an application does a lookup of a .directory file.
The real nice advantage here is that these .directory files (and possible others) are managed from the local host, providing the
local applications the necessary information how to present the directory, including the icon. The construction uses various
configuration files (system and user wide) to set these icons.

An example, a path and a symlink to a autofs mountpoint for an USB stick is converted like:

/var/lib/workspace/sbon/bind/Devices/USB_DISK_28X ->
                  /mnt/mount.md5key/sbon/mount/cd533116c2ad65ae296d923c6dc83dd


looks in /home/sbon/Workspace:

Devices/USB_DISK_28X

where USB_DISK_28X is a directory, not a symlink anymore.

Installation

Setup

To make use of the fusemodule, compile it:

gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fuse-workspace-ll.c -o fuse-workspace-ll

Activate it:

(as root)
install --directory /var/lib/workspace/%USERID%
install --owner=%USERID% --directory /var/lib/workspace/$USERID/{bind,conf}

(as yourself:)

mkdir ~/Workspace
%path to where fuse-workspace-union is%/fuse-workspace-union --bind-directory=/var/lib/workspace/%USERID%/bind \
                                                             --conf-directory=/var/lib/workspace/%USERID%/conf \
                                                             ~/Workspace

(note this will not make use of the md5key construction. If you want to make it do that, do the following)

%path to where fuse-workspace-union is%/fuse-workspace-union --bind-directory=/var/lib/workspace/%USERID%/bind \
                                                             --conf-directory=/var/lib/workspace/%USERID%/conf \
                                                             --autofs-mount-directory=/mnt/mount.md5key/%USERID%/mount \
                                                             --autofs-cache-directory=/var/cache/mount.md5key \
                                                             ~/Workspace

Examples

Simple example

There is nothing in the workspace now, create a symlink to the system documentation:

mkdir /var/lib/workspace/%USERID%/bind/Documents
ln -sf /usr/share/doc /var/lib/workspace/%USERID%/bind/Documents/System

At this moment the symbolic link is still a symbolic link (test it!), adjust this by creating the directory in the shadow map:

mkdir -p /var/lib/workspace/%USERID%/conf/Documents/System

Check the workspace:

ls -al ~/Workspace/Documents
total 12
drwxr-xr-x  2 sbon root 4096 2009-09-28 10:37 .
drwxr-xr-x  4 sbon root 4096 2009-10-12 12:33 ..
drwxr-xr-x 60 root root 4096 2009-09-24 15:28 System
ls -al ~/Workspace/Documents/System
total 324                                           
drwxr-xr-x 60 root root  4096 2009-09-24 15:28 .    
drwxr-xr-x  2 sbon root  4096 2009-09-28 10:37 ..   
drwxr-xr-x  2 root root  4096 2008-07-03 19:02 acl  
drwxr-xr-x  2 root root  4096 2009-03-29 01:14 at   
drwxr-xr-x  2 root root  4096 2008-07-03 18:58 attr 
drwxr-xr-x  2 root root  4096 2008-05-11 19:46 automake
drwxr-xr-x  2 root root  4096 2008-05-11 19:47 bash-3.2
...
a lot of directories ....
...
drwxr-xr-x  2 root root  4096 2008-05-11 19:57 udev-113
lrwxrwxrwx  1 root root    16 2008-12-25 18:13 vim-7.1 -> ../vim/vim71/doc
drwxr-xr-x  2 root root  4096 2009-03-13 11:03 xen
drwxr-xr-x  2 root root  4096 2008-08-23 22:43 xfsprogs
drwxr-xr-x  3 root root  4096 2008-06-06 19:03 xine-lib

As you can see it LOOKS LIKE the documentation in /usr/share/doc is IN the directory ~/Workspace/Documents/System.



This way the system documentation is a subdirectory of your own Documents map.



Hardware like USB devices


Creating a symlink to hardware is possible. An USB stick is mounted by HAL:

Make a symlink.

ln -sf /media "/var/lib/workspace/sbon/bind/media"
mkdir -p "/var/lib/workspace/sbon/conf/media"

Now the device is also available at /home/sbon/Workspace/media/disk.

Another aproach is to make a symlink per device:

mount | grep /media
/dev/sdb1 on /media/disk type vfat (rw,nosuid,nodev,uhelper=hal,uid=4000,utf8,shortname=mixed)

Create a symlink for this device. Note you can choose your own name:

mkdir "/var/lib/workspace/sbon/bind/Devices"
ln -sf /media/disk "/var/lib/workspace/sbon/bind/Devices/My USB stick"
mkdir -p "/var/lib/workspace/sbon/conf/Devices/My USB stick"

Notes


Automation

It's very easy to automate the above commands at the moment a device is added (and removed).


Using automounter in stead of HAL.

The big disadvantage with HAL imho is that it mounts the device only once, with all the files/dirs owned by one user. This is not working in a multiuser environment like multiseat, where more users may want to access the disk.
Now with this construction it's very possible the user has a mirrored mountpoint to the device,
where the mountpoint itself is managed bu autofs. Below is described to use the automounter to access network resources like
Windows/Samba shares, using "md5 service records", with all the necessary information to mount them. It's not hard to extend this
construction with "local hardware service records" for mounting CDroms, USB devices etc.

This way, the device is mounted multiple times, every user has her/his own mountpoint, every mount with it's own specific
options.

Export "mirrored mountpoint" to (graphical) environment

In an environment like KDE, the directory under which the device is available (here: ~/Workspace/Devices/My USB stick)
should also be used by applications like Dolphin, when it's showing a list of USB devices. Now it's only using the general (system)
directory /media/disk. It's already possible by HAL (and I believe DeviceKit) to use more than one mountpoint, but it's still using
the general mountpoint at /media. There is no easy tool in KDE as far as I know to configure this.

Shared/public directories

Shared directories are very easy to setup.
Create an user/group, and make other users member of the same group:

(as root)
groupadd publicuser
useradd -c "Public user" -d /home/public -m -s /bin/false -g publicuser publicuser
mkdir -p "/home/public/Shared documents" 
chown publicuser:publicuser "/home/public/Shared documents"
chmod 775 "/home/public/Shared documents"
usermod -G publicuser %YOURUSERID%

Next is to make symlinks from your workspace to it:

ln -sf "/home/public/Shared documents" "/var/lib/workspace/sbon/bind/Shared documents"
mkdir -p "/var/lib/workspace/sbon/conf/Shared documents"

Now you're able to access the contents of this shared directory. Note that permissions are not changed in any way. If another user has saved a file there with access rights only for him/herself you can see it, but still not do anything with it. The fusemodule does not change permissions. (and it should run as root if it does).

It's also possible to create a subdirectory of the Documents folder shared:

mkdir ~/Documents
ln -sf ~/Documents ~/var/lib/workspace/sbon/bind/Documents
mkdir -p /var/lib/workspace/sbon/conf/Documents

Now the documents in ~/Documents are also present in the Workspace. Create a link to the shared documents, and make it look like a directory:

ln -sf "/home/public/Shared documents" ~/Documents/shared
mkdir -p /var/lib/workspace/sbon/conf/Documents/shared

Network access with automounter

It's also possible to mirror an autofs managed mountpoint of network resources, like Samba/Windows shares.


Create an autofs mountpoint as described here:

http://linux.bononline.nl/linux/mount.md5key

Here files are used to store information about a Windows share for example:

#> cat /var/cache/mount.md5key/980d82abb098209ffa60e9d6a537385a
NET_service=smb
LOCAL_user=sbon
SMB_workgroup=BONONLINE
SMB_name=ROUTER
SMB_share=bononline
SMB_ip=192.168.0.1

Now for every mdkey file available for this user, create a symlink:

[]# mkdir -p "/var/lib/workspace/sbon/bind/Network/Windows Network/BONONLINE/ROUTER"
[]# ln -sf /mnt/mount.md5key/sbon/mount/980d82abb098209ffa60e9d6a537385a \
       "/var/lib/workspace/sbon/bind/Network/Windows Network/BONONLINE/ROUTER/bononline"
[]# mkdir -p "/var/lib/workspace/sbon/conf/Network/Windows Network/BONONLINE/ROUTER/bononline"
[]# touch "/var/lib/workspace/sbon/conf/Network/Windows Network/BONONLINE/ROUTER/bononline/autofs-managed"


The result is an browseable tree in the workspace, where one is able to access the SMB network, with the help of the automounter:

[]# mount | grep /mnt/mount.md5key
[]# cd "~/Workspace/Network/Windows Network/BONONLINE/ROUTER/bononline"
[]# ls -al
total 8
drwxr-xr-x  2 root root     4096 2009-08-27 13:39 .
drwxr-xr-x  2 root root     4096 2009-09-08 09:54 ..
lrwxrwxrwx  1 root root       18 2008-07-29 10:31 linux.bononline.nl -> linux.bononline.tk
drwxr-xr-x  7 sbon netgroup    0 2008-11-09 15:12 linux.bononline.tk
drwxr-xr-x  2 sbon netgroup    0 2006-08-21 20:15 scripts
lrwxrwxrwx  1 root root       16 2008-07-29 09:51 www.bononline.nl -> www.bononline.tk
drwxr-xr-x 11 sbon netgroup    0 2007-06-16 12:38 www.bononline.tk
drwxr-xr-x  6 sbon netgroup    0 2006-06-11 13:30 www.intern.bononline.tk
[]# mount | grep /mnt/mount.md5key
//ROUTER/bononline on /mnt/mount.md5key/sbon/mount/980d82abb098209ffa60e9d6a537385a type cifs (rw,mand)

Notes

Automation

As described at the page about mounting with the help of the md5 keys, it's very easy to make the host
discover every SMB host/server with tools like nbtscan or nmblookup. For every host found,
it's also easy to determine the shares an user has access to with smbclient, and create these md5key files
with this information.
Next it's easy to update the directories under /var/lib/workspace/%USERID%/bind and /var/lib/workspace/%USERID%/shadow,
pointing to the right entries in the automounter managed directory /mnt/mount.md5key/%USERID%/mount.


And futher: ANYTHING mountable, direct or with Fuse, and thus is mountable by the automounter WORKS!!!.
I've created records for FTP (with curlftps) and SSH (with sshfs) and changed the mounter mount.md5key
so it supports these services by calling the right mount command (with the right parameters).

I'm not able to test it, but I'm convinced that mounting Netware (NCP/IPX) shares is also possible. This may look like:

/home/sbon/Workspace/Network/Novell Network/Some Server/Some share

Other examples

Other examples are possible, like special directories where files are filtered or archives are extracted.

Features

ACL are supported, if the underlying filesystem supports is.
Futher inotify is not supported.

Interception of .directory files

By default the module intercepts .directory files when the directory it is in is a md5key-autofs managed directory.
It will not present the eventual .directory in this directory, but in the cache directory for this resource.
To explain: when an application (like Dolphin in KDE) does a lookup of a .directory file in

~/Workspace/Network/Windows Network/BONONLINE/ROUTER/bononline

this fuse module intercepts this call. As already explained above, the resource the SMB server ROUTER, share bononline,
ipnumber 192.168.0.1, with md5key 980d82abb098209ffa60e9d6a537385a.
In stead of looking it up at the autofs managed directory /mnt/mount.md5key/sbon/mount/980d82abb098209ffa60e9d6a537385a/.directory
(which will of course make is mount), it will look for the .directory file in
/var/cache/mount.md5key/980d82abb098209ffa60e9d6a537385a/. This behaviour has the advantage that these "cosmetics" file are managed
on the localhost, independent from the target.

Per 2010-03-08 the fuse module determines the resource is mounted or not, making it possible to present different .directory files,
presenting the state it's mounted or not mounted. To demonstrate, I'm doing a lookup of a .directory file from a shell, manual:

sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ ls -l
total 20
drwxr-xr-x 2 root root     4096 2010-02-28 14:33 bononline
drwxr-xr-x 2 gast netgroup 4096 2010-02-28 14:33 ftp
drwxrwxr-x 2 gast netgroup 4096 2010-02-28 14:33 public
drwxr-xr-x 2 sbon netgroup 4096 2010-02-28 14:33 sbon
drwxr-xr-x 2 root root     4096 2010-02-28 14:33 video
sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ mount | grep /mnt/mount.md5key
//SCLFS20091030/video on /mnt/mount.md5key/sbon/mount/54735268b08375cb5d11b46325210ac7 type cifs (rw,mand)
//SCLFS20091030/bononline on /mnt/mount.md5key/sbon/mount/7810adcea773f747c7e3bea8dda70038 type cifs (rw,mand)

(there are obvious two shares mounted: I'm working on this website on this moment - this text!! - and amarok is playing a audio file)
(so do here first do a lookup of a .directory file of a share that's not mounted)

sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ cat sbon/.directory
[Desktop Entry]
Icon=/opt/kde-4.4/share/icons/nuvola/128x128/devices/nfs_unmount.png

[Dolphin]
AdditionalInfo=42
sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ mount | grep /mnt/mount.md5key
//SCLFS20091030/video on /mnt/mount.md5key/sbon/mount/54735268b08375cb5d11b46325210ac7 type cifs (rw,mand)
//SCLFS20091030/bononline on /mnt/mount.md5key/sbon/mount/7810adcea773f747c7e3bea8dda70038 type cifs (rw,mand)

(the lookup does not make the share mounted!!! Now look what's happening when it is mounted)
sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ ls -l sbon
total 5147
-rw-------  1 sbon netgroup   12800 2008-10-12 21:27 aasome.doc
-rw-r--r--  1 sbon netgroup   20992 2009-06-02 18:34 another.doc
...
...
...
a lot of (private) files
...
...
...

sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ mount | grep /mnt/mount.md5key
//SCLFS20091030/bononline on /mnt/mount.md5key/sbon/mount/7810adcea773f747c7e3bea8dda70038 type cifs (rw,mand)
//SCLFS20091030/video on /mnt/mount.md5key/sbon/mount/54735268b08375cb5d11b46325210ac7 type cifs (rw,mand)
//SCLFS20091030/sbon on /mnt/mount.md5key/sbon/mount/8fa6f400cdf2f053817f3965188f4acc type cifs (rw,mand)
sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ cat sbon/.directory
[Desktop Entry]
Icon=/opt/kde-4.4/share/icons/nuvola/128x128/devices/nfs_mount.png

[Dolphin]
AdditionalInfo=42

(the share is mounted, and the module is presenting a different .directory file)
(these files are actually at /var/cache/mount.md5key/8fa6f400cdf2f053817f3965188f4acc:)

sbon [ ~/Workspace/Netwerk/Windows Netwerk/BONONLINE/SCLFS20091030 ]$ ls -l /var/cache/mount.md5key/8fa6f400cdf2f053817f3965188f4acc/.directory*
-rw-r--r-- 1 root root 114 2010-02-28 14:33 /var/cache/mount.md5key/8fa6f400cdf2f053817f3965188f4acc/.directory
-rw-r--r-- 1 root root 112 2010-03-06 18:21 /var/cache/mount.md5key/8fa6f400cdf2f053817f3965188f4acc/.directory.mounted

Locking and Extended attributes

Within FUSE, it was very easy to implement these features. Extended attributes are supported when the underlying filesystem
supports them. With locking the same. For locking there is a special library (libulockmgr). This works even with a
network filesystem like cifs.

Use of a configuration tree

The module uses a special conf tree, next to the bind directory, which is used as a runtime configuration. As already demonstrated above
it is used to make a symlink look like a directory.
This configuration tree is also used by scripts (manage_workspace.sh) to maintain the various directories to resources. For example,
when after a new lookup of all the SMB network resources the previously detected shares on a server have disappeared, this will
result that ll shares are removed from the fuse-workspace-union map. Removing the symbolic links from the bind and conf trees are
sufficient. BUt this will result in a directory representing the server, which offers no shares. This means that also the servermap
has te be removed. But how does the manage_workspace.sh know that this map cannot be empty and therefore has to be removed?
For this purpose there is the file .notempty in the directory (in the conf tree) which cannot be empty. The same story with the
workgroup. If the server is the last server, and removed, than there appears an empty workgroup, which should not happen. To avoid this
also these directories have .notempty files in the config tree.

Screenshots

Idea's

Access the data in the non empty mountpoint

I'm looking at the ability to mount the workspace module directly at the directory of users home.
The problem is that we're not only dealing with an non empty mountpoint, but it must also be possible
to access the data in the original homedirectory.

The way to do that is to mount the home to another place first like:

mount --move %HOMEofUSER% /var/lib/workspace/%USERID%/bind

fuse-workspace-union --bind-directory=/var/lib/workspace/%USERID%/bind ....other paramters... %HOMEofUSER%



In the maillinglist of fuse-devel this topic is discussed :

[fuse-devel] Accessing the underlying directory when using nonempty option


Integration with target fs specific helpers (libraries)

The module does some caching. The way it does that works, but could be be better. When accessing a SMB share
it's better to have a preview of the permissions via libsmbclient.so, in stead of caching it (with risk of wrong values).


Show and hide a directory (like GoboLinux)


Today (10 march 2010) I've visited the website of GoboLinux, and was really really realy impressed how nice this distribution
works. I've tried the live cd in VirtualBox, awesome! Check it yourself:

http://gobolinux.org


With Fuse this is also possible. FUSE supports ioctls in userspace, so it is possible to communicate with the fuse fs,
for exampe to instruct it to hide or show directories.

Maybe it's possible to create a chroot construction here, but it does not have my attention.

Ask the module about the origin of the file

When posting about this construction on KDE devellists/brainstorm, somebody noted that it's important for applications to
"know" the origin of a file, is it from the local machine, or from the network. That's also possible (well in theory for now)
via a ioctl device. It's not hard to make the fuse module detect the resource it's on. Everything is a resource in this construction,
even the local machine is a resource. Now when accessing a resource via the mount helper (autofs) it's not so hard to match
the path to a URI service location:


when for example playing a mp3 on amarok, it's playing the file in the workspace


Network/Windows Network/MyWorkgroup/MyServer/MediaShare/mp3/Abba-The winner takes it all.mp3

it's very easy to make it translate this path into:

smb://MyServer/MediaShare/mp3/Abba-The winner takes it all.mp3


The other way also works, but depends on how the user has configured his/her fuse-workspace. In my construction it's possible to
hide the workgroup and/or use different names. I'm dutch, so for me this URI is translated into:


Netwerk/Windows Netwerk/MyServer/MediaShare/mp3/Abba-The winner takes it all.mp3


Note that it's also possible to communicate more than the URI. Also the name of the resource record is very usefull.

What is supported and what not

Normal operations are supported by fuse in general and this module specific. To name some:

- extended attributes (ACL's). The module will a request for xattr pass through to the underlying fs. So if that fs supports them,
this module does also.
- locking. Normal UNIX like locking is supported.
- seeking though files.


Some important things are not supported yet. I do not know the status of memory mapping (how can I test it?) but I do know inotify does
not work with FUSE in general. To be clear, setting an inotify watch on a directory in a FUSE based filesystem does work already.
It (with inotifytools for example) will report every activity on the directory it's set upon. But that does not mean that FUSE is
supporting inotify. An example, if you have an FUSE fs which makes a database in MySQL look like an fs (there is such a fs).
Full support for inotify means that when a client wants to monitor a directory of this fs, that every action in that directory
(read:in the database) is reported back through the fuse module back to the client. So, when another client or user is removing
a file in that particular directory, the fuse module must pass through this change to the client who asked for it before.

To be more specific, if a client gives an inotify command to monitor a directory (or a file), the call should, like any other system
call or operation (like readdir, getattr and open) be passed through by glibc, kernel VFS and the FUSE kernel module to the FUSE fs.
This fs will translate the standard call (inotify_add_watch) into a for this fs specific call. I do not know it's possible to
to monitor a MySQL database with an fd, but suppose it is, then the changes in the database should be passed back (and only then)
to the original inotify request.

It's easier when you've got an overlay fs, then the incoming inotify system call (inotify_add_watch or inotify_rm_watch) is linked to
an fuse fs specific call, which on his turn do the same command on the underlying fs: a call to add a watch on the fuse fs will result
in a call to add a watch on the underlying fs, and the changes on the underlying fs should be given back. To summarize:

- I do not exactly know how an inotify system call is handled in the kernel/VFS, but it should be passed to the fuse module, just like
any other call, and mapped to a fs specific operation:

.inotify_add_watch    =   myfs_inotify_add_watch, 
.inotify_rm_watch     =   myfs_inotify_rm_watch,

The add_watch call should result in an fd, which should be managed with select/poll/epoll to read for incoming events.
These events (standard inotify_event format?) should be forwared back to the original add_watch call. The latest is also
an fd, but should it also be polled to be ready to be written to? I do not know.
One parameter is of course the path.

Forwarding from the underlying fs to the fuse fs is simple, too simple. Fact is that my fs does some modifications. The inotify
events comming from the underlying fs should therefore also have some modifications....

To add these fd's to the main epoll instance is an challenging task. They have to be treated not like the other operations, these
are command driven. An inotify event can occur anytime. So the fd should be watched constantly.

When setting a watch on the underlying fs, I think it's a good thing to add this to the already declared inotify instance.
This instance it watched with epoll. Suppose there are more than one of those watches added (or activated). Now the system
will pass through any event back to the inotify instance. When these are noted and managed with epoll, it's not so hard
to match these events with the original inotify request on the fuse fs. To do that an array or linked list with elements
which matches the original watch descriptor to the watch descriptor used by the fuse module.

Per resource different actions

Inotify is what I'm working on at this moment (7 may 2010). It's obvious that the way to get notified on changes
on a resource. differs per resource. For example, inotify works perfectly on a local device ( is a device which
is not shared with another host/os) but does not work good on a shared remote SMB share.

(note that on this moment inotify is being worked on in the GSOC 2010:

[linux-cifs-client] [GSoC 2010][RESEND] Questions on Improved async/vector i/o support, fscache integration, and VFS change notification

Futher inotify is not necessary on a "fixed" filesystem like a CDROM.
So it looks that the inotify requests should be handled different per resource. So it's probably necessary to use
something simular like gamin, a server to monitor files and directories.:

Homepage of gamin.

There are more mechanismes which can differ per resource:
- user quota's
- indexing. Indexing an USB device is very possible, indexing a remote share is not what you want.
- encryption
- ...



License

This software and the construction is distributed under the terms of the GNU General Public License. A copy you'll find at the src directory.