diff --git a/virtcontainers/hypervisor.go b/virtcontainers/hypervisor.go index cfbd885fae..b5d0d3d8ce 100644 --- a/virtcontainers/hypervisor.go +++ b/virtcontainers/hypervisor.go @@ -201,6 +201,10 @@ type HypervisorConfig struct { // DisableBlockDeviceUse disallows a block device from being used. DisableBlockDeviceUse bool + // EnableIOThreads enables IO to be processed in a separate thread. + // Supported currently for virtio-scsi driver. + EnableIOThreads bool + // Debug changes the default hypervisor and kernel parameters to // enable debug output where available. Debug bool diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index 93bcf2136e..1eca297402 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -379,8 +379,9 @@ func (q *qemu) createPod(podConfig PodConfig) error { return err } + var ioThread *govmmQemu.IOThread if q.config.BlockDeviceDriver == VirtioSCSI { - devices = q.arch.appendSCSIController(devices) + devices, ioThread = q.arch.appendSCSIController(devices, q.config.EnableIOThreads) } cpuModel := q.arch.cpuModel() @@ -414,6 +415,10 @@ func (q *qemu) createPod(podConfig PodConfig) error { Bios: firmwarePath, } + if ioThread != nil { + qemuConfig.IOThreads = []govmmQemu.IOThread{*ioThread} + } + q.qemuConfig = qemuConfig return nil diff --git a/virtcontainers/qemu_arch_base.go b/virtcontainers/qemu_arch_base.go index c377755a45..81fcf8a8eb 100644 --- a/virtcontainers/qemu_arch_base.go +++ b/virtcontainers/qemu_arch_base.go @@ -66,7 +66,7 @@ type qemuArch interface { appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) // appendSCSIController appens a SCSI controller to devices - appendSCSIController(devices []govmmQemu.Device) []govmmQemu.Device + appendSCSIController(devices []govmmQemu.Device, enableIOThreads bool) ([]govmmQemu.Device, *govmmQemu.IOThread) // appendBridges appends bridges to devices appendBridges(devices []govmmQemu.Device, bridges []Bridge) []govmmQemu.Device @@ -300,15 +300,27 @@ func (q *qemuArchBase) appendImage(devices []govmmQemu.Device, path string) ([]g return q.appendBlockDevice(devices, drive), nil } -func (q *qemuArchBase) appendSCSIController(devices []govmmQemu.Device) []govmmQemu.Device { +func (q *qemuArchBase) appendSCSIController(devices []govmmQemu.Device, enableIOThreads bool) ([]govmmQemu.Device, *govmmQemu.IOThread) { scsiController := govmmQemu.SCSIController{ ID: scsiControllerID, DisableModern: q.nestedRun, } + var t *govmmQemu.IOThread + + if enableIOThreads { + randBytes, _ := generateRandomBytes(8) + + t = &govmmQemu.IOThread{ + ID: fmt.Sprintf("%s-%s", "iothread", hex.EncodeToString(randBytes)), + } + + scsiController.IOThread = t.ID + } + devices = append(devices, scsiController) - return devices + return devices, t } // appendBridges appends to devices the given bridges diff --git a/virtcontainers/qemu_arch_base_test.go b/virtcontainers/qemu_arch_base_test.go index a91a06a586..451e01a68c 100644 --- a/virtcontainers/qemu_arch_base_test.go +++ b/virtcontainers/qemu_arch_base_test.go @@ -470,6 +470,10 @@ func TestQemuArchBaseAppendSCSIController(t *testing.T) { }, } - devices = qemuArchBase.appendSCSIController(devices) + devices, ioThread := qemuArchBase.appendSCSIController(devices, false) assert.Equal(expectedOut, devices) + assert.Nil(ioThread) + + _, ioThread = qemuArchBase.appendSCSIController(devices, true) + assert.NotNil(ioThread) }