From 7dbb4ff11deca729da21dd27cde7a6f49e6a9e15 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Wed, 1 Jan 2025 11:12:18 -0500 Subject: [PATCH] incus: fix virtual-machines with qemu 9.2 --- pkgs/by-name/in/incus/1531.diff | 271 ++++++++++++++++++++++++++++++ pkgs/by-name/in/incus/package.nix | 5 +- 2 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 pkgs/by-name/in/incus/1531.diff diff --git a/pkgs/by-name/in/incus/1531.diff b/pkgs/by-name/in/incus/1531.diff new file mode 100644 index 000000000000..fbcdcad438f0 --- /dev/null +++ b/pkgs/by-name/in/incus/1531.diff @@ -0,0 +1,271 @@ +diff --git a/internal/server/instance/drivers/driver_qemu.go b/internal/server/instance/drivers/driver_qemu.go +index 1c773213468..fb43917ca96 100644 +--- a/internal/server/instance/drivers/driver_qemu.go ++++ b/internal/server/instance/drivers/driver_qemu.go +@@ -2393,7 +2393,7 @@ func (d *qemu) deviceAttachPath(deviceName string, configCopy map[string]string, + + d.logger.Debug("Using PCI bus device to hotplug virtiofs into", logger.Ctx{"device": deviceName, "port": pciDeviceName}) + +- qemuDev := map[string]string{ ++ qemuDev := map[string]any{ + "driver": "vhost-user-fs-pci", + "bus": pciDeviceName, + "addr": "00.0", +@@ -2535,7 +2535,7 @@ func (d *qemu) deviceAttachNIC(deviceName string, configCopy map[string]string, + return err + } + +- qemuDev := make(map[string]string) ++ qemuDev := make(map[string]any) + + // PCIe and PCI require a port device name to hotplug the NIC into. + if slices.Contains([]string{"pcie", "pci"}, qemuBus) { +@@ -2633,7 +2633,7 @@ func (d *qemu) deviceAttachPCI(deviceName string, configCopy map[string]string, + return err + } + +- qemuDev := make(map[string]string) ++ qemuDev := make(map[string]any) + escapedDeviceName := linux.PathNameEncode(devName) + + d.logger.Debug("Using PCI bus device to hotplug NIC into", logger.Ctx{"device": deviceName, "port": pciDeviceName}) +@@ -3589,7 +3589,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo + break + } + +- qemuDev := make(map[string]string) ++ qemuDev := make(map[string]any) + if slices.Contains([]string{"nvme", "virtio-blk"}, busName) { + // Allocate a PCI(e) port and write it to the config file so QMP can "hotplug" the + // drive into it later. +@@ -3600,7 +3600,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo + qemuDev["addr"] = devAddr + + if multi { +- qemuDev["multifunction"] = "on" ++ qemuDev["multifunction"] = true + } + } + +@@ -3624,7 +3624,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo + + // Add network device. + if len(runConf.NetworkInterface) > 0 { +- qemuDev := make(map[string]string) ++ qemuDev := make(map[string]any) + if slices.Contains([]string{"pcie", "pci"}, bus.name) { + // Allocate a PCI(e) port and write it to the config file so QMP can "hotplug" the + // NIC into it later. +@@ -3635,7 +3635,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo + qemuDev["addr"] = devAddr + + if multi { +- qemuDev["multifunction"] = "on" ++ qemuDev["multifunction"] = true + } + } + +@@ -3860,7 +3860,7 @@ func (d *qemu) addFileDescriptor(fdFiles *[]*os.File, file *os.File) int { + } + + // addRootDriveConfig adds the qemu config required for adding the root drive. +-func (d *qemu) addRootDriveConfig(qemuDev map[string]string, mountInfo *storagePools.MountInfo, bootIndexes map[string]int, rootDriveConf deviceConfig.MountEntryItem) (monitorHook, error) { ++func (d *qemu) addRootDriveConfig(qemuDev map[string]any, mountInfo *storagePools.MountInfo, bootIndexes map[string]int, rootDriveConf deviceConfig.MountEntryItem) (monitorHook, error) { + if rootDriveConf.TargetPath != "/" { + return nil, fmt.Errorf("Non-root drive config supplied") + } +@@ -3992,7 +3992,7 @@ func (d *qemu) addDriveDirConfig(cfg *[]cfgSection, bus *qemuBus, fdFiles *[]*os + } + + // addDriveConfig adds the qemu config required for adding a supplementary drive. +-func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string]int, driveConf deviceConfig.MountEntryItem) (monitorHook, error) { ++func (d *qemu) addDriveConfig(qemuDev map[string]any, bootIndexes map[string]int, driveConf deviceConfig.MountEntryItem) (monitorHook, error) { + aioMode := "native" // Use native kernel async IO and O_DIRECT by default. + cacheMode := "none" // Bypass host cache, use O_DIRECT semantics by default. + media := "disk" +@@ -4248,7 +4248,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string] + } + + if qemuDev == nil { +- qemuDev = map[string]string{} ++ qemuDev = map[string]any{} + } + + qemuDev["id"] = fmt.Sprintf("%s%s", qemuDeviceIDPrefix, escapedDeviceName) +@@ -4256,8 +4256,8 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string] + qemuDev["serial"] = fmt.Sprintf("%s%s", qemuBlockDevIDPrefix, escapedDeviceName) + + if bus == "virtio-scsi" { +- qemuDev["channel"] = "0" +- qemuDev["lun"] = "1" ++ qemuDev["channel"] = 0 ++ qemuDev["lun"] = 1 + qemuDev["bus"] = "qemu_scsi.0" + + if media == "disk" { +@@ -4282,7 +4282,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string] + } + + if bootIndexes != nil { +- qemuDev["bootindex"] = strconv.Itoa(bootIndexes[driveConf.DevName]) ++ qemuDev["bootindex"] = bootIndexes[driveConf.DevName] + } + + monHook := func(m *qmp.Monitor) error { +@@ -4336,7 +4336,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string] + } + + if driveConf.Limits != nil { +- err = m.SetBlockThrottle(qemuDev["id"], int(driveConf.Limits.ReadBytes), int(driveConf.Limits.WriteBytes), int(driveConf.Limits.ReadIOps), int(driveConf.Limits.WriteIOps)) ++ err = m.SetBlockThrottle(qemuDev["id"].(string), int(driveConf.Limits.ReadBytes), int(driveConf.Limits.WriteBytes), int(driveConf.Limits.ReadIOps), int(driveConf.Limits.WriteIOps)) + if err != nil { + return fmt.Errorf("Failed applying limits for disk device %q: %w", driveConf.DevName, err) + } +@@ -4351,7 +4351,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string] + + // addNetDevConfig adds the qemu config required for adding a network device. + // The qemuDev map is expected to be preconfigured with the settings for an existing port to use for the device. +-func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIndexes map[string]int, nicConfig []deviceConfig.RunConfigItem) (monitorHook, error) { ++func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]any, bootIndexes map[string]int, nicConfig []deviceConfig.RunConfigItem) (monitorHook, error) { + reverter := revert.New() + defer reverter.Fail() + +@@ -4382,7 +4382,7 @@ func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIn + if len(bootIndexes) > 0 { + bootIndex, found := bootIndexes[devName] + if found { +- qemuDev["bootindex"] = strconv.Itoa(bootIndex) ++ qemuDev["bootindex"] = bootIndex + } + } + +@@ -4400,9 +4400,9 @@ func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIn + // Number of vectors is number of vCPUs * 2 (RX/TX) + 2 (config/control MSI-X). + vectors := 2*queueCount + 2 + if vectors > 0 { +- qemuDev["mq"] = "on" ++ qemuDev["mq"] = true + if slices.Contains([]string{"pcie", "pci"}, busName) { +- qemuDev["vectors"] = strconv.Itoa(vectors) ++ qemuDev["vectors"] = vectors + } + } + +@@ -4591,9 +4591,9 @@ func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIn + } + + qemuDev["netdev"] = qemuNetDev["id"].(string) +- qemuDev["page-per-vq"] = "on" +- qemuDev["iommu_platform"] = "on" +- qemuDev["disable-legacy"] = "on" ++ qemuDev["page-per-vq"] = true ++ qemuDev["iommu_platform"] = true ++ qemuDev["disable-legacy"] = true + + err = m.AddNIC(qemuNetDev, qemuDev) + if err != nil { +@@ -4819,7 +4819,7 @@ func (d *qemu) addGPUDevConfig(cfg *[]cfgSection, bus *qemuBus, gpuConfig []devi + } + + func (d *qemu) addUSBDeviceConfig(usbDev deviceConfig.USBDeviceItem) (monitorHook, error) { +- device := map[string]string{ ++ qemuDev := map[string]any{ + "id": fmt.Sprintf("%s%s", qemuDeviceIDPrefix, usbDev.DeviceName), + "driver": "usb-host", + "bus": "qemu_usb.0", +@@ -4836,18 +4836,18 @@ func (d *qemu) addUSBDeviceConfig(usbDev deviceConfig.USBDeviceItem) (monitorHoo + + defer func() { _ = f.Close() }() + +- info, err := m.SendFileWithFDSet(device["id"], f, false) ++ info, err := m.SendFileWithFDSet(qemuDev["id"].(string), f, false) + if err != nil { + return fmt.Errorf("Failed to send file descriptor: %w", err) + } + + revert.Add(func() { +- _ = m.RemoveFDFromFDSet(device["id"]) ++ _ = m.RemoveFDFromFDSet(qemuDev["id"].(string)) + }) + +- device["hostdevice"] = fmt.Sprintf("/dev/fdset/%d", info.ID) ++ qemuDev["hostdevice"] = fmt.Sprintf("/dev/fdset/%d", info.ID) + +- err = m.AddDevice(device) ++ err = m.AddDevice(qemuDev) + if err != nil { + return fmt.Errorf("Failed to add device: %w", err) + } +@@ -9188,19 +9188,19 @@ func (d *qemu) setCPUs(monitor *qmp.Monitor, count int) error { + + devID := fmt.Sprintf("cpu%d%d%d", cpu.Props.SocketID, cpu.Props.CoreID, cpu.Props.ThreadID) + +- dev := map[string]string{ ++ qemuDev := map[string]any{ + "id": devID, + "driver": cpu.Type, +- "core-id": fmt.Sprintf("%d", cpu.Props.CoreID), ++ "core-id": cpu.Props.CoreID, + } + + // No such thing as sockets and threads on s390x. + if d.architecture != osarch.ARCH_64BIT_S390_BIG_ENDIAN { +- dev["socket-id"] = fmt.Sprintf("%d", cpu.Props.SocketID) +- dev["thread-id"] = fmt.Sprintf("%d", cpu.Props.ThreadID) ++ qemuDev["socket-id"] = cpu.Props.SocketID ++ qemuDev["thread-id"] = cpu.Props.ThreadID + } + +- err := monitor.AddDevice(dev) ++ err := monitor.AddDevice(qemuDev) + if err != nil { + return fmt.Errorf("Failed to add device: %w", err) + } +@@ -9229,12 +9229,12 @@ func (d *qemu) setCPUs(monitor *qmp.Monitor, count int) error { + } + + revert.Add(func() { +- err := monitor.AddDevice(map[string]string{ ++ err := monitor.AddDevice(map[string]any{ + "id": devID, + "driver": cpu.Type, +- "socket-id": fmt.Sprintf("%d", cpu.Props.SocketID), +- "core-id": fmt.Sprintf("%d", cpu.Props.CoreID), +- "thread-id": fmt.Sprintf("%d", cpu.Props.ThreadID), ++ "socket-id": cpu.Props.SocketID, ++ "core-id": cpu.Props.CoreID, ++ "thread-id": cpu.Props.ThreadID, + }) + d.logger.Warn("Failed to add CPU device", logger.Ctx{"err": err}) + }) +diff --git a/internal/server/instance/drivers/qmp/commands.go b/internal/server/instance/drivers/qmp/commands.go +index 3e9752780c5..d81da8ff4f4 100644 +--- a/internal/server/instance/drivers/qmp/commands.go ++++ b/internal/server/instance/drivers/qmp/commands.go +@@ -538,7 +538,7 @@ func (m *Monitor) SetMemoryBalloonSizeBytes(sizeBytes int64) error { + } + + // AddBlockDevice adds a block device. +-func (m *Monitor) AddBlockDevice(blockDev map[string]any, device map[string]string) error { ++func (m *Monitor) AddBlockDevice(blockDev map[string]any, device map[string]any) error { + revert := revert.New() + defer revert.Fail() + +@@ -624,7 +624,7 @@ func (m *Monitor) RemoveCharDevice(deviceID string) error { + } + + // AddDevice adds a new device. +-func (m *Monitor) AddDevice(device map[string]string) error { ++func (m *Monitor) AddDevice(device map[string]any) error { + if device != nil { + err := m.Run("device_add", device, nil) + if err != nil { +@@ -656,7 +656,7 @@ func (m *Monitor) RemoveDevice(deviceID string) error { + } + + // AddNIC adds a NIC device. +-func (m *Monitor) AddNIC(netDev map[string]any, device map[string]string) error { ++func (m *Monitor) AddNIC(netDev map[string]any, device map[string]any) error { + revert := revert.New() + defer revert.Fail() + diff --git a/pkgs/by-name/in/incus/package.nix b/pkgs/by-name/in/incus/package.nix index 551987d1c16e..a0e1c4c3e0c5 100644 --- a/pkgs/by-name/in/incus/package.nix +++ b/pkgs/by-name/in/incus/package.nix @@ -2,5 +2,8 @@ import ./generic.nix { hash = "sha256-Ir+cT+2xA+L4kBXhwA0XXE/D8zjMPGYiwW0VrEdobZ4="; version = "6.8.0"; vendorHash = "sha256-CDLq41AB2Y9nYlTuXZaAOgwXIin9CbqSXCFoigsc14A="; - patches = [ ]; + patches = [ + # qemu 9.2 support + ./1531.diff + ]; }