Kernel Korner - Unionfs: Bringing Filesystems Together
By default, Unionfs attempts to delete all instances of a file (or directory) in all branches; this mode is called DELETE_ALL. Aside from DELETE_ALL, Unionfs also supports two more deletion modes, DELETE_WHITEOUT and DELETE_FIRST. DELETE_WHITEOUT behaves like the default mode externally, but instead of removing all files in the Union, a whiteout is created. This has the advantage that the lower-priority files still are available through the underlying filesystem. DELETE_FIRST departs from classical UNIX semantics. It only removes the highest-priority entry in the union and, thus, allows the lower-priority entries to show through. These modes also are used for the RENAME operation, as it is a combination of a create followed by a delete.
DELETE_FIRST requires some user knowledge of the union's components. This is useful when Unionfs is used for source code versioning, as in our previous example of a kernel source tree. If we change a file in /home/cpw/linux, the file is copied up to the higher-priority branch. If the file is deleted with standard DELETE_ALL semantics, Unionfs creates a whiteout in the highest-priority branch (because it cannot modify the read-only lower-priority branch). The original source file in the lower-priority branch is now inaccessible, so it must be copied into the union from the source, which hardly makes for a convenient versioning system. This situation is precisely where DELETE_FIRST comes in handy. The delete mode is specified as a mount option, as in the following example:
# mount -t unionfs -o \ > dirs=/home/cpw/linux:/usr/src/linux=ro,\ > delete=first none /home/cpw/linux
Now, as before, if we change a file in /home/cpw/linux, the changes don't affect /usr/src/ linux. If we decide we don't like the changes, we simply can remove the file and the original version will show through.
With the unionctl utility, Unionfs's branch configuration can change on the fly. New branches can be added anywhere in the union, branches can be removed and read-write branches can be marked read-only (or vice versa). This flexibility allows Unionfs to create filesystem snapshots. In this example, we use Unionfs to create a snapshot of /usr while installing a new package:
# mount -t unionfs -o dirs=/usr none /usr
At this point, Unionfs has a single branch that is read-write, /usr. All operations are passed to the lower-level filesystem, and it is as if Unionfs didn't exist.
Creating a snapshot involves two steps. The first is to specify the location of the snapshot files by adding a branch (say, /snaps/0), as follows:
# unionctl /usr --add /snaps/0
At this point, Unionfs creates new files for /usr in /snaps/0, but files in subdirectories of /usr are created in the underlying /usr. The reason for this seeming contradiction is the rule that files are created in the highest-priority branch where the parent exists. For files in the root directory of the union, /usr, the parent exists in both branches. Because /snaps/0 is the higher-priority branch, new files and directories are created physically in /snaps/0. However, /snaps/0 is empty, so if a file were created in /usr/local, the highest-priority parent actually would be in the underlying /usr branch.
To complete the migration, the original /usr branch needs to be read-only. Again, we use unionctl to modify the branch configuration:
# unionctl /usr --mode /usr ro
Now, because Unionfs thinks the underlying /usr is read-only, all write operations really take place in /snaps/0. Multiple snapshots can be taken simply by adding another branch, say, /snaps/1, and marking /snaps/0 as read-only.
The first snapshot can be viewed through the underlying directory, /usr. Each snapshot consists of a base directory and several directories that have incremental differences. To view a specific snapshot, all we need is to unify the first snapshot and the incremental changes. For example, to view the snapshot that consists of /usr and /snaps/0, mount Unionfs as follows:
# mount -t unionfs -o ro,dirs=/snaps/0:/usr \ > none /mnt/snap
In this example, Unionfs itself is mounted read-only, so the underlying directories are not modified.
After determining that the changes made in a snapshot are good, the next step often is to merge the snapshot back into the base. The Unionfs distribution includes a snapmerge script that applies incremental Unionfs snapshots to a base directory. This is done by recursively copying the files in the snapshot directory to the base. After the copy procedure is done, new files and changed files are completed. The last step is to handle file deletions, which is done by creating the list of whiteouts and deleting the corresponding files. The whiteouts themselves also are removed so as not to clutter the tree.
Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report
August 27, 2015
12:00 PM CDT
DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.
Free to Linux Journal readers.Register Now!
- Django Models and Migrations
- Hacking a Safe with Bash
- Secure Server Deployments in Hostile Territory, Part II
- The Controversy Behind Canonical's Intellectual Property Policy
- Home Automation with Raspberry Pi
- Huge Package Overhaul for Debian and Ubuntu
- Shashlik - a Tasty New Android Simulator
- KDE Reveals Plasma Mobile
- Embed Linux in Monitoring and Control Systems
- diff -u: What's New in Kernel Development