fix(host): cpu hotplug compatible with high qemu version (#24759)

This commit is contained in:
wanyaoqi
2026-05-03 23:22:13 +08:00
committed by GitHub
parent fe665d986c
commit c36093b1e4
4 changed files with 95 additions and 22 deletions

View File

@@ -2606,6 +2606,7 @@ type SGuestHotplugCpuMemTask struct {
addedCpuCount int
addedVcpuIds []int
cpuNumaPin []*desc.SCpuNumaPin
cpuList []monitor.HotpluggableCPU
addedMemSize int
memSlotNewIndex *int
@@ -2643,6 +2644,12 @@ func NewGuestHotplugCpuMemTask(
// First at all add cpu count, second add mem size
func (task *SGuestHotplugCpuMemTask) Start() {
if task.addCpuCount > 0 {
res, err := task.getHotpluggableCPUList()
if err != nil {
task.onFail(err.Error())
return
}
task.cpuList = res
task.startAddCpu()
} else if task.addMemSize > 0 {
task.startAddMem()
@@ -2682,16 +2689,12 @@ func (task *SGuestHotplugCpuMemTask) buildVcpusMap() {
}
func (task *SGuestHotplugCpuMemTask) startAddCpusWithFreeVcpuSet(vcpuSet []int) {
if task.addedCpuCount >= task.addCpuCount {
task.startAddMem()
return
}
vcpuId := vcpuSet[0]
cb := func(reason string) {
if len(reason) > 0 {
log.Errorln(reason)
task.onFail(reason)
for i := range vcpuSet {
vcpuId := vcpuSet[i]
err := task.AddCpu(task.cpuList, vcpuSet[i])
if err != nil {
log.Errorf("failed add cpu %d: %s", vcpuSet[i], err)
task.onFail(err.Error())
return
}
@@ -2726,9 +2729,9 @@ func (task *SGuestHotplugCpuMemTask) startAddCpusWithFreeVcpuSet(vcpuSet []int)
}
task.addedCpuCount += 1
task.startAddCpusWithFreeVcpuSet(vcpuSet[1:])
}
task.Monitor.AddCpu(vcpuId, cb)
task.startAddMem()
}
func (task *SGuestHotplugCpuMemTask) onGetCpuCount(count int) {
@@ -2738,7 +2741,12 @@ func (task *SGuestHotplugCpuMemTask) onGetCpuCount(count int) {
func (task *SGuestHotplugCpuMemTask) doAddCpu() {
if task.addedCpuCount < task.addCpuCount {
task.Monitor.AddCpu(task.originalCpuCount+task.addedCpuCount, task.onAddCpu)
err := task.AddCpu(task.cpuList, task.originalCpuCount+task.addedCpuCount)
ret := ""
if err != nil {
ret = err.Error()
}
task.onAddCpu(ret)
} else {
task.startAddMem()
}

View File

@@ -3061,8 +3061,57 @@ func (s *SKVMGuestInstance) doBlockIoThrottle() {
}
}
func (s *SKVMGuestInstance) startHotPlugVcpus(vcpuSet []int) error {
func (s *SKVMGuestInstance) AddCpu(cpuList []monitor.HotpluggableCPU, cpu int) error {
var c = make(chan error)
cb := func(res string) {
var e error = nil
if len(res) > 0 {
e = errors.Errorf("failed add cpu %d: %s", cpu, res)
}
c <- e
}
if version.GT(s.QemuVersion, "4.0.2") {
var found = false
for i := range cpuList {
if cpuList[i].Props.SocketID == nil || cpuList[i].Props.CoreID == nil {
continue
}
if cpuList[i].QomPath != nil {
// cpu present
continue
}
cpusPerSocket := int(s.Desc.CpuDesc.MaxCpus / s.Desc.CpuDesc.Sockets)
coreId := int(*cpuList[i].Props.CoreID) + cpusPerSocket*int(*cpuList[i].Props.SocketID)
if coreId == cpu {
found = true
params := map[string]interface{}{
"id": fmt.Sprintf("cpu-%d", cpu),
"core-id": cpu % cpusPerSocket,
"socket-id": *cpuList[i].Props.SocketID,
}
if cpuList[i].Props.ThreadID != nil {
params["thread-id"] = *cpuList[i].Props.ThreadID
}
s.Monitor.DeviceAddCpu(cpuList[i].Type, params, cb)
break
}
}
if !found {
return errors.Errorf("hot pluggable cpu %d not found", cpu)
}
} else {
s.Monitor.AddCpu(cpu, cb)
}
err, _ := <-c
return err
}
func (s *SKVMGuestInstance) startHotPlugVcpus(vcpuSet []int) error {
cpuList, err := s.getHotpluggableCPUList()
if err != nil {
return errors.Wrap(err, "getHotpluggableCPUList")
}
for i := range vcpuSet {
if vcpuSet[i] == 0 {
@@ -3070,14 +3119,8 @@ func (s *SKVMGuestInstance) startHotPlugVcpus(vcpuSet []int) error {
continue
}
s.Monitor.AddCpu(vcpuSet[i], func(res string) {
var e error = nil
if len(res) > 0 {
e = errors.Errorf("failed add cpu %d: %s", vcpuSet[i], res)
}
c <- e
})
if err, _ := <-c; err != nil {
err = s.AddCpu(cpuList, vcpuSet[i])
if err != nil {
return err
}
}

View File

@@ -220,6 +220,7 @@ type Monitor interface {
ObjectAdd(objectType string, params map[string]string, callback StringCallback)
DriveAdd(bus, node string, params map[string]string, callback StringCallback)
DeviceAdd(dev string, params map[string]string, callback StringCallback)
DeviceAddCpu(dev string, params map[string]interface{}, callback StringCallback)
XBlockdevChange(parent, node, child string, callback StringCallback)
BlockStream(drive string, callback StringCallback)

View File

@@ -553,6 +553,27 @@ func (m *QmpMonitor) DeviceAdd(dev string, params map[string]string, callback St
m.Query(cmd, cb)
}
func (m *QmpMonitor) DeviceAddCpu(dev string, params map[string]interface{}, callback StringCallback) {
args := map[string]interface{}{
"driver": dev,
}
for k, v := range params {
args[k] = v
}
cmd := &Command{
Execute: "device_add",
Args: args,
}
cb := func(res *Response) {
callback(m.actionResult(res))
}
m.Query(cmd, cb)
}
func (m *QmpMonitor) MigrateSetDowntime(dtSec float64, callback StringCallback) {
m.HumanMonitorCommand(fmt.Sprintf("migrate_set_downtime %f", dtSec), callback)
}