Uncanny overlay behavior... bug in overlayfs?
mgree opened this issue · comments
Look at the following interaction:
~/try $ uname -a
Linux hippogriff 6.7.12-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.7.12-1 (2024-04-24) x86_64 GNU/Linux
~/try $ mkdir d
~/try $ touch d/oldfile
~/try $ ./try -n "rm -r d; mkdir d; touch d/newfile"
/tmp/tmp.JNMeX6OTCV
~/try [commit-utils] $ ls -al /tmp/tmp.JNMeX6OTCV/upperdir/home/mgreenbe/try/d
total 0
drwxrwxr-x 2 mgreenbe mgreenbe 60 Jun 7 12:02 .
drwxr-xr-x 3 mgreenbe mgreenbe 60 Jun 7 12:02 ..
-rw-rw-r-- 1 mgreenbe mgreenbe 0 Jun 7 12:02 newfile
~/try $ utils/try-summary /tmp/tmp.JNMeX6OTCV/upperdir
Changes detected in the following files:
/home/mgreenbe/try/d/newfile (added)
~/try $ utils/try-commit /tmp/tmp.JNMeX6OTCV/upperdir
~/try $ ls d
newfile oldfile
Why on earth is oldfile
still there?
Ah! Because user.overlay.opaque
is set to y
. 🤦
Kernel docs had me looking for trusted.overlay.opaque
.
It appears that overlayfs is not creating the whiteout file for old when the directory is recreated(?)
Right: it doesn't need to, because an opaque directory ignores everything from the lowerdir. It's a bug in our summary/commit semantics (and in the kernel docs lol).
for context:
whiteouts and opaque directories
In order to support rm and rmdir without changing the lower filesystem, an overlay filesystem needs to record in the upper filesystem that files have been removed. This is done using whiteouts and opaque directories (non-directories are always opaque).
A whiteout is created as a character device with 0/0 device number or as a zero-size regular file with the xattr “trusted.overlay.whiteout”.
When a whiteout is found in the upper level of a merged directory, any matching name in the lower level is ignored, and the whiteout itself is also hidden.
A directory is made opaque by setting the xattr “trusted.overlay.opaque” to “y”. Where the upper filesystem contains an opaque directory, any directory in the lower filesystem with the same name is ignored.
An opaque directory should not conntain any whiteouts, because they do not serve any purpose. A merge directory containing regular files with the xattr “trusted.overlay.whiteout”, should be additionally marked by setting the xattr “trusted.overlay.opaque” to “x” on the merge directory itself. This is needed to avoid the overhead of checking the “trusted.overlay.whiteout” on all entries during readdir in the common case.
Okay, so in the commit logic, we want to check each directory for user.overlay.opaque
, and completely replace the lowerdir of that directory with it.
When that is set to y
, it means we need to destroy the existing lowerdir. But don't worry about this---I am doing it!