diff --git a/vendor/github.com/containerd/continuity/fs/diff.go b/vendor/github.com/containerd/continuity/fs/diff.go index e64f9e73d304..0204f08ab01b 100644 --- a/vendor/github.com/containerd/continuity/fs/diff.go +++ b/vendor/github.com/containerd/continuity/fs/diff.go @@ -212,7 +212,7 @@ func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *di // This block is here to ensure the change is recorded even if the // modify time, mode and size of the parent directory in the rw and ro layers are all equal. // Check https://github.com/docker/docker/pull/13590 for details. - if f.IsDir() { + if f != nil && f.IsDir() { changedDirs[path] = struct{}{} } if kind == ChangeKindAdd || kind == ChangeKindDelete { diff --git a/vendor/github.com/containerd/continuity/fs/diff_unix.go b/vendor/github.com/containerd/continuity/fs/diff_unix.go index 7913af27d903..09b4db8601be 100644 --- a/vendor/github.com/containerd/continuity/fs/diff_unix.go +++ b/vendor/github.com/containerd/continuity/fs/diff_unix.go @@ -21,20 +21,82 @@ package fs import ( "bytes" "os" + "strings" "syscall" + "github.com/containerd/containerd/mount" "github.com/containerd/continuity/sysx" "github.com/pkg/errors" ) +// deleteChangeOverlay checks if file has been deleted +// in overlay fs by checking if file is marked as char device. +func deleteChangeOverlay(diffDir, path string, f os.FileInfo) (string, error) { + if f.Mode()&os.ModeCharDevice != 0 { + return path, nil + } else { + return "", nil + } +} + +// getLowerDir returns the list of lower directories from +// the options of overlay mount, provided no upperdir +// exists ( implying readonly overaly) +func getLowerDir(vfsOptions string) ([]string) { + options := strings.Split(vfsOptions, ",") + var lowerDir []string + for _, opts := range options { + if strings.HasPrefix(opts, "lowerdir=") { + lowerDir = strings.Split(strings.Split(opts, "lowerdir=")[1], ":") + } + if strings.HasPrefix(opts, "upperdir=") { + return []string{} + } + } + return lowerDir +} + // detectDirDiff returns diff dir options if a directory could // be found in the mount info for upper which is the direct // diff with the provided lower directory func detectDirDiff(upper, lower string) *diffDirOptions { - // TODO: get mount options for upper // TODO: detect AUFS - // TODO: detect overlay - return nil + // Implemented only for overlay + mountInfoUpper, err := mount.Lookup(upper) + if err != nil { + return nil + } + mountInfoLower, err := mount.Lookup(lower) + if err != nil { + return nil + } + if mountInfoUpper.FSType != "overlay" { + return nil + } + if mountInfoLower.FSType != "overlay" { + return nil + } + upperLowerDir := getLowerDir(mountInfoUpper.VFSOptions) + lowerLowerDir := getLowerDir(mountInfoLower.VFSOptions) + if len(lowerLowerDir) != len(upperLowerDir) - 1 { + // the mount points differ by more than 1 snapshots. + // In this case resort to double diff walk between the + // mount points. + return nil + } + for i, dir := range lowerLowerDir { + if upperLowerDir[i+1] != dir { + // the lower dirs are not in order. So compare with + // double diff walk. + return nil + } + } + + var options diffDirOptions + options.diffDir = upperLowerDir[0] + options.deleteChange = deleteChangeOverlay + + return &options } // compareSysStat returns whether the stats are equivalent,