Browse Source

Merge pull request #2304 from unclejack/fix_layer_size_computation

Fix layer size computation: handle hard links correctly
Michael Crosby 11 years ago
parent
commit
f7c2a00557
2 changed files with 44 additions and 5 deletions
  1. 30 4
      container.go
  2. 14 1
      image.go

+ 30 - 4
container.go

@@ -1346,20 +1346,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
 		})
 	}

+ 14 - 1
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
 	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