Skip to content
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

fs: add DiffDirChanges function to get changeset fast #145

Merged
merged 1 commit into from
Jan 31, 2024

Conversation

fuweid
Copy link
Member

@fuweid fuweid commented Nov 23, 2019

Since AUFS/OverlayFS can persist changeset in diff directory,
DiffDirChanges function can retrieve layer changeset from diff directory
without walking the whole rootfs directory.

Signed-off-by: Wei Fu fuweid89@gmail.com

@fuweid fuweid changed the title fs: add DiffDirChanges function to get changeset fast [RFC] fs: add DiffDirChanges function to get changeset fast Nov 23, 2019
@fuweid
Copy link
Member Author

fuweid commented Nov 23, 2019

The original issue is from moby/buildkit#1192. The docker uses graphdriver to retrieve the layer diff based on AUFS/OverlayFS and it is fast than containerd Compare API which walks the whole rootfs directory.

The github.com/containerd/continuity/fs package provides the Changes function, and it is hard to get relationship between two rootfs paths without original mount information, since the overlayfs mount info might be changed by Chdir if there are too many lowerdirs. Therefore, add new function named by DiffDirChanges and containerd Compare API can choose the efficient way to retrieve diff layer.

@dmcgowan @tonistiigi @AkihiroSuda

@fuweid fuweid force-pushed the me-support-diff-change-walk branch 2 times, most recently from ade3c4b to 3214e3b Compare November 30, 2019 09:12
@fuweid fuweid changed the title [RFC] fs: add DiffDirChanges function to get changeset fast [WIP|RFC] fs: add DiffDirChanges function to get changeset fast Dec 12, 2019
Copy link
Member

@ktock ktock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fuweid Are you still working on this?
Fixing slow diff has been gathering demand in the community (moby/buildkit#1704, moby/buildkit#1192).
Can we move this forward?

fs/diff.go Outdated
Comment on lines 177 to 180
case DiffSourceAUFS:
o = &diffDirOptions{
skipChange: skipAUFSMetadata,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUFS snapshotter is deprecated since containerd v1.5. Could we focus on overlayfs in this PR?

@fuweid
Copy link
Member Author

fuweid commented Jun 15, 2021

@fuweid Are you still working on this?

Fixing slow diff has been gathering demand in the community (moby/buildkit#1704, moby/buildkit#1192).

Can we move this forward?

yeah. will update it in days~ Thanks!

@pankajkumar229
Copy link

Why was this never merged?

@AkihiroSuda
Copy link
Member

I think this can be just merged after rebasing and removing AUFS codes

@fuweid
Copy link
Member Author

fuweid commented Jan 24, 2024

oops. Will update it later. Thanks for remider

@fuweid fuweid force-pushed the me-support-diff-change-walk branch from 3214e3b to b9af6a9 Compare January 24, 2024 13:54
@fuweid fuweid changed the title [WIP|RFC] fs: add DiffDirChanges function to get changeset fast fs: add DiffDirChanges function to get changeset fast Jan 24, 2024
@fuweid fuweid marked this pull request as ready for review January 24, 2024 13:54
// CreateDeviceFile provides creates devices Applier.
func CreateDeviceFile(name string, mode os.FileMode, maj, min int) Applier {
return applyFn(func(root string) error {
return errors.New("Not implemented")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: should we use errdefs.ErrNotImplemented?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Let me handle it in the follow-up. (Use containerd/errdefs repo to handle this).

fs/diff_test.go Outdated
@@ -350,7 +397,38 @@ func testDiffWithoutBase(t testing.TB, apply fstest.Applier, expected []TestChan
return checkChanges(tmp, changes, expected)
}

func testDiffDirChange(base, diff fstest.Applier, source DiffSource, expected []TestChange) error {
baseTmp, err := ioutil.TempDir("", "fast-diff-base-")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ioutil is deprecated

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

fs/diff_test.go Outdated
func (tcs TestChanges) Len() int { return len(tcs) }
func (tcs TestChanges) Less(i, j int) bool { return tcs[i].Path < tcs[j].Path }
func (tcs TestChanges) Swap(i, j int) { tcs[i], tcs[j] = tcs[j], tcs[i] }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just use sort.Slice?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

fs/diff.go Outdated

if f.IsDir() {
originalPath := filepath.Join(diffDir, path)
opaque, err := sysx.LGetxattr(originalPath, "trusted.overlay.opaque")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user.overlay.* has to be checked too
torvalds/linux@2d2f2d7

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Please take a look.

fs/diff.go Outdated
originalPath := filepath.Join(diffDir, path)
opaque, err := sysx.LGetxattr(originalPath, "trusted.overlay.opaque")
if err != nil {
if err == unix.ENODATA {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors.Is is more preferable over directly using the = operator

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@fuweid fuweid force-pushed the me-support-diff-change-walk branch from b9af6a9 to 349dea6 Compare January 24, 2024 15:01
@fuweid fuweid force-pushed the me-support-diff-change-walk branch 5 times, most recently from bcc5706 to 2545354 Compare January 24, 2024 16:06
@pankajkumar229
Copy link

Many Thanks for the quick turnaround.

@fuweid fuweid force-pushed the me-support-diff-change-walk branch from 2545354 to 19f4218 Compare January 24, 2024 16:11
deletedFile := false

if o.deleteChange != nil {
deletedFile, err = o.deleteChange(diffDir, path, f, changeFn)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nilt: We don't need to mark this file as "deleted" if this file doesn't exist in the base dir.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. Let me think how to handle this

fs/diff_linux.go Outdated
Comment on lines 62 to 66
// FIXME(fuweid): In spite of that .wh..wh..opq might not be
// existing, mark it as faked delete change so that changeFn
// will add whiteout prefix for this faked file. It requires
// that changeFn callback must not read the os.FileInfo
// parameter.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the convention introduced here is that if 3rd arg is nil then changeFn must make the dir opaque, right? Could we add this explanation to godoc of DiffDirChanges?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Sorry for late reply. Let me think about how to remove FIXME

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't want to introduce a new convention, another approach might be starting a new doubleWalkDiffer on the opaque directory to make changeFn opaque-agnostic.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Please take a look.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For deleted file, 3rd one is nil. FYI

@pankajkumar229
Copy link

Is it possible to get this change to a previous version of containerd when it gets released?

@AkihiroSuda
Copy link
Member

Is it possible to get this change to a previous version of containerd when it gets released?

Unlikely, due to potential risk of regression.

@pankajkumar229
Copy link

Is it possible to merge this soon? It will help us compile our own containerd. OTherwise I think we will need some code changes in containerd to use this branch or another fork.

Thanks again for the quick turnaround.

@pankajkumar229
Copy link

We still see the slowness in commit. It is possibly because "nerdctl commit" is calling the function Compare inside containerd and it seems to create a two temporary mounts: upperRoot and lowerRoot. Both seem to have a full copy of the file system. Now when compare calls writeDiff, even if continuity can check for overlayfs, it is still going through a lot of files and taking forever to do "nerdctl commit". What would be a good way to fix this?

Screenshot 2024-01-27 at 3 50 18 PM

Although this belongs to the containerd repository , I thought I would ask here since I saw Mr. Kohei Tokunaga's name in the relevant code and it is possibly better discussed in one place.

@pankajkumar229
Copy link

I created a (https://github.com/containerd/containerd/pull/9699/files) that essentially does not temp mount both upper and lower but only the lower. And then compares with the upper. It seems to work with the continuity changes in this pull request. Is this the correct approach? It is a pretty small change, just newline changes make it look large.

Since AUFS/OverlayFS can persist changeset in diff directory,
DiffDirChanges function can retrieve layer changeset from diff directory
without walking the whole rootfs directory.

Signed-off-by: Wei Fu <fuweid89@gmail.com>
@fuweid fuweid merged commit 386dc78 into containerd:main Jan 31, 2024
13 checks passed
@fuweid fuweid deleted the me-support-diff-change-walk branch January 31, 2024 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

5 participants