diff --git a/internal/hcsoci/resources_wcow.go b/internal/hcsoci/resources_wcow.go index 211b15f300..2430edca0b 100644 --- a/internal/hcsoci/resources_wcow.go +++ b/internal/hcsoci/resources_wcow.go @@ -34,18 +34,26 @@ func allocateWindowsResources(ctx context.Context, coi *createOptionsInternal, r coi.Spec.Root = &specs.Root{} } - if coi.Spec.Root.Path == "" && (coi.HostingSystem != nil || coi.Spec.Windows.HyperV == nil) { - log.G(ctx).Debug("hcsshim::allocateWindowsResources mounting storage") - mountedLayers, closer, err := layers.MountWCOWLayers(ctx, coi.actualID, coi.HostingSystem, coi.WCOWLayers) - if err != nil { - return errors.Wrap(err, "failed to mount container storage") - } - coi.Spec.Root.Path = mountedLayers.RootFS - coi.mountedWCOWLayers = mountedLayers - // If this is the pause container in a hypervisor-isolated pod, we can skip cleanup of - // layers, as that happens automatically when the UVM is terminated. - if !isSandbox || coi.HostingSystem == nil { - r.SetLayers(closer) + if coi.HostingSystem != nil || coi.Spec.Windows.HyperV == nil { + if coi.Spec.Root.Path == "" { + log.G(ctx).Debug("hcsshim::allocateWindowsResources mounting storage") + mountedLayers, closer, err := layers.MountWCOWLayers(ctx, coi.actualID, coi.HostingSystem, coi.WCOWLayers) + if err != nil { + return errors.Wrap(err, "failed to mount container storage") + } + coi.Spec.Root.Path = mountedLayers.RootFS + coi.mountedWCOWLayers = mountedLayers + // If this is the pause container in a hypervisor-isolated pod, we can skip cleanup of + // layers, as that happens automatically when the UVM is terminated. + if !isSandbox || coi.HostingSystem == nil { + r.SetLayers(closer) + } + } else { + l, err := layers.MakeMountedWCOWLayers(ctx, coi.WCOWLayers, coi.Spec.Root.Path) + if err != nil { + return errors.Wrap(err, "failed to use pre-mounted container storage") + } + coi.mountedWCOWLayers = l } } diff --git a/internal/layers/wcow_mount.go b/internal/layers/wcow_mount.go index 3bb78c09d6..9398eec1b1 100644 --- a/internal/layers/wcow_mount.go +++ b/internal/layers/wcow_mount.go @@ -49,6 +49,44 @@ func MountWCOWLayers(ctx context.Context, containerID string, vm *uvm.UtilityVM, } } +// MakeMountedWCOWLayers creates a MountedWCOWLayers structure from wl, like +// [MountWCOWLayers], without actually mounting anything. +func MakeMountedWCOWLayers(ctx context.Context, wl WCOWLayers, mountPath string) (*MountedWCOWLayers, error) { + switch l := wl.(type) { + case *wcowWCIFSLayers: + layersWithID := []MountedWCOWLayer{} + for _, l := range l.layerPaths { + layerID, err := wclayer.LayerID(ctx, l) + if err != nil { + return nil, err + } + layersWithID = append(layersWithID, MountedWCOWLayer{ + LayerID: layerID.String(), + MountedPath: l, + }) + } + + return &MountedWCOWLayers{ + RootFS: mountPath, + MountedLayerPaths: layersWithID, + }, nil + case *wcowForkedCIMLayers, *wcowBlockCIMLayers: + layerID, err := cimlayer.LayerID(mountPath) + if err != nil { + return nil, err + } + return &MountedWCOWLayers{ + RootFS: mountPath, + MountedLayerPaths: []MountedWCOWLayer{{ + LayerID: layerID, + MountedPath: mountPath, + }}, + }, nil + default: + return nil, fmt.Errorf("invalid layer type %T", wl) + } +} + // Represents a single layer that is mounted and ready to use. Depending on the type of // layers each individual layer may or may not be mounted. However, HCS still needs paths // of individual layers and a unique ID for each layer.