1
2
3 package wclayer
4
5 import (
6 "context"
7 "os"
8 "path/filepath"
9 "syscall"
10 "unsafe"
11
12 "github.com/Microsoft/hcsshim/internal/hcserror"
13 "github.com/Microsoft/hcsshim/internal/oc"
14 "github.com/Microsoft/hcsshim/osversion"
15 "go.opencensus.io/trace"
16 )
17
18
19 func ExpandScratchSize(ctx context.Context, path string, size uint64) (err error) {
20 title := "hcsshim::ExpandScratchSize"
21 ctx, span := oc.StartSpan(ctx, title)
22 defer span.End()
23 defer func() { oc.SetSpanStatus(span, err) }()
24 span.AddAttributes(
25 trace.StringAttribute("path", path),
26 trace.Int64Attribute("size", int64(size)))
27
28 err = expandSandboxSize(&stdDriverInfo, path, size)
29 if err != nil {
30 return hcserror.New(err, title, "")
31 }
32
33
34
35 if build := osversion.Build(); build >= osversion.V19H1 && build < 19020 {
36 err = expandSandboxVolume(ctx, path)
37 if err != nil {
38 return err
39 }
40 }
41 return nil
42 }
43
44 type virtualStorageType struct {
45 DeviceID uint32
46 VendorID [16]byte
47 }
48
49 type openVersion2 struct {
50 GetInfoOnly int32
51 ReadOnly int32
52 ResiliencyGUID [16]byte
53 }
54
55 type openVirtualDiskParameters struct {
56 Version uint32
57 Version2 openVersion2
58 }
59
60 func attachVhd(path string) (syscall.Handle, error) {
61 var (
62 defaultType virtualStorageType
63 handle syscall.Handle
64 )
65 parameters := openVirtualDiskParameters{Version: 2}
66 err := openVirtualDisk(
67 &defaultType,
68 path,
69 0,
70 0,
71 ¶meters,
72 &handle)
73 if err != nil {
74 return 0, &os.PathError{Op: "OpenVirtualDisk", Path: path, Err: err}
75 }
76 err = attachVirtualDisk(handle, 0, 0, 0, 0, 0)
77 if err != nil {
78 syscall.Close(handle)
79 return 0, &os.PathError{Op: "AttachVirtualDisk", Path: path, Err: err}
80 }
81 return handle, nil
82 }
83
84 func expandSandboxVolume(ctx context.Context, path string) error {
85
86 vhdPath := filepath.Join(path, "sandbox.vhdx")
87 vhd, err := attachVhd(vhdPath)
88 if err != nil {
89 return &os.PathError{Op: "OpenVirtualDisk", Path: vhdPath, Err: err}
90 }
91 defer syscall.Close(vhd)
92
93
94 volumePath, err := GetLayerMountPath(ctx, path)
95 if err != nil {
96 return err
97 }
98 if volumePath[len(volumePath)-1] == '\\' {
99 volumePath = volumePath[:len(volumePath)-1]
100 }
101 volume, err := os.OpenFile(volumePath, os.O_RDWR, 0)
102 if err != nil {
103 return err
104 }
105 defer volume.Close()
106
107
108 var (
109 partitionSize int64
110 bytes uint32
111 )
112 const _IOCTL_DISK_GET_LENGTH_INFO = 0x0007405C
113 err = syscall.DeviceIoControl(syscall.Handle(volume.Fd()), _IOCTL_DISK_GET_LENGTH_INFO, nil, 0, (*byte)(unsafe.Pointer(&partitionSize)), 8, &bytes, nil)
114 if err != nil {
115 return &os.PathError{Op: "IOCTL_DISK_GET_LENGTH_INFO", Path: volume.Name(), Err: err}
116 }
117 const (
118 clusterSize = 4096
119 sectorSize = 512
120 )
121 targetClusters := partitionSize / clusterSize
122
123
124 var volumeSize int64
125 err = getDiskFreeSpaceEx(volume.Name()+"\\", nil, &volumeSize, nil)
126 if err != nil {
127 return &os.PathError{Op: "GetDiskFreeSpaceEx", Path: volume.Name(), Err: err}
128 }
129 volumeClusters := volumeSize / clusterSize
130
131
132
133 if volumeClusters+1 < targetClusters {
134 targetSectors := targetClusters * (clusterSize / sectorSize)
135 const _FSCTL_EXTEND_VOLUME = 0x000900F0
136 err = syscall.DeviceIoControl(syscall.Handle(volume.Fd()), _FSCTL_EXTEND_VOLUME, (*byte)(unsafe.Pointer(&targetSectors)), 8, nil, 0, &bytes, nil)
137 if err != nil {
138 return &os.PathError{Op: "FSCTL_EXTEND_VOLUME", Path: volume.Name(), Err: err}
139 }
140 }
141 return nil
142 }
143
View as plain text