Browse code

Revendor hcsshim to fix image import bug

This change brings in a single new commit from Microsoft/hcsshim. The
commit fixes an issue when unpacking a Windows container layer which
could result in incorrect directory timestamps.

This manifested most significantly in an impact to startup times of
some Windows container images (such as anything based on servercore).

Signed-off-by: Kevin Parsons <kevpar@microsoft.com>

Kevin Parsons authored on 2020/06/10 13:49:06
Showing 4 changed files
... ...
@@ -1,5 +1,5 @@
1 1
 github.com/Azure/go-ansiterm                        d6e3b3328b783f23731bc4d058875b0371ff8109
2
-github.com/Microsoft/hcsshim                        5bc557dd210ff2caf615e6e22d398123de77fc11 # v0.8.9
2
+github.com/Microsoft/hcsshim                        9dcb42f100215f8d375b4a9265e5bba009217a85 # moby branch
3 3
 github.com/Microsoft/go-winio                       6c72808b55902eae4c5943626030429ff20f3b63 # v0.4.14
4 4
 github.com/docker/libtrust                          9cbd2a1374f46905c68a4eb3694a130610adc62a
5 5
 github.com/golang/gddo                              72a348e765d293ed6d1ded7b699591f14d6cd921
... ...
@@ -37,7 +37,7 @@ type dirInfo struct {
37 37
 func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error {
38 38
 	for i := range dis {
39 39
 		di := &dis[len(dis)-i-1] // reverse order: process child directories first
40
-		f, err := safefile.OpenRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_OPEN, safefile.FILE_DIRECTORY_FILE)
40
+		f, err := safefile.OpenRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_OPEN, safefile.FILE_DIRECTORY_FILE|syscall.FILE_FLAG_OPEN_REPARSE_POINT)
41 41
 		if err != nil {
42 42
 			return err
43 43
 		}
... ...
@@ -47,6 +47,7 @@ func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error {
47 47
 		if err != nil {
48 48
 			return err
49 49
 		}
50
+
50 51
 	}
51 52
 	return nil
52 53
 }
... ...
@@ -93,9 +94,7 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e
93 93
 	extraFlags := uint32(0)
94 94
 	if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
95 95
 		extraFlags |= safefile.FILE_DIRECTORY_FILE
96
-		if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
97
-			w.dirInfo = append(w.dirInfo, dirInfo{name, *fileInfo})
98
-		}
96
+		w.dirInfo = append(w.dirInfo, dirInfo{name, *fileInfo})
99 97
 	}
100 98
 
101 99
 	mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY)
... ...
@@ -93,6 +93,19 @@ func (r *legacyLayerWriterWrapper) Close() (err error) {
93 93
 			return err
94 94
 		}
95 95
 	}
96
+
97
+	// The reapplyDirectoryTimes must be called AFTER we are done with Tombstone
98
+	// deletion and hard link creation. This is because Tombstone deletion and hard link
99
+	// creation updates the directory last write timestamps so that will change the
100
+	// timestamps added by the `Add` call. Some container applications depend on the
101
+	// correctness of these timestamps and so we should change the timestamps back to
102
+	// the original value (i.e the value provided in the Add call) after this
103
+	// processing is done.
104
+	err = reapplyDirectoryTimes(r.destRoot, r.changedDi)
105
+	if err != nil {
106
+		return err
107
+	}
108
+
96 109
 	// Prepare the utility VM for use if one is present in the layer.
97 110
 	if r.HasUtilityVM {
98 111
 		err := safefile.EnsureNotReparsePointRelative("UtilityVM", r.destRoot)
... ...
@@ -341,7 +341,7 @@ type legacyLayerWriter struct {
341 341
 	backupWriter    *winio.BackupFileWriter
342 342
 	Tombstones      []string
343 343
 	HasUtilityVM    bool
344
-	uvmDi           []dirInfo
344
+	changedDi       []dirInfo
345 345
 	addedFiles      map[string]bool
346 346
 	PendingLinks    []pendingLink
347 347
 	pendingDirs     []pendingDir
... ...
@@ -555,7 +555,7 @@ func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles
555 555
 			if err != nil {
556 556
 				return err
557 557
 			}
558
-			if isDir && !isReparsePoint {
558
+			if isDir {
559 559
 				di = append(di, dirInfo{path: relPath, fileInfo: *fi})
560 560
 			}
561 561
 		} else {
... ...
@@ -583,6 +583,10 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
583 583
 		return w.initUtilityVM()
584 584
 	}
585 585
 
586
+	if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
587
+		w.changedDi = append(w.changedDi, dirInfo{path: name, fileInfo: *fileInfo})
588
+	}
589
+
586 590
 	name = filepath.Clean(name)
587 591
 	if hasPathPrefix(name, utilityVMPath) {
588 592
 		if !w.HasUtilityVM {
... ...
@@ -612,9 +616,6 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
612 612
 					return err
613 613
 				}
614 614
 			}
615
-			if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
616
-				w.uvmDi = append(w.uvmDi, dirInfo{path: name, fileInfo: *fileInfo})
617
-			}
618 615
 		} else {
619 616
 			// Overwrite any existing hard link.
620 617
 			err := safefile.RemoveRelative(name, w.destRoot)
... ...
@@ -805,11 +806,5 @@ func (w *legacyLayerWriter) Close() error {
805 805
 			return err
806 806
 		}
807 807
 	}
808
-	if w.HasUtilityVM {
809
-		err := reapplyDirectoryTimes(w.destRoot, w.uvmDi)
810
-		if err != nil {
811
-			return err
812
-		}
813
-	}
814 808
 	return nil
815 809
 }