binpash / try

Inspect a command's effects before modifying your live system
MIT License
5.17k stars 64 forks source link

Uncanny overlay behavior... bug in overlayfs? #163

Closed mgree closed 1 month ago

mgree commented 1 month ago

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?

mgree commented 1 month ago

Ah! Because user.overlay.opaque is set to y. :facepalm:

Kernel docs had me looking for trusted.overlay.opaque.

ezrizhu commented 1 month ago

It appears that overlayfs is not creating the whiteout file for old when the directory is recreated(?)

mgree commented 1 month ago

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

ezrizhu commented 1 month ago

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.

ezrizhu commented 1 month ago

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.

mgree commented 1 month ago

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!