Browse code

Windows: Support ApplyDiff on a base layer

This adds support to the Windows graph driver for ApplyDiff on a base
layer. It also adds support for hard links, which are needed because the
Windows base layers double in size without hard link support.

Signed-off-by: John Starks <jostarks@microsoft.com>

John Starks authored on 2016/03/30 01:53:00
Showing 1 changed files
... ...
@@ -26,6 +26,7 @@ import (
26 26
 	"github.com/docker/docker/pkg/chrootarchive"
27 27
 	"github.com/docker/docker/pkg/idtools"
28 28
 	"github.com/docker/docker/pkg/ioutils"
29
+	"github.com/docker/docker/pkg/longpath"
29 30
 	"github.com/vbatts/tar-split/tar/storage"
30 31
 )
31 32
 
... ...
@@ -319,10 +320,10 @@ func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
319 319
 		}
320 320
 		name = filepath.ToSlash(name)
321 321
 		if fileInfo == nil {
322
-			changes = append(changes, archive.Change{name, archive.ChangeDelete})
322
+			changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeDelete})
323 323
 		} else {
324 324
 			// Currently there is no way to tell between an add and a modify.
325
-			changes = append(changes, archive.Change{name, archive.ChangeModify})
325
+			changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeModify})
326 326
 		}
327 327
 	}
328 328
 	return changes, nil
... ...
@@ -332,45 +333,49 @@ func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
332 332
 // layer with the specified id and parent, returning the size of the
333 333
 // new layer in bytes.
334 334
 // The layer should not be mounted when calling this function
335
-func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error) {
336
-	rPId, err := d.resolveID(parent)
337
-	if err != nil {
338
-		return
339
-	}
340
-
335
+func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (int64, error) {
341 336
 	if d.info.Flavour == diffDriver {
342 337
 		start := time.Now().UTC()
343 338
 		logrus.Debugf("WindowsGraphDriver ApplyDiff: Start untar layer")
344 339
 		destination := d.dir(id)
345 340
 		destination = filepath.Dir(destination)
346
-		if size, err = chrootarchive.ApplyUncompressedLayer(destination, diff, nil); err != nil {
347
-			return
341
+		size, err := chrootarchive.ApplyUncompressedLayer(destination, diff, nil)
342
+		if err != nil {
343
+			return 0, err
348 344
 		}
349 345
 		logrus.Debugf("WindowsGraphDriver ApplyDiff: Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
350 346
 
351
-		return
347
+		return size, nil
352 348
 	}
353 349
 
354
-	parentChain, err := d.getLayerChain(rPId)
355
-	if err != nil {
356
-		return
357
-	}
358
-	parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
359
-	if err != nil {
360
-		return
350
+	var layerChain []string
351
+	if parent != "" {
352
+		rPId, err := d.resolveID(parent)
353
+		if err != nil {
354
+			return 0, err
355
+		}
356
+		parentChain, err := d.getLayerChain(rPId)
357
+		if err != nil {
358
+			return 0, err
359
+		}
360
+		parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
361
+		if err != nil {
362
+			return 0, err
363
+		}
364
+		layerChain = append(layerChain, parentPath)
365
+		layerChain = append(layerChain, parentChain...)
361 366
 	}
362
-	layerChain := []string{parentPath}
363
-	layerChain = append(layerChain, parentChain...)
364 367
 
365
-	if size, err = d.importLayer(id, diff, layerChain); err != nil {
366
-		return
368
+	size, err := d.importLayer(id, diff, layerChain)
369
+	if err != nil {
370
+		return 0, err
367 371
 	}
368 372
 
369 373
 	if err = d.setLayerChain(id, layerChain); err != nil {
370
-		return
374
+		return 0, err
371 375
 	}
372 376
 
373
-	return
377
+	return size, nil
374 378
 }
375 379
 
376 380
 // DiffSize calculates the changes between the specified layer
... ...
@@ -539,6 +544,12 @@ func writeLayerFromTar(r archive.Reader, w hcsshim.LayerWriter) (int64, error) {
539 539
 				return 0, err
540 540
 			}
541 541
 			hdr, err = t.Next()
542
+		} else if hdr.Typeflag == tar.TypeLink {
543
+			err = w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
544
+			if err != nil {
545
+				return 0, err
546
+			}
547
+			hdr, err = t.Next()
542 548
 		} else {
543 549
 			var (
544 550
 				name     string
... ...
@@ -575,7 +586,6 @@ func (d *Driver) importLayer(id string, layerData archive.Reader, parentLayerPat
575 575
 	if err != nil {
576 576
 		return
577 577
 	}
578
-
579 578
 	size, err = writeLayerFromTar(layerData, w)
580 579
 	if err != nil {
581 580
 		w.Close()
... ...
@@ -653,7 +663,7 @@ func (fg *fileGetCloserWithBackupPrivileges) Get(filename string) (io.ReadCloser
653 653
 	// file can be opened even if the caller does not actually have access to it according
654 654
 	// to the security descriptor.
655 655
 	err := winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error {
656
-		path := filepath.Join(fg.path, filename)
656
+		path := longpath.AddPrefix(filepath.Join(fg.path, filename))
657 657
 		p, err := syscall.UTF16FromString(path)
658 658
 		if err != nil {
659 659
 			return err