Around this time last year, I posted about setting up a udev rule to run a script when I plugged my USB drive containing all of my music into one of my laptops; the script, a couple of lines of bash, removes all pre-existing symlinks to $HOME/Music and repopulates the directory with an updated set. Almost. The one flaw that has been an irritant of variable intensity, depending on what I felt like listening at any given time, is that the symlinks aren’t written for directories that already exist on the target filesystem.
In order that I am able to play some music if I forget the USB drive, each of
the laptops has a subset of albums on it, depending on the size of their
respective hard drives. If I add a new album to the USB drive, then that change won’t
get written to either of the laptops when the drive is plugged in. Not entirely
satisfactory. I had tinkered around with
globbing, or with
having find(1)
scan deeper into the tree, or even a loop to check for the presence of directories in an array…
It just got too hard. My rudimentary scripting skills and the spectre of recursion, I am sorry to admit, conspired to undermine my resolve. So, rather than concede unconditional surrender, I asked for help. As is almost always the case in these situations, this proved to be a particularly wise move; the response I received was neither what I expected, nor was it anything I was even remotely familiar with: so in addition to an excellent solution (one far better suited to what I was trying to achieve), I learned something new.
The first comment on my question proved singularly insightful.
Care to use union mounts, for example via overlayfs?
A union mount, something until now I was blissfully unaware of, is according to Wikipedia,
a mount that allows several filesystems to be mounted at one time, appearing to be one filesystem.
Union mounting has a long and storied history on Unix, beginning in 1993 with the Inheriting File System (IFS). The genealogy of these mounts has been well covered in this 2010 LWN article by Valerie Aurora. However, it is only in the current kernel, 3.18, that a union mount has been accepted into the kernel tree.
After reading the documentation for overlayfs, it seemed this was exactly what I was looking for. Essentially, an overlay mount would allow me to “merge" the underlying tree (the Music directory on the USB drive) with an “upper” one, $HOME/Music on the laptop, completely seamlessly.
Then whenever a lookup is requested in such a merged directory, the lookup is performed in each actual directory and the combined result is cached in the dentry belonging to the overlay filesystem.
It was the just a matter of adapting my script to use overlayfs
, which was
trivial:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
And now, when I plug in the USB drive, the contents of the drive are merged with my local music directory, and I can access whichever album I feel inclined to listen to. I can also copy files across to the local machines, knowing if I update the portable drive, it will no longer mean I have to forego listening to any newer additions by that artist in the future (without manually intervening, anyway).
Overall, this is a lightweight union mount. There is neither a lot of functionality, nor complexity. As the commit note makes clear, this “simplifies the implementation and allows native performance in these cases.” Just note the warning about attempting to write to a mounted underlying filesystem, where the behaviour is described as “undefined”.
Notes
Creative Commons image, mulitlayered jello by Frank Farm.