From a54de1835bdf1516905e500143ff3f8522ab5e27 Mon Sep 17 00:00:00 2001 From: Archana Shinde Date: Wed, 28 Mar 2018 16:12:31 -0700 Subject: [PATCH 1/2] iothread: Add ability to configure iothreads IOthreads also known as x-data-plane allow IO to be processed in a separate thread rather than the main event loop. This produces much better IO throughput and latency. Signed-off-by: Archana Shinde --- qemu/qemu.go | 17 +++++++++++++++++ qemu/qemu_test.go | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/qemu/qemu.go b/qemu/qemu.go index 89d053fe95..0b5adb2858 100644 --- a/qemu/qemu.go +++ b/qemu/qemu.go @@ -1159,6 +1159,11 @@ type Knobs struct { Realtime bool } +// IOThread allows IO to be performed on a separate thread. +type IOThread struct { + ID string +} + // Config is the qemu configuration structure. // It allows for passing custom settings and parameters to the qemu API. type Config struct { @@ -1213,6 +1218,8 @@ type Config struct { // fds is a list of open file descriptors to be passed to the spawned qemu process fds []*os.File + IOThreads []IOThread + qemuParams []string } @@ -1481,6 +1488,15 @@ func (config *Config) appendBios() { } } +func (config *Config) appendIOThreads() { + for _, t := range config.IOThreads { + if t.ID != "" { + config.qemuParams = append(config.qemuParams, "-object") + config.qemuParams = append(config.qemuParams, fmt.Sprintf("iothread,id=%s", t.ID)) + } + } +} + // LaunchQemu can be used to launch a new qemu instance. // // The Config parameter contains a set of qemu parameters and settings. @@ -1504,6 +1520,7 @@ func LaunchQemu(config Config, logger QMPLog) (string, error) { config.appendKnobs() config.appendKernel() config.appendBios() + config.appendIOThreads() if err := config.appendCPUs(); err != nil { return "", err diff --git a/qemu/qemu_test.go b/qemu/qemu_test.go index b7e60e7271..1c63e42bdb 100644 --- a/qemu/qemu_test.go +++ b/qemu/qemu_test.go @@ -67,6 +67,10 @@ func testAppend(structure interface{}, expected string, t *testing.T) { case RTC: config.RTC = s config.appendRTC() + + case IOThread: + config.IOThreads = []IOThread{s} + config.appendIOThreads() } result := strings.Join(config.qemuParams, " ") @@ -525,3 +529,13 @@ func TestAppendRTC(t *testing.T) { testAppend(rtc, rtcString, t) } + +var ioThreadString = "-object iothread,id=iothread1" + +func TestAppendIOThread(t *testing.T) { + ioThread := IOThread{ + ID: "iothread1", + } + + testAppend(ioThread, ioThreadString, t) +} From 9130f375166febfa9ca1937d126d2c6aa155b2a1 Mon Sep 17 00:00:00 2001 From: Archana Shinde Date: Wed, 28 Mar 2018 16:15:52 -0700 Subject: [PATCH 2/2] scsi: Allow scsi controller to associate with an IO thread. This enable data-plane for scsi. All drives attached to the scsi controller will have their IO processed in a single separate IO thread instead of qemu's main event loop. Signed-off-by: Archana Shinde --- qemu/qemu.go | 6 ++++++ qemu/qemu_test.go | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/qemu/qemu.go b/qemu/qemu.go index 0b5adb2858..4b0e41795a 100644 --- a/qemu/qemu.go +++ b/qemu/qemu.go @@ -841,6 +841,9 @@ type SCSIController struct { // DisableModern prevents qemu from relying on fast MMIO. DisableModern bool + + // IOThread is the IO thread on which IO will be handled + IOThread string } // Valid returns true if the SCSIController structure is valid and complete. @@ -867,6 +870,9 @@ func (scsiCon SCSIController) QemuParams(config *Config) []string { if scsiCon.DisableModern { devParams = append(devParams, fmt.Sprintf("disable-modern=true")) } + if scsiCon.IOThread != "" { + devParams = append(devParams, fmt.Sprintf("iothread=%s", scsiCon.IOThread)) + } qemuParams = append(qemuParams, "-device") qemuParams = append(qemuParams, strings.Join(devParams, ",")) diff --git a/qemu/qemu_test.go b/qemu/qemu_test.go index 1c63e42bdb..0506f4240f 100644 --- a/qemu/qemu_test.go +++ b/qemu/qemu_test.go @@ -350,7 +350,7 @@ func TestVSOCKValid(t *testing.T) { } var deviceSCSIControllerStr = "-device virtio-scsi-pci,id=foo" -var deviceSCSIControllerBusAddrStr = "-device virtio-scsi-pci,id=foo,bus=pci.0,addr=00:04.0,disable-modern=true" +var deviceSCSIControllerBusAddrStr = "-device virtio-scsi-pci,id=foo,bus=pci.0,addr=00:04.0,disable-modern=true,iothread=iothread1" func TestAppendDeviceSCSIController(t *testing.T) { scsiCon := SCSIController{ @@ -361,6 +361,7 @@ func TestAppendDeviceSCSIController(t *testing.T) { scsiCon.Bus = "pci.0" scsiCon.Addr = "00:04.0" scsiCon.DisableModern = true + scsiCon.IOThread = "iothread1" testAppend(scsiCon, deviceSCSIControllerBusAddrStr, t) }