Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: Pass KataVirtualVolume to the guest as devices in go runtime #8494

Merged
merged 4 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/runtime/pkg/katautils/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func CreateSandbox(ctx context.Context, vci vc.VC, ociSpec specs.Spec, runtimeCo
}

if !rootFs.Mounted && len(sandboxConfig.Containers) == 1 {
if rootFs.Source != "" {
if rootFs.Source != "" && !vc.HasOptionPrefix(rootFs.Options, vc.VirtualVolumePrefix) {
realPath, err := ResolvePath(rootFs.Source)
if err != nil {
return nil, vc.Process{}, err
Expand Down
94 changes: 60 additions & 34 deletions src/runtime/virtcontainers/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -662,41 +662,9 @@ func (c *Container) createBlockDevices(ctx context.Context) error {
}
}

var stat unix.Stat_t
if err := unix.Stat(c.mounts[i].Source, &stat); err != nil {
return fmt.Errorf("stat %q failed: %v", c.mounts[i].Source, err)
}

var di *config.DeviceInfo
var err error

// Check if mount is a block device file. If it is, the block device will be attached to the host
// instead of passing this as a shared mount.
if stat.Mode&unix.S_IFMT == unix.S_IFBLK {
di = &config.DeviceInfo{
HostPath: c.mounts[i].Source,
ContainerPath: c.mounts[i].Destination,
DevType: "b",
Major: int64(unix.Major(uint64(stat.Rdev))),
Minor: int64(unix.Minor(uint64(stat.Rdev))),
ReadOnly: c.mounts[i].ReadOnly,
}
} else if isBlockFile && stat.Mode&unix.S_IFMT == unix.S_IFREG {
di = &config.DeviceInfo{
HostPath: c.mounts[i].Source,
ContainerPath: c.mounts[i].Destination,
DevType: "b",
Major: -1,
Minor: 0,
ReadOnly: c.mounts[i].ReadOnly,
}
// Check whether source can be used as a pmem device
} else if di, err = config.PmemDeviceInfo(c.mounts[i].Source, c.mounts[i].Destination); err != nil {
c.Logger().WithError(err).
WithField("mount-source", c.mounts[i].Source).
Debug("no loop device")
}

di, err := c.createDeviceInfo(c.mounts[i].Source, c.mounts[i].Destination, c.mounts[i].ReadOnly, isBlockFile)
if err == nil && di != nil {
b, err := c.sandbox.devManager.NewDevice(*di)
if err != nil {
Expand Down Expand Up @@ -795,6 +763,58 @@ func newContainer(ctx context.Context, sandbox *Sandbox, contConfig *ContainerCo
return c, nil
}

// Create Device Information about the block device
func (c *Container) createDeviceInfo(source, destination string, readonly, isBlockFile bool) (*config.DeviceInfo, error) {
var stat unix.Stat_t
if err := unix.Stat(source, &stat); err != nil {
return nil, fmt.Errorf("stat %q failed: %v", source, err)
}

var di *config.DeviceInfo
var err error

if stat.Mode&unix.S_IFMT == unix.S_IFBLK {
di = &config.DeviceInfo{
HostPath: source,
ContainerPath: destination,
DevType: "b",
Major: int64(unix.Major(uint64(stat.Rdev))),
Minor: int64(unix.Minor(uint64(stat.Rdev))),
ReadOnly: readonly,
}
} else if isBlockFile && stat.Mode&unix.S_IFMT == unix.S_IFREG {
di = &config.DeviceInfo{
HostPath: source,
ContainerPath: destination,
DevType: "b",
Major: -1,
Minor: 0,
ReadOnly: readonly,
}
// Check whether source can be used as a pmem device
} else if di, err = config.PmemDeviceInfo(source, destination); err != nil {
c.Logger().WithError(err).
WithField("mount-source", source).
Debug("no loop device")
}
return di, err
}

// call hypervisor to create device about KataVirtualVolume.
func (c *Container) createVirtualVolumeDevices() ([]config.DeviceInfo, error) {
var deviceInfos []config.DeviceInfo
for _, o := range c.rootFs.Options {
if strings.HasPrefix(o, VirtualVolumePrefix) {
virtVolume, err := types.ParseKataVirtualVolume(strings.TrimPrefix(o, VirtualVolumePrefix))
if err != nil {
return nil, err
}
c.Logger().Infof("KataVirtualVolume volumetype = %s", virtVolume.VolumeType)
}
}
return deviceInfos, nil
}

func (c *Container) createMounts(ctx context.Context) error {
// Create block devices for newly created container
return c.createBlockDevices(ctx)
Expand All @@ -804,7 +824,13 @@ func (c *Container) createDevices(contConfig *ContainerConfig) error {
// If devices were not found in storage, create Device implementations
// from the configuration. This should happen at create.
var storedDevices []ContainerDevice
for _, info := range contConfig.DeviceInfos {
virtualVolumesDeviceInfos, err := c.createVirtualVolumeDevices()
if err != nil {
return err
}
deviceInfos := append(virtualVolumesDeviceInfos, contConfig.DeviceInfos...)

for _, info := range deviceInfos {
dev, err := c.sandbox.devManager.NewDevice(info)
if err != nil {
return err
Expand Down
5 changes: 3 additions & 2 deletions src/runtime/virtcontainers/fs_share.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ var fsShareTracingTags = map[string]string{
// SharedFile represents the outcome of a host filesystem sharing
// operation.
type SharedFile struct {
storage *grpc.Storage
guestPath string
containerStorages []*grpc.Storage
volumeStorages []*grpc.Storage
guestPath string
}

type FilesystemSharer interface {
Expand Down
65 changes: 57 additions & 8 deletions src/runtime/virtcontainers/fs_share_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"os"
"path/filepath"
"regexp"
"strings"
"sync"
"syscall"

Expand All @@ -26,6 +27,7 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils/katatrace"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols/grpc"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
)

Expand Down Expand Up @@ -455,13 +457,60 @@ func (f *FilesystemShare) shareRootFilesystemWithNydus(ctx context.Context, c *C
f.Logger().Infof("Nydus rootfs info: %#v\n", rootfs)

return &SharedFile{
storage: rootfs,
guestPath: rootfsGuestPath,
containerStorages: []*grpc.Storage{rootfs},
guestPath: rootfsGuestPath,
}, nil
}

// handleVirtualVolume processes all `io.katacontainers.volume=` messages in rootFs.Options,
// creating storage, and then aggregates all storages into an array.
func handleVirtualVolume(c *Container) ([]*grpc.Storage, string, error) {
var volumes []*grpc.Storage
var volumeType string

for _, o := range c.rootFs.Options {
if strings.HasPrefix(o, VirtualVolumePrefix) {
virtVolume, err := types.ParseKataVirtualVolume(strings.TrimPrefix(o, VirtualVolumePrefix))
if err != nil {
return nil, "", err
}

volumeType = virtVolume.VolumeType
var vol *grpc.Storage
vol, err = handleVirtualVolumeStorageObject(c, "", virtVolume)
if err != nil {
return nil, "", err
}

if vol != nil {
volumes = append(volumes, vol)
}
}
}

return volumes, volumeType, nil
}

func (f *FilesystemShare) shareRootFilesystemWithVirtualVolume(ctx context.Context, c *Container) (*SharedFile, error) {
guestPath := filepath.Join("/run/kata-containers/", c.id, c.rootfsSuffix)
rootFsStorages, _, err := handleVirtualVolume(c)
if err != nil {
return nil, err
}

return &SharedFile{
containerStorages: rootFsStorages,
guestPath: guestPath,
}, nil
}

// func (c *Container) shareRootfs(ctx context.Context) (*grpc.Storage, string, error) {
func (f *FilesystemShare) ShareRootFilesystem(ctx context.Context, c *Container) (*SharedFile, error) {

if HasOptionPrefix(c.rootFs.Options, VirtualVolumePrefix) {
return f.shareRootFilesystemWithVirtualVolume(ctx, c)
}

if c.rootFs.Type == NydusRootFSType {
return f.shareRootFilesystemWithNydus(ctx, c)
}
Expand All @@ -470,13 +519,13 @@ func (f *FilesystemShare) ShareRootFilesystem(ctx context.Context, c *Container)
if HasOptionPrefix(c.rootFs.Options, annotations.FileSystemLayer) {
path := filepath.Join("/run/kata-containers", c.id, "rootfs")
return &SharedFile{
storage: &grpc.Storage{
containerStorages: []*grpc.Storage{{
MountPoint: path,
Source: "none",
Fstype: c.rootFs.Type,
Driver: kataOverlayDevType,
Options: c.rootFs.Options,
},
}},
guestPath: path,
}, nil
}
Expand Down Expand Up @@ -541,8 +590,8 @@ func (f *FilesystemShare) ShareRootFilesystem(ctx context.Context, c *Container)
}

return &SharedFile{
storage: rootfsStorage,
guestPath: rootfsGuestPath,
containerStorages: []*grpc.Storage{rootfsStorage},
guestPath: rootfsGuestPath,
}, nil
}

Expand All @@ -556,8 +605,8 @@ func (f *FilesystemShare) ShareRootFilesystem(ctx context.Context, c *Container)
}

return &SharedFile{
storage: nil,
guestPath: rootfsGuestPath,
containerStorages: nil,
guestPath: rootfsGuestPath,
}, nil
}

Expand Down