fs: add DiffDirChanges function to get changeset fast#145
fs: add DiffDirChanges function to get changeset fast#145fuweid merged 1 commit intocontainerd:mainfrom
Conversation
|
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 |
ade3c4b to
3214e3b
Compare
ktock
left a comment
There was a problem hiding this comment.
@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
| case DiffSourceAUFS: | ||
| o = &diffDirOptions{ | ||
| skipChange: skipAUFSMetadata, | ||
| } |
There was a problem hiding this comment.
AUFS snapshotter is deprecated since containerd v1.5. Could we focus on overlayfs in this PR?
yeah. will update it in days~ Thanks! |
|
Why was this never merged? |
|
I think this can be just merged after rebasing and removing AUFS codes |
|
oops. Will update it later. Thanks for remider |
3214e3b to
b9af6a9
Compare
| // 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") |
There was a problem hiding this comment.
Nit: should we use errdefs.ErrNotImplemented?
There was a problem hiding this comment.
Good catch. Let me handle it in the follow-up. (Use containerd/errdefs repo to handle this).
fs/diff_test.go
Outdated
| } | ||
|
|
||
| func testDiffDirChange(base, diff fstest.Applier, source DiffSource, expected []TestChange) error { | ||
| baseTmp, err := ioutil.TempDir("", "fast-diff-base-") |
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] } | ||
|
|
There was a problem hiding this comment.
Can we just use sort.Slice?
fs/diff.go
Outdated
|
|
||
| if f.IsDir() { | ||
| originalPath := filepath.Join(diffDir, path) | ||
| opaque, err := sysx.LGetxattr(originalPath, "trusted.overlay.opaque") |
There was a problem hiding this comment.
user.overlay.* has to be checked too
torvalds/linux@2d2f2d7
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
errors.Is is more preferable over directly using the = operator
b9af6a9 to
349dea6
Compare
7e2b2a4 to
f700d27
Compare
bcc5706 to
2545354
Compare
|
Many Thanks for the quick turnaround. |
2545354 to
19f4218
Compare
| deletedFile := false | ||
|
|
||
| if o.deleteChange != nil { | ||
| deletedFile, err = o.deleteChange(diffDir, path, f, changeFn) |
There was a problem hiding this comment.
nilt: We don't need to mark this file as "deleted" if this file doesn't exist in the base dir.
There was a problem hiding this comment.
good catch. Let me think how to handle this
fs/diff_linux.go
Outdated
| // 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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Good catch. Sorry for late reply. Let me think about how to remove FIXME
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Updated. Please take a look.
There was a problem hiding this comment.
For deleted file, 3rd one is nil. FYI
|
Is it possible to get this change to a previous version of containerd when it gets released? |
Unlikely, due to potential risk of regression. |
|
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. |
6a68270 to
d3a8156
Compare
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 <[email protected]>
d3a8156 to
8b312bd
Compare
Unlike the walking differ, which implements a generic method to accommodate all kinds of snapshotters, the EROFS differ is just implemented for EROFS and EROFS snapshotter so it can utilize the recent DiffDirChanges() [1] to avoid traversing the entire rootfs directory in order to improve `nerdctl commit` performance. Additionally, I think `baseDir` is unnecessary too (in principle, only `upperdir` is useful for OCI format convention). However, addressing this requires more work, so left as is for now. It's also useful to implement a customized Compare() method for EROFS differ so that we can dump the native EROFS-formatted blob to the content store later. [1] containerd/continuity#145 Signed-off-by: Gao Xiang <[email protected]>
Unlike the walking differ, which implements a generic method to accommodate all kinds of snapshotters, the EROFS differ is just implemented for EROFS and EROFS snapshotter so it can utilize the recent DiffDirChanges() [1] to avoid traversing the entire rootfs directory in order to improve `nerdctl commit` performance. Additionally, I think `baseDir` is unnecessary too (in principle, only `upperdir` is useful for OCI format convention). However, addressing this requires more work, so left as is for now. It's also useful to implement a customized Compare() method for EROFS differ so that we can dump the native EROFS-formatted blob to the content store later. [1] containerd/continuity#145 Signed-off-by: Gao Xiang <[email protected]>
Unlike the walking differ, which implements a generic method to accommodate all kinds of snapshotters, the EROFS differ is just implemented for EROFS and EROFS snapshotter so it can utilize the recent DiffDirChanges() [1] to avoid traversing the entire rootfs directory in order to improve `nerdctl commit` performance. Additionally, I think `baseDir` is unnecessary too (in principle, only `upperdir` is useful for OCI format convention). However, addressing this requires more work, so left as is for now. It's also useful to implement a customized Compare() method for EROFS differ so that we can dump the native EROFS-formatted blob to the content store later. [1] containerd/continuity#145 Signed-off-by: Gao Xiang <[email protected]>

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 [email protected]