binpash / try

Inspect a command's effects before modifying your live system

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

commented

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).

commented

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.

commented

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!