From ac821f2446628a9151587038f1d377f57985a452 Mon Sep 17 00:00:00 2001 From: unclejack Date: Sat, 19 Oct 2013 04:17:00 +0300 Subject: [PATCH 1/2] fix layer size computation: handle hard links This change makes docker compute layer size correctly. The old code isn't taking hard links into account. Layers could seem like they're up to 1-1.5x larger than they really were. --- image.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/image.go b/image.go index c600273c1a..f2d1b3e7ee 100644 --- a/image.go +++ b/image.go @@ -16,6 +16,7 @@ import ( "path/filepath" "strconv" "strings" + "syscall" "time" ) @@ -114,10 +115,22 @@ func StoreImage(img *Image, jsonData []byte, layerData archive.Archive, root str func StoreSize(img *Image, root string) error { layer := layerPath(root) + data := make(map[uint64]bool) var totalSize int64 = 0 filepath.Walk(layer, func(path string, fileInfo os.FileInfo, err error) error { - totalSize += fileInfo.Size() + size := fileInfo.Size() + if size == 0 { + return nil + } + + inode := fileInfo.Sys().(*syscall.Stat_t).Ino + if _, entryExists := data[inode]; entryExists { + return nil + } + data[inode] = false + + totalSize += size return nil }) img.Size = totalSize From 78c843c8eff64da5e12725bdb111b18e51d82606 Mon Sep 17 00:00:00 2001 From: unclejack Date: Tue, 19 Nov 2013 00:13:09 +0200 Subject: [PATCH 2/2] fix container size computation: handle hard links This change makes docker compute container size correctly. The old code isn't taking hard links into account. Containers could seem like they're up to 1-1.5x larger than they really were. --- container.go | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/container.go b/container.go index 9dac345447..0686d2f5aa 100644 --- a/container.go +++ b/container.go @@ -1559,20 +1559,46 @@ func validateID(id string) error { // GetSize, return real size, virtual size func (container *Container) GetSize() (int64, int64) { var sizeRw, sizeRootfs int64 + data := make(map[uint64]bool) filepath.Walk(container.rwPath(), func(path string, fileInfo os.FileInfo, err error) error { - if fileInfo != nil { - sizeRw += fileInfo.Size() + if fileInfo == nil { + return nil } + size := fileInfo.Size() + if size == 0 { + return nil + } + + inode := fileInfo.Sys().(*syscall.Stat_t).Ino + if _, entryExists := data[inode]; entryExists { + return nil + } + data[inode] = false + + sizeRw += size return nil }) + data = make(map[uint64]bool) _, err := os.Stat(container.RootfsPath()) if err == nil { filepath.Walk(container.RootfsPath(), func(path string, fileInfo os.FileInfo, err error) error { - if fileInfo != nil { - sizeRootfs += fileInfo.Size() + if fileInfo == nil { + return nil } + size := fileInfo.Size() + if size == 0 { + return nil + } + + inode := fileInfo.Sys().(*syscall.Stat_t).Ino + if _, entryExists := data[inode]; entryExists { + return nil + } + data[inode] = false + + sizeRootfs += size return nil }) }