-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix hardlink issue with whiteout deletes in the merge snapshotter. #4516
Conversation
b5ecae7
to
a35951a
Compare
Thanks @sipsma for the review. I’ll try to write a test but I tried to run the integration tests with
Not sure if that’s expected or I am doing something wrong? |
@gdlg Not sure what is wrong in that case and if it is a specific test, worker or something with your config, but you can run a specific test/pkg or worker with https://github.com/moby/buildkit/blob/master/.github/CONTRIBUTING.md#run-the-unit--and-integration-tests commands. |
Whiteouts may share the same inode which cause the snapshotter to attempt to create a hardlink between two whiteouts in the destination layer. The problem is that the first whiteout is only created if it is part of the lower layer from the base snapshot. Otherwise, the whiteout is not created in the destination layer because it is not needed. If the first whiteout is not created in the destination, attempting to create a hardlink for the second whiteout will fail. To avoid this issue, this fix disables hardlinks for whiteouts. Signed-off-by: Grégoire Payen de La Garanderie <[email protected]>
a35951a
to
bc646a6
Compare
I have added a test to mergediff_test.go which reproduces the issue on the master branch:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming this is ready, remove the draft label.
I have marked the PR as ready but I wasn’t able to run the full integration test suite on my machine due to lack of resources which causes a lot of timeouts. Is the CI sufficient? Otherwise I could try to get hold of a more powerful machine to run the tests on my side. |
Yup @gdlg don't worry, the CI is generally our source of truth for tests - no need to worry about running them all locally, I don't do that for any of my PRs. |
This PR attempts to fix the following error during a merge snapshot:
in the corresponding Dockerfile:
The file /file2 is included in the base snapshot by Merge() in snapshot/merge.go but not /file1. Due to this, when applying changes for /file1 in applyDelete(), the function decides to not create a whiteout for /file1 since it’s not part of the lower dirs from the base snapshot. It then tries to create a whiteout for /file2 (which is part of the lower dirs).
The issue occurs in applyHardlink() in snapshot/diffapply_unix.go which attempts to create a hardlink from /file2 to /file1 whiteouts in the destination layer. This attempt fails because we didn’t create any whiteout for /file1 (as it’s not needed). This hardlink occurs because /file1 and /file2 whiteouts in the upper layers share the same inode (even though they are created in different layers).
I think that it doesn’t make sense to try to create hardlinks between whiteouts in the destination layer because even if they share the same inode in the source, this is not an intended behaviour and there is no real relationship between the whiteouts in source layers. So in this PR, I propose to skip “delete changes” in the list of inodes used to create hardlinks. This causes applyHardlinks to create a cross-snapshot link to the original file (i.e. dest /file2 whiteout to src /file2 whiteout instead of doing dest /file2 to dest /file1).