2011-05-17

I’m currently experimenting with a low-effort technique for mimicking the benefits of a hybrid solid state/hard disk drive.

My approach is to use a union mount with multiple writable branches to combine folders from both an ssd and hdd into a single home folder in the root filesystem. The result is a unified home folder that contains a mixture of files from each drive in a way that is transparent to the operating system:

Hybrid SSD/HDD home folder

Newly created files are stored on the same device as their parent folder. Files created at the root of the home folder are typically configuration files and so default to the ssd.

As the screenshot reveals, I have also drafted a Nautilus extension that detects which storage back end each file uses and labels those which use the ssd.

The branches of the union mount exist externally as folders within the root filesystem. I chose to place them within /home/.ssd and /home/.hdd. On my system / already uses the ssd so /home/.ssd can simply exist as a regular folder, while /home/.hdd is mounted separately. /etc/fstab contains:

# / containing /home/.ssd (Physical SSD)
UUID=... / ext4 noatime,discard,errors=remount-ro 0 1

# /home/.hdd (Physical HDD)
UUID=... /home/.hdd ext4 errors=remount-ro 0 2

The default file creation policy in aufs is to store new files within the same branch as their parent folder, with files created in the root directory of the union filesystem defaulting to the first listed branch. As long as the ssd branch is listed first, no other policy needs to be explicitly defined:

# /home/ak from SSD and HDD mounts
none /home/ak aufs noauto,br:/home/.ssd/ak=rw:/home/.hdd/ak=rw 0 0

It is critical that this entry in /etc/fstab be mounted only after the previous two lines so that the incorporated branches contain mounted filesystems and not empty mount points. Until I learn how to specify a particular mount order in /etc/fstab, I have disabled automatic mounting of the union mount (noauto above) and instead mount it during /etc/rc.local:

# Workaround to mount aufs only *after* its branches exist
mount /home/ak

Back end detection is accomplished with a custom emblem in ~/.local/share/icons/hicolor/24x24/emblems and a Nautilus-Python extension saved as ~/.nautilus/python-extensions/ssd-emblem.py that checks for parallel files in /home/.ssd:

import os.path
import nautilus

class SsdEmblem(nautilus.InfoProvider):
def update_file_info(self, file):
union = "/home/ak/"
ssd = "/home/.ssd/ak/"

path = os.path.realpath(file.get_location().get_path())

if path.startswith(union) and os.path.exists(path.replace(union, ssd, 1)):
file.add_emblem("ssd")

After using this for a week I’m pleased with the results. There is a noticeable improvement in login times compared with my previous configuration that stored the entire home folder on a hdd.

I would like there to be an easy way to switch the storage back end of individual files and folders, ideally via a Nautilus context menu item. This looks possible via udba, but there are several potential quirks involved that I haven’t spent the time to thoroughly investigate.

Obviously, more work would need to be done for this to be scalable to multi-user environments or to be compatible with encrypted home folders. I have no plans to develop these areas.