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>
This commit is contained in:
John Starks 2016-03-29 09:53:00 -07:00
parent 9b486999f2
commit cf7944bf6f
1 changed files with 36 additions and 26 deletions

View File

@ -26,6 +26,7 @@ import (
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/longpath"
"github.com/vbatts/tar-split/tar/storage"
)
@ -319,10 +320,10 @@ func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
}
name = filepath.ToSlash(name)
if fileInfo == nil {
changes = append(changes, archive.Change{name, archive.ChangeDelete})
changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeDelete})
} else {
// Currently there is no way to tell between an add and a modify.
changes = append(changes, archive.Change{name, archive.ChangeModify})
changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeModify})
}
}
return changes, nil
@ -332,45 +333,49 @@ func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
// layer with the specified id and parent, returning the size of the
// new layer in bytes.
// The layer should not be mounted when calling this function
func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error) {
rPId, err := d.resolveID(parent)
if err != nil {
return
}
func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (int64, error) {
if d.info.Flavour == diffDriver {
start := time.Now().UTC()
logrus.Debugf("WindowsGraphDriver ApplyDiff: Start untar layer")
destination := d.dir(id)
destination = filepath.Dir(destination)
if size, err = chrootarchive.ApplyUncompressedLayer(destination, diff, nil); err != nil {
return
size, err := chrootarchive.ApplyUncompressedLayer(destination, diff, nil)
if err != nil {
return 0, err
}
logrus.Debugf("WindowsGraphDriver ApplyDiff: Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
return
return size, nil
}
parentChain, err := d.getLayerChain(rPId)
if err != nil {
return
var layerChain []string
if parent != "" {
rPId, err := d.resolveID(parent)
if err != nil {
return 0, err
}
parentChain, err := d.getLayerChain(rPId)
if err != nil {
return 0, err
}
parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
if err != nil {
return 0, err
}
layerChain = append(layerChain, parentPath)
layerChain = append(layerChain, parentChain...)
}
parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
if err != nil {
return
}
layerChain := []string{parentPath}
layerChain = append(layerChain, parentChain...)
if size, err = d.importLayer(id, diff, layerChain); err != nil {
return
size, err := d.importLayer(id, diff, layerChain)
if err != nil {
return 0, err
}
if err = d.setLayerChain(id, layerChain); err != nil {
return
return 0, err
}
return
return size, nil
}
// DiffSize calculates the changes between the specified layer
@ -539,6 +544,12 @@ func writeLayerFromTar(r archive.Reader, w hcsshim.LayerWriter) (int64, error) {
return 0, err
}
hdr, err = t.Next()
} else if hdr.Typeflag == tar.TypeLink {
err = w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
if err != nil {
return 0, err
}
hdr, err = t.Next()
} else {
var (
name string
@ -575,7 +586,6 @@ func (d *Driver) importLayer(id string, layerData archive.Reader, parentLayerPat
if err != nil {
return
}
size, err = writeLayerFromTar(layerData, w)
if err != nil {
w.Close()
@ -653,7 +663,7 @@ func (fg *fileGetCloserWithBackupPrivileges) Get(filename string) (io.ReadCloser
// file can be opened even if the caller does not actually have access to it according
// to the security descriptor.
err := winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error {
path := filepath.Join(fg.path, filename)
path := longpath.AddPrefix(filepath.Join(fg.path, filename))
p, err := syscall.UTF16FromString(path)
if err != nil {
return err