mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-19 07:14:22 +01:00
Merge pull request #4798 from amshinde/use-iouring-qemu
Use iouring for qemu block devices
This commit is contained in:
@@ -253,6 +253,7 @@ ifneq (,$(QEMUCMD))
|
|||||||
|
|
||||||
# qemu-specific options (all should be suffixed by "_QEMU")
|
# qemu-specific options (all should be suffixed by "_QEMU")
|
||||||
DEFBLOCKSTORAGEDRIVER_QEMU := virtio-scsi
|
DEFBLOCKSTORAGEDRIVER_QEMU := virtio-scsi
|
||||||
|
DEFBLOCKDEVICEAIO_QEMU := io_uring
|
||||||
DEFNETWORKMODEL_QEMU := tcfilter
|
DEFNETWORKMODEL_QEMU := tcfilter
|
||||||
KERNELTYPE = uncompressed
|
KERNELTYPE = uncompressed
|
||||||
KERNELNAME = $(call MAKE_KERNEL_NAME,$(KERNELTYPE))
|
KERNELNAME = $(call MAKE_KERNEL_NAME,$(KERNELTYPE))
|
||||||
@@ -458,6 +459,7 @@ USER_VARS += DEFDISABLEBLOCK
|
|||||||
USER_VARS += DEFBLOCKSTORAGEDRIVER_ACRN
|
USER_VARS += DEFBLOCKSTORAGEDRIVER_ACRN
|
||||||
USER_VARS += DEFBLOCKSTORAGEDRIVER_FC
|
USER_VARS += DEFBLOCKSTORAGEDRIVER_FC
|
||||||
USER_VARS += DEFBLOCKSTORAGEDRIVER_QEMU
|
USER_VARS += DEFBLOCKSTORAGEDRIVER_QEMU
|
||||||
|
USER_VARS += DEFBLOCKDEVICEAIO_QEMU
|
||||||
USER_VARS += DEFSHAREDFS_CLH_VIRTIOFS
|
USER_VARS += DEFSHAREDFS_CLH_VIRTIOFS
|
||||||
USER_VARS += DEFSHAREDFS_QEMU_VIRTIOFS
|
USER_VARS += DEFSHAREDFS_QEMU_VIRTIOFS
|
||||||
USER_VARS += DEFVIRTIOFSDAEMON
|
USER_VARS += DEFVIRTIOFSDAEMON
|
||||||
|
|||||||
@@ -208,6 +208,20 @@ virtio_fs_cache = "@DEFVIRTIOFSCACHE@"
|
|||||||
# or nvdimm.
|
# or nvdimm.
|
||||||
block_device_driver = "@DEFBLOCKSTORAGEDRIVER_QEMU@"
|
block_device_driver = "@DEFBLOCKSTORAGEDRIVER_QEMU@"
|
||||||
|
|
||||||
|
# aio is the I/O mechanism used by qemu
|
||||||
|
# Options:
|
||||||
|
#
|
||||||
|
# - threads
|
||||||
|
# Pthread based disk I/O.
|
||||||
|
#
|
||||||
|
# - native
|
||||||
|
# Native Linux I/O.
|
||||||
|
#
|
||||||
|
# - io_uring
|
||||||
|
# Linux io_uring API. This provides the fastest I/O operations on Linux, requires kernel>5.1 and
|
||||||
|
# qemu >=5.0.
|
||||||
|
block_device_aio = "@DEFBLOCKDEVICEAIO_QEMU@"
|
||||||
|
|
||||||
# Specifies cache-related options will be set to block devices or not.
|
# Specifies cache-related options will be set to block devices or not.
|
||||||
# Default false
|
# Default false
|
||||||
#block_device_cache_set = true
|
#block_device_cache_set = true
|
||||||
|
|||||||
@@ -61,6 +61,17 @@ const (
|
|||||||
Nvdimm = "nvdimm"
|
Nvdimm = "nvdimm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AIOThreads is the pthread asynchronous I/O implementation.
|
||||||
|
AIOThreads = "threads"
|
||||||
|
|
||||||
|
// AIONative is the native Linux AIO implementation
|
||||||
|
AIONative = "native"
|
||||||
|
|
||||||
|
// AIOUring is the Linux io_uring I/O implementation
|
||||||
|
AIOIOUring = "io_uring"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Virtio9P means use virtio-9p for the shared file system
|
// Virtio9P means use virtio-9p for the shared file system
|
||||||
Virtio9P = "virtio-9p"
|
Virtio9P = "virtio-9p"
|
||||||
|
|||||||
@@ -1140,8 +1140,11 @@ const (
|
|||||||
// Threads is the pthread asynchronous I/O implementation.
|
// Threads is the pthread asynchronous I/O implementation.
|
||||||
Threads BlockDeviceAIO = "threads"
|
Threads BlockDeviceAIO = "threads"
|
||||||
|
|
||||||
// Native is the pthread asynchronous I/O implementation.
|
// Native is the native Linux AIO implementation.
|
||||||
Native BlockDeviceAIO = "native"
|
Native BlockDeviceAIO = "native"
|
||||||
|
|
||||||
|
// IOUring is the Linux io_uring I/O implementation.
|
||||||
|
IOUring BlockDeviceAIO = "io_uring"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -771,30 +771,28 @@ func (q *QMP) ExecuteQuit(ctx context.Context) error {
|
|||||||
return q.executeCommand(ctx, "quit", nil, nil)
|
return q.executeCommand(ctx, "quit", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *QMP) blockdevAddBaseArgs(driver, device, blockdevID string, ro bool) (map[string]interface{}, map[string]interface{}) {
|
func (q *QMP) blockdevAddBaseArgs(driver string, blockDevice *BlockDevice) map[string]interface{} {
|
||||||
var args map[string]interface{}
|
|
||||||
|
|
||||||
blockdevArgs := map[string]interface{}{
|
blockdevArgs := map[string]interface{}{
|
||||||
"driver": "raw",
|
"driver": "raw",
|
||||||
"read-only": ro,
|
"read-only": blockDevice.ReadOnly,
|
||||||
"file": map[string]interface{}{
|
"file": map[string]interface{}{
|
||||||
"driver": driver,
|
"driver": driver,
|
||||||
"filename": device,
|
"filename": blockDevice.File,
|
||||||
|
"aio": string(blockDevice.AIO),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
blockdevArgs["node-name"] = blockdevID
|
blockdevArgs["node-name"] = blockDevice.ID
|
||||||
args = blockdevArgs
|
|
||||||
|
|
||||||
return args, blockdevArgs
|
return blockdevArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteBlockdevAdd sends a blockdev-add to the QEMU instance. device is the
|
// ExecuteBlockdevAdd sends a blockdev-add to the QEMU instance. device is the
|
||||||
// path of the device to add, e.g., /dev/rdb0, and blockdevID is an identifier
|
// path of the device to add, e.g., /dev/rdb0, and blockdevID is an identifier
|
||||||
// used to name the device. As this identifier will be passed directly to QMP,
|
// used to name the device. As this identifier will be passed directly to QMP,
|
||||||
// it must obey QMP's naming rules, e,g., it must start with a letter.
|
// it must obey QMP's naming rules, e,g., it must start with a letter.
|
||||||
func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, device, blockdevID string, ro bool) error {
|
func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, blockDevice *BlockDevice) error {
|
||||||
args, _ := q.blockdevAddBaseArgs("host_device", device, blockdevID, ro)
|
args := q.blockdevAddBaseArgs("host_device", blockDevice)
|
||||||
|
|
||||||
return q.executeCommand(ctx, "blockdev-add", args, nil)
|
return q.executeCommand(ctx, "blockdev-add", args, nil)
|
||||||
}
|
}
|
||||||
@@ -806,29 +804,29 @@ func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, device, blockdevID string,
|
|||||||
// direct denotes whether use of O_DIRECT (bypass the host page cache)
|
// direct denotes whether use of O_DIRECT (bypass the host page cache)
|
||||||
// is enabled. noFlush denotes whether flush requests for the device are
|
// is enabled. noFlush denotes whether flush requests for the device are
|
||||||
// ignored.
|
// ignored.
|
||||||
func (q *QMP) ExecuteBlockdevAddWithCache(ctx context.Context, device, blockdevID string, direct, noFlush, ro bool) error {
|
func (q *QMP) ExecuteBlockdevAddWithCache(ctx context.Context, blockDevice *BlockDevice, direct, noFlush bool) error {
|
||||||
args, blockdevArgs := q.blockdevAddBaseArgs("host_device", device, blockdevID, ro)
|
blockdevArgs := q.blockdevAddBaseArgs("host_device", blockDevice)
|
||||||
|
|
||||||
blockdevArgs["cache"] = map[string]interface{}{
|
blockdevArgs["cache"] = map[string]interface{}{
|
||||||
"direct": direct,
|
"direct": direct,
|
||||||
"no-flush": noFlush,
|
"no-flush": noFlush,
|
||||||
}
|
}
|
||||||
|
|
||||||
return q.executeCommand(ctx, "blockdev-add", args, nil)
|
return q.executeCommand(ctx, "blockdev-add", blockdevArgs, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteBlockdevAddWithDriverCache has three one parameter driver
|
// ExecuteBlockdevAddWithDriverCache has three one parameter driver
|
||||||
// than ExecuteBlockdevAddWithCache.
|
// than ExecuteBlockdevAddWithCache.
|
||||||
// Parameter driver can set the driver of block device.
|
// Parameter driver can set the driver of block device.
|
||||||
func (q *QMP) ExecuteBlockdevAddWithDriverCache(ctx context.Context, driver, device, blockdevID string, direct, noFlush, ro bool) error {
|
func (q *QMP) ExecuteBlockdevAddWithDriverCache(ctx context.Context, driver string, blockDevice *BlockDevice, direct, noFlush bool) error {
|
||||||
args, blockdevArgs := q.blockdevAddBaseArgs(driver, device, blockdevID, ro)
|
blockdevArgs := q.blockdevAddBaseArgs(driver, blockDevice)
|
||||||
|
|
||||||
blockdevArgs["cache"] = map[string]interface{}{
|
blockdevArgs["cache"] = map[string]interface{}{
|
||||||
"direct": direct,
|
"direct": direct,
|
||||||
"no-flush": noFlush,
|
"no-flush": noFlush,
|
||||||
}
|
}
|
||||||
|
|
||||||
return q.executeCommand(ctx, "blockdev-add", args, nil)
|
return q.executeCommand(ctx, "blockdev-add", blockdevArgs, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteDeviceAdd adds the guest portion of a device to a QEMU instance
|
// ExecuteDeviceAdd adds the guest portion of a device to a QEMU instance
|
||||||
|
|||||||
@@ -400,8 +400,13 @@ func TestQMPBlockdevAdd(t *testing.T) {
|
|||||||
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||||
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||||
q.version = checkVersion(t, connectedCh)
|
q.version = checkVersion(t, connectedCh)
|
||||||
err := q.ExecuteBlockdevAdd(context.Background(), "/dev/rbd0",
|
dev := BlockDevice{
|
||||||
fmt.Sprintf("drive_%s", volumeUUID), false)
|
ID: fmt.Sprintf("drive_%s", volumeUUID),
|
||||||
|
File: "/dev/rbd0",
|
||||||
|
ReadOnly: false,
|
||||||
|
AIO: Native,
|
||||||
|
}
|
||||||
|
err := q.ExecuteBlockdevAdd(context.Background(), &dev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error %v", err)
|
t.Fatalf("Unexpected error %v", err)
|
||||||
}
|
}
|
||||||
@@ -424,8 +429,13 @@ func TestQMPBlockdevAddWithCache(t *testing.T) {
|
|||||||
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||||
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||||
q.version = checkVersion(t, connectedCh)
|
q.version = checkVersion(t, connectedCh)
|
||||||
err := q.ExecuteBlockdevAddWithCache(context.Background(), "/dev/rbd0",
|
dev := BlockDevice{
|
||||||
fmt.Sprintf("drive_%s", volumeUUID), true, true, false)
|
ID: fmt.Sprintf("drive_%s", volumeUUID),
|
||||||
|
File: "/dev/rbd0",
|
||||||
|
ReadOnly: false,
|
||||||
|
AIO: Native,
|
||||||
|
}
|
||||||
|
err := q.ExecuteBlockdevAddWithCache(context.Background(), &dev, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error %v", err)
|
t.Fatalf("Unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ type RuntimeConfigOptions struct {
|
|||||||
ShimPath string
|
ShimPath string
|
||||||
LogPath string
|
LogPath string
|
||||||
BlockDeviceDriver string
|
BlockDeviceDriver string
|
||||||
|
BlockDeviceAIO string
|
||||||
SharedFS string
|
SharedFS string
|
||||||
VirtioFSDaemon string
|
VirtioFSDaemon string
|
||||||
JaegerEndpoint string
|
JaegerEndpoint string
|
||||||
@@ -305,6 +306,7 @@ func MakeRuntimeConfigFileData(config RuntimeConfigOptions) string {
|
|||||||
path = "` + config.HypervisorPath + `"
|
path = "` + config.HypervisorPath + `"
|
||||||
kernel = "` + config.KernelPath + `"
|
kernel = "` + config.KernelPath + `"
|
||||||
block_device_driver = "` + config.BlockDeviceDriver + `"
|
block_device_driver = "` + config.BlockDeviceDriver + `"
|
||||||
|
block_device_aio = "` + config.BlockDeviceAIO + `"
|
||||||
kernel_params = "` + config.KernelParams + `"
|
kernel_params = "` + config.KernelParams + `"
|
||||||
image = "` + config.ImagePath + `"
|
image = "` + config.ImagePath + `"
|
||||||
machine_type = "` + config.MachineType + `"
|
machine_type = "` + config.MachineType + `"
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ const defaultBridgesCount uint32 = 1
|
|||||||
const defaultInterNetworkingModel = "tcfilter"
|
const defaultInterNetworkingModel = "tcfilter"
|
||||||
const defaultDisableBlockDeviceUse bool = false
|
const defaultDisableBlockDeviceUse bool = false
|
||||||
const defaultBlockDeviceDriver = "virtio-scsi"
|
const defaultBlockDeviceDriver = "virtio-scsi"
|
||||||
|
const defaultBlockDeviceAIO string = "io_uring"
|
||||||
const defaultBlockDeviceCacheSet bool = false
|
const defaultBlockDeviceCacheSet bool = false
|
||||||
const defaultBlockDeviceCacheDirect bool = false
|
const defaultBlockDeviceCacheDirect bool = false
|
||||||
const defaultBlockDeviceCacheNoflush bool = false
|
const defaultBlockDeviceCacheNoflush bool = false
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ type hypervisor struct {
|
|||||||
GuestHookPath string `toml:"guest_hook_path"`
|
GuestHookPath string `toml:"guest_hook_path"`
|
||||||
GuestMemoryDumpPath string `toml:"guest_memory_dump_path"`
|
GuestMemoryDumpPath string `toml:"guest_memory_dump_path"`
|
||||||
SeccompSandbox string `toml:"seccompsandbox"`
|
SeccompSandbox string `toml:"seccompsandbox"`
|
||||||
|
BlockDeviceAIO string `toml:"block_device_aio"`
|
||||||
HypervisorPathList []string `toml:"valid_hypervisor_paths"`
|
HypervisorPathList []string `toml:"valid_hypervisor_paths"`
|
||||||
JailerPathList []string `toml:"valid_jailer_paths"`
|
JailerPathList []string `toml:"valid_jailer_paths"`
|
||||||
CtlPathList []string `toml:"valid_ctlpaths"`
|
CtlPathList []string `toml:"valid_ctlpaths"`
|
||||||
@@ -469,6 +470,22 @@ func (h hypervisor) blockDeviceDriver() (string, error) {
|
|||||||
return "", fmt.Errorf("Invalid hypervisor block storage driver %v specified (supported drivers: %v)", h.BlockDeviceDriver, supportedBlockDrivers)
|
return "", fmt.Errorf("Invalid hypervisor block storage driver %v specified (supported drivers: %v)", h.BlockDeviceDriver, supportedBlockDrivers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h hypervisor) blockDeviceAIO() (string, error) {
|
||||||
|
supportedBlockAIO := []string{config.AIOIOUring, config.AIONative, config.AIOThreads}
|
||||||
|
|
||||||
|
if h.BlockDeviceAIO == "" {
|
||||||
|
return defaultBlockDeviceAIO, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, b := range supportedBlockAIO {
|
||||||
|
if b == h.BlockDeviceAIO {
|
||||||
|
return h.BlockDeviceAIO, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Invalid hypervisor block storage I/O mechanism %v specified (supported AIO: %v)", h.BlockDeviceAIO, supportedBlockAIO)
|
||||||
|
}
|
||||||
|
|
||||||
func (h hypervisor) sharedFS() (string, error) {
|
func (h hypervisor) sharedFS() (string, error) {
|
||||||
supportedSharedFS := []string{config.Virtio9P, config.VirtioFS, config.VirtioFSNydus}
|
supportedSharedFS := []string{config.Virtio9P, config.VirtioFS, config.VirtioFSNydus}
|
||||||
|
|
||||||
@@ -728,6 +745,11 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
|||||||
return vc.HypervisorConfig{}, err
|
return vc.HypervisorConfig{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blockAIO, err := h.blockDeviceAIO()
|
||||||
|
if err != nil {
|
||||||
|
return vc.HypervisorConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
sharedFS, err := h.sharedFS()
|
sharedFS, err := h.sharedFS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return vc.HypervisorConfig{}, err
|
return vc.HypervisorConfig{}, err
|
||||||
@@ -784,6 +806,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
|||||||
Debug: h.Debug,
|
Debug: h.Debug,
|
||||||
DisableNestingChecks: h.DisableNestingChecks,
|
DisableNestingChecks: h.DisableNestingChecks,
|
||||||
BlockDeviceDriver: blockDriver,
|
BlockDeviceDriver: blockDriver,
|
||||||
|
BlockDeviceAIO: blockAIO,
|
||||||
BlockDeviceCacheSet: h.BlockDeviceCacheSet,
|
BlockDeviceCacheSet: h.BlockDeviceCacheSet,
|
||||||
BlockDeviceCacheDirect: h.BlockDeviceCacheDirect,
|
BlockDeviceCacheDirect: h.BlockDeviceCacheDirect,
|
||||||
BlockDeviceCacheNoflush: h.BlockDeviceCacheNoflush,
|
BlockDeviceCacheNoflush: h.BlockDeviceCacheNoflush,
|
||||||
@@ -1182,6 +1205,7 @@ func GetDefaultHypervisorConfig() vc.HypervisorConfig {
|
|||||||
Debug: defaultEnableDebug,
|
Debug: defaultEnableDebug,
|
||||||
DisableNestingChecks: defaultDisableNestingChecks,
|
DisableNestingChecks: defaultDisableNestingChecks,
|
||||||
BlockDeviceDriver: defaultBlockDeviceDriver,
|
BlockDeviceDriver: defaultBlockDeviceDriver,
|
||||||
|
BlockDeviceAIO: defaultBlockDeviceAIO,
|
||||||
BlockDeviceCacheSet: defaultBlockDeviceCacheSet,
|
BlockDeviceCacheSet: defaultBlockDeviceCacheSet,
|
||||||
BlockDeviceCacheDirect: defaultBlockDeviceCacheDirect,
|
BlockDeviceCacheDirect: defaultBlockDeviceCacheDirect,
|
||||||
BlockDeviceCacheNoflush: defaultBlockDeviceCacheNoflush,
|
BlockDeviceCacheNoflush: defaultBlockDeviceCacheNoflush,
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
|||||||
machineType := "machineType"
|
machineType := "machineType"
|
||||||
disableBlockDevice := true
|
disableBlockDevice := true
|
||||||
blockDeviceDriver := "virtio-scsi"
|
blockDeviceDriver := "virtio-scsi"
|
||||||
|
blockDeviceAIO := "io_uring"
|
||||||
enableIOThreads := true
|
enableIOThreads := true
|
||||||
hotplugVFIOOnRootBus := true
|
hotplugVFIOOnRootBus := true
|
||||||
pcieRootPort := uint32(2)
|
pcieRootPort := uint32(2)
|
||||||
@@ -99,6 +100,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
|||||||
DefaultGuestHookPath: defaultGuestHookPath,
|
DefaultGuestHookPath: defaultGuestHookPath,
|
||||||
DisableBlock: disableBlockDevice,
|
DisableBlock: disableBlockDevice,
|
||||||
BlockDeviceDriver: blockDeviceDriver,
|
BlockDeviceDriver: blockDeviceDriver,
|
||||||
|
BlockDeviceAIO: blockDeviceAIO,
|
||||||
EnableIOThreads: enableIOThreads,
|
EnableIOThreads: enableIOThreads,
|
||||||
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
|
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
|
||||||
PCIeRootPort: pcieRootPort,
|
PCIeRootPort: pcieRootPort,
|
||||||
@@ -159,6 +161,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
|||||||
DefaultMaxMemorySize: maxMemory,
|
DefaultMaxMemorySize: maxMemory,
|
||||||
DisableBlockDeviceUse: disableBlockDevice,
|
DisableBlockDeviceUse: disableBlockDevice,
|
||||||
BlockDeviceDriver: defaultBlockDeviceDriver,
|
BlockDeviceDriver: defaultBlockDeviceDriver,
|
||||||
|
BlockDeviceAIO: defaultBlockDeviceAIO,
|
||||||
DefaultBridges: defaultBridgesCount,
|
DefaultBridges: defaultBridgesCount,
|
||||||
EnableIOThreads: enableIOThreads,
|
EnableIOThreads: enableIOThreads,
|
||||||
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
|
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
|
||||||
@@ -550,6 +553,7 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
|||||||
GuestHookPath: defaultGuestHookPath,
|
GuestHookPath: defaultGuestHookPath,
|
||||||
VhostUserStorePath: defaultVhostUserStorePath,
|
VhostUserStorePath: defaultVhostUserStorePath,
|
||||||
VirtioFSCache: defaultVirtioFSCacheMode,
|
VirtioFSCache: defaultVirtioFSCacheMode,
|
||||||
|
BlockDeviceAIO: defaultBlockDeviceAIO,
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedAgentConfig := vc.KataAgentConfig{
|
expectedAgentConfig := vc.KataAgentConfig{
|
||||||
@@ -593,6 +597,7 @@ func TestNewQemuHypervisorConfig(t *testing.T) {
|
|||||||
hotplugVFIOOnRootBus := true
|
hotplugVFIOOnRootBus := true
|
||||||
pcieRootPort := uint32(2)
|
pcieRootPort := uint32(2)
|
||||||
orgVHostVSockDevicePath := utils.VHostVSockDevicePath
|
orgVHostVSockDevicePath := utils.VHostVSockDevicePath
|
||||||
|
blockDeviceAIO := "io_uring"
|
||||||
defer func() {
|
defer func() {
|
||||||
utils.VHostVSockDevicePath = orgVHostVSockDevicePath
|
utils.VHostVSockDevicePath = orgVHostVSockDevicePath
|
||||||
}()
|
}()
|
||||||
@@ -614,6 +619,7 @@ func TestNewQemuHypervisorConfig(t *testing.T) {
|
|||||||
TxRateLimiterMaxRate: txRateLimiterMaxRate,
|
TxRateLimiterMaxRate: txRateLimiterMaxRate,
|
||||||
SharedFS: "virtio-fs",
|
SharedFS: "virtio-fs",
|
||||||
VirtioFSDaemon: filepath.Join(dir, "virtiofsd"),
|
VirtioFSDaemon: filepath.Join(dir, "virtiofsd"),
|
||||||
|
BlockDeviceAIO: blockDeviceAIO,
|
||||||
}
|
}
|
||||||
|
|
||||||
files := []string{hypervisorPath, kernelPath, imagePath}
|
files := []string{hypervisorPath, kernelPath, imagePath}
|
||||||
@@ -674,6 +680,11 @@ func TestNewQemuHypervisorConfig(t *testing.T) {
|
|||||||
if config.TxRateLimiterMaxRate != txRateLimiterMaxRate {
|
if config.TxRateLimiterMaxRate != txRateLimiterMaxRate {
|
||||||
t.Errorf("Expected value for tx rate limiter %v, got %v", txRateLimiterMaxRate, config.TxRateLimiterMaxRate)
|
t.Errorf("Expected value for tx rate limiter %v, got %v", txRateLimiterMaxRate, config.TxRateLimiterMaxRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.BlockDeviceAIO != blockDeviceAIO {
|
||||||
|
t.Errorf("Expected value for BlockDeviceAIO %v, got %v", blockDeviceAIO, config.BlockDeviceAIO)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewFirecrackerHypervisorConfig(t *testing.T) {
|
func TestNewFirecrackerHypervisorConfig(t *testing.T) {
|
||||||
|
|||||||
@@ -683,6 +683,22 @@ func addHypervisorBlockOverrides(ocispec specs.Spec, sbConfig *vc.SandboxConfig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if value, ok := ocispec.Annotations[vcAnnotations.BlockDeviceAIO]; ok {
|
||||||
|
supportedAIO := []string{config.AIONative, config.AIOThreads, config.AIOIOUring}
|
||||||
|
|
||||||
|
valid := false
|
||||||
|
for _, b := range supportedAIO {
|
||||||
|
if b == value {
|
||||||
|
sbConfig.HypervisorConfig.BlockDeviceAIO = value
|
||||||
|
valid = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
return fmt.Errorf("Invalid AIO mechanism %v specified in annotation (supported IO mechanism : %v)", value, supportedAIO)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := newAnnotationConfiguration(ocispec, vcAnnotations.DisableBlockDeviceUse).setBool(func(disableBlockDeviceUse bool) {
|
if err := newAnnotationConfiguration(ocispec, vcAnnotations.DisableBlockDeviceUse).setBool(func(disableBlockDeviceUse bool) {
|
||||||
sbConfig.HypervisorConfig.DisableBlockDeviceUse = disableBlockDeviceUse
|
sbConfig.HypervisorConfig.DisableBlockDeviceUse = disableBlockDeviceUse
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|||||||
@@ -642,6 +642,7 @@ func TestAddHypervisorAnnotations(t *testing.T) {
|
|||||||
ocispec.Annotations[vcAnnotations.HugePages] = "true"
|
ocispec.Annotations[vcAnnotations.HugePages] = "true"
|
||||||
ocispec.Annotations[vcAnnotations.IOMMU] = "true"
|
ocispec.Annotations[vcAnnotations.IOMMU] = "true"
|
||||||
ocispec.Annotations[vcAnnotations.BlockDeviceDriver] = "virtio-scsi"
|
ocispec.Annotations[vcAnnotations.BlockDeviceDriver] = "virtio-scsi"
|
||||||
|
ocispec.Annotations[vcAnnotations.BlockDeviceAIO] = "io_uring"
|
||||||
ocispec.Annotations[vcAnnotations.DisableBlockDeviceUse] = "true"
|
ocispec.Annotations[vcAnnotations.DisableBlockDeviceUse] = "true"
|
||||||
ocispec.Annotations[vcAnnotations.EnableIOThreads] = "true"
|
ocispec.Annotations[vcAnnotations.EnableIOThreads] = "true"
|
||||||
ocispec.Annotations[vcAnnotations.BlockDeviceCacheSet] = "true"
|
ocispec.Annotations[vcAnnotations.BlockDeviceCacheSet] = "true"
|
||||||
@@ -679,6 +680,7 @@ func TestAddHypervisorAnnotations(t *testing.T) {
|
|||||||
assert.Equal(config.HypervisorConfig.HugePages, true)
|
assert.Equal(config.HypervisorConfig.HugePages, true)
|
||||||
assert.Equal(config.HypervisorConfig.IOMMU, true)
|
assert.Equal(config.HypervisorConfig.IOMMU, true)
|
||||||
assert.Equal(config.HypervisorConfig.BlockDeviceDriver, "virtio-scsi")
|
assert.Equal(config.HypervisorConfig.BlockDeviceDriver, "virtio-scsi")
|
||||||
|
assert.Equal(config.HypervisorConfig.BlockDeviceAIO, "io_uring")
|
||||||
assert.Equal(config.HypervisorConfig.DisableBlockDeviceUse, true)
|
assert.Equal(config.HypervisorConfig.DisableBlockDeviceUse, true)
|
||||||
assert.Equal(config.HypervisorConfig.EnableIOThreads, true)
|
assert.Equal(config.HypervisorConfig.EnableIOThreads, true)
|
||||||
assert.Equal(config.HypervisorConfig.BlockDeviceCacheSet, true)
|
assert.Equal(config.HypervisorConfig.BlockDeviceCacheSet, true)
|
||||||
|
|||||||
@@ -377,6 +377,9 @@ type HypervisorConfig struct {
|
|||||||
// SeccompSandbox is the qemu function which enables the seccomp feature
|
// SeccompSandbox is the qemu function which enables the seccomp feature
|
||||||
SeccompSandbox string
|
SeccompSandbox string
|
||||||
|
|
||||||
|
// BlockiDeviceAIO specifies the I/O API to be used.
|
||||||
|
BlockDeviceAIO string
|
||||||
|
|
||||||
// KernelParams are additional guest kernel parameters.
|
// KernelParams are additional guest kernel parameters.
|
||||||
KernelParams []Param
|
KernelParams []Param
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,9 @@ const (
|
|||||||
// BlockDeviceDriver specifies the driver to be used for block device either VirtioSCSI or VirtioBlock
|
// BlockDeviceDriver specifies the driver to be used for block device either VirtioSCSI or VirtioBlock
|
||||||
BlockDeviceDriver = kataAnnotHypervisorPrefix + "block_device_driver"
|
BlockDeviceDriver = kataAnnotHypervisorPrefix + "block_device_driver"
|
||||||
|
|
||||||
|
// BlockDeviceAIO specifies I/O mechanism to be used with VirtioBlock for qemu
|
||||||
|
BlockDeviceAIO = kataAnnotHypervisorPrefix + "block_device_aio"
|
||||||
|
|
||||||
// DisableBlockDeviceUse is a sandbox annotation that disallows a block device from being used.
|
// DisableBlockDeviceUse is a sandbox annotation that disallows a block device from being used.
|
||||||
DisableBlockDeviceUse = kataAnnotHypervisorPrefix + "disable_block_device_use"
|
DisableBlockDeviceUse = kataAnnotHypervisorPrefix + "disable_block_device_use"
|
||||||
|
|
||||||
|
|||||||
@@ -1292,12 +1292,19 @@ func (q *qemu) hotplugAddBlockDevice(ctx context.Context, drive *config.BlockDri
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qblkDevice := govmmQemu.BlockDevice{
|
||||||
|
ID: drive.ID,
|
||||||
|
File: drive.File,
|
||||||
|
ReadOnly: drive.ReadOnly,
|
||||||
|
AIO: govmmQemu.BlockDeviceAIO(q.config.BlockDeviceAIO),
|
||||||
|
}
|
||||||
|
|
||||||
if drive.Swap {
|
if drive.Swap {
|
||||||
err = q.qmpMonitorCh.qmp.ExecuteBlockdevAddWithDriverCache(q.qmpMonitorCh.ctx, "file", drive.File, drive.ID, false, false, false)
|
err = q.qmpMonitorCh.qmp.ExecuteBlockdevAddWithDriverCache(q.qmpMonitorCh.ctx, "file", &qblkDevice, false, false)
|
||||||
} else if q.config.BlockDeviceCacheSet {
|
} else if q.config.BlockDeviceCacheSet {
|
||||||
err = q.qmpMonitorCh.qmp.ExecuteBlockdevAddWithCache(q.qmpMonitorCh.ctx, drive.File, drive.ID, q.config.BlockDeviceCacheDirect, q.config.BlockDeviceCacheNoflush, drive.ReadOnly)
|
err = q.qmpMonitorCh.qmp.ExecuteBlockdevAddWithCache(q.qmpMonitorCh.ctx, &qblkDevice, q.config.BlockDeviceCacheDirect, q.config.BlockDeviceCacheNoflush)
|
||||||
} else {
|
} else {
|
||||||
err = q.qmpMonitorCh.qmp.ExecuteBlockdevAdd(q.qmpMonitorCh.ctx, drive.File, drive.ID, drive.ReadOnly)
|
err = q.qmpMonitorCh.qmp.ExecuteBlockdevAdd(q.qmpMonitorCh.ctx, &qblkDevice)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user