summaryrefslogtreecommitdiff
path: root/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go')
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go115
1 files changed, 115 insertions, 0 deletions
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
index 651676fb2..b3b431e35 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
@@ -1,7 +1,13 @@
package wclayer
import (
+ "os"
+ "path/filepath"
+ "syscall"
+ "unsafe"
+
"github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/Microsoft/hcsshim/osversion"
"github.com/sirupsen/logrus"
)
@@ -26,5 +32,114 @@ func ExpandScratchSize(path string, size uint64) (err error) {
if err != nil {
return hcserror.New(err, title+" - failed", "")
}
+
+ // Manually expand the volume now in order to work around bugs in 19H1 and
+ // prerelease versions of Vb. Remove once this is fixed in Windows.
+ if build := osversion.Get().Build; build >= osversion.V19H1 && build < 19020 {
+ err = expandSandboxVolume(path)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type virtualStorageType struct {
+ DeviceID uint32
+ VendorID [16]byte
+}
+
+type openVersion2 struct {
+ GetInfoOnly int32 // bool but 4-byte aligned
+ ReadOnly int32 // bool but 4-byte aligned
+ ResiliencyGUID [16]byte // GUID
+}
+
+type openVirtualDiskParameters struct {
+ Version uint32 // Must always be set to 2
+ Version2 openVersion2
+}
+
+func attachVhd(path string) (syscall.Handle, error) {
+ var (
+ defaultType virtualStorageType
+ handle syscall.Handle
+ )
+ parameters := openVirtualDiskParameters{Version: 2}
+ err := openVirtualDisk(
+ &defaultType,
+ path,
+ 0,
+ 0,
+ &parameters,
+ &handle)
+ if err != nil {
+ return 0, &os.PathError{Op: "OpenVirtualDisk", Path: path, Err: err}
+ }
+ err = attachVirtualDisk(handle, 0, 0, 0, 0, 0)
+ if err != nil {
+ syscall.Close(handle)
+ return 0, &os.PathError{Op: "AttachVirtualDisk", Path: path, Err: err}
+ }
+ return handle, nil
+}
+
+func expandSandboxVolume(path string) error {
+ // Mount the sandbox VHD temporarily.
+ vhdPath := filepath.Join(path, "sandbox.vhdx")
+ vhd, err := attachVhd(vhdPath)
+ if err != nil {
+ return &os.PathError{Op: "OpenVirtualDisk", Path: vhdPath, Err: err}
+ }
+ defer syscall.Close(vhd)
+
+ // Open the volume.
+ volumePath, err := GetLayerMountPath(path)
+ if err != nil {
+ return err
+ }
+ if volumePath[len(volumePath)-1] == '\\' {
+ volumePath = volumePath[:len(volumePath)-1]
+ }
+ volume, err := os.OpenFile(volumePath, os.O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+ defer volume.Close()
+
+ // Get the volume's underlying partition size in NTFS clusters.
+ var (
+ partitionSize int64
+ bytes uint32
+ )
+ const _IOCTL_DISK_GET_LENGTH_INFO = 0x0007405C
+ err = syscall.DeviceIoControl(syscall.Handle(volume.Fd()), _IOCTL_DISK_GET_LENGTH_INFO, nil, 0, (*byte)(unsafe.Pointer(&partitionSize)), 8, &bytes, nil)
+ if err != nil {
+ return &os.PathError{Op: "IOCTL_DISK_GET_LENGTH_INFO", Path: volume.Name(), Err: err}
+ }
+ const (
+ clusterSize = 4096
+ sectorSize = 512
+ )
+ targetClusters := partitionSize / clusterSize
+
+ // Get the volume's current size in NTFS clusters.
+ var volumeSize int64
+ err = getDiskFreeSpaceEx(volume.Name()+"\\", nil, &volumeSize, nil)
+ if err != nil {
+ return &os.PathError{Op: "GetDiskFreeSpaceEx", Path: volume.Name(), Err: err}
+ }
+ volumeClusters := volumeSize / clusterSize
+
+ // Only resize the volume if there is space to grow, otherwise this will
+ // fail with invalid parameter. NTFS reserves one cluster.
+ if volumeClusters+1 < targetClusters {
+ targetSectors := targetClusters * (clusterSize / sectorSize)
+ const _FSCTL_EXTEND_VOLUME = 0x000900F0
+ err = syscall.DeviceIoControl(syscall.Handle(volume.Fd()), _FSCTL_EXTEND_VOLUME, (*byte)(unsafe.Pointer(&targetSectors)), 8, nil, 0, &bytes, nil)
+ if err != nil {
+ return &os.PathError{Op: "FSCTL_EXTEND_VOLUME", Path: volume.Name(), Err: err}
+ }
+ }
return nil
}