Skip to content

Commit 7298e13

Browse files
incus: fix virtual-machines with qemu 9.2 (#369996)
2 parents 523c8d3 + 7dbb4ff commit 7298e13

File tree

2 files changed

+275
-1
lines changed

2 files changed

+275
-1
lines changed

pkgs/by-name/in/incus/1531.diff

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
diff --git a/internal/server/instance/drivers/driver_qemu.go b/internal/server/instance/drivers/driver_qemu.go
2+
index 1c773213468..fb43917ca96 100644
3+
--- a/internal/server/instance/drivers/driver_qemu.go
4+
+++ b/internal/server/instance/drivers/driver_qemu.go
5+
@@ -2393,7 +2393,7 @@ func (d *qemu) deviceAttachPath(deviceName string, configCopy map[string]string,
6+
7+
d.logger.Debug("Using PCI bus device to hotplug virtiofs into", logger.Ctx{"device": deviceName, "port": pciDeviceName})
8+
9+
- qemuDev := map[string]string{
10+
+ qemuDev := map[string]any{
11+
"driver": "vhost-user-fs-pci",
12+
"bus": pciDeviceName,
13+
"addr": "00.0",
14+
@@ -2535,7 +2535,7 @@ func (d *qemu) deviceAttachNIC(deviceName string, configCopy map[string]string,
15+
return err
16+
}
17+
18+
- qemuDev := make(map[string]string)
19+
+ qemuDev := make(map[string]any)
20+
21+
// PCIe and PCI require a port device name to hotplug the NIC into.
22+
if slices.Contains([]string{"pcie", "pci"}, qemuBus) {
23+
@@ -2633,7 +2633,7 @@ func (d *qemu) deviceAttachPCI(deviceName string, configCopy map[string]string,
24+
return err
25+
}
26+
27+
- qemuDev := make(map[string]string)
28+
+ qemuDev := make(map[string]any)
29+
escapedDeviceName := linux.PathNameEncode(devName)
30+
31+
d.logger.Debug("Using PCI bus device to hotplug NIC into", logger.Ctx{"device": deviceName, "port": pciDeviceName})
32+
@@ -3589,7 +3589,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo
33+
break
34+
}
35+
36+
- qemuDev := make(map[string]string)
37+
+ qemuDev := make(map[string]any)
38+
if slices.Contains([]string{"nvme", "virtio-blk"}, busName) {
39+
// Allocate a PCI(e) port and write it to the config file so QMP can "hotplug" the
40+
// drive into it later.
41+
@@ -3600,7 +3600,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo
42+
qemuDev["addr"] = devAddr
43+
44+
if multi {
45+
- qemuDev["multifunction"] = "on"
46+
+ qemuDev["multifunction"] = true
47+
}
48+
}
49+
50+
@@ -3624,7 +3624,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo
51+
52+
// Add network device.
53+
if len(runConf.NetworkInterface) > 0 {
54+
- qemuDev := make(map[string]string)
55+
+ qemuDev := make(map[string]any)
56+
if slices.Contains([]string{"pcie", "pci"}, bus.name) {
57+
// Allocate a PCI(e) port and write it to the config file so QMP can "hotplug" the
58+
// NIC into it later.
59+
@@ -3635,7 +3635,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo
60+
qemuDev["addr"] = devAddr
61+
62+
if multi {
63+
- qemuDev["multifunction"] = "on"
64+
+ qemuDev["multifunction"] = true
65+
}
66+
}
67+
68+
@@ -3860,7 +3860,7 @@ func (d *qemu) addFileDescriptor(fdFiles *[]*os.File, file *os.File) int {
69+
}
70+
71+
// addRootDriveConfig adds the qemu config required for adding the root drive.
72+
-func (d *qemu) addRootDriveConfig(qemuDev map[string]string, mountInfo *storagePools.MountInfo, bootIndexes map[string]int, rootDriveConf deviceConfig.MountEntryItem) (monitorHook, error) {
73+
+func (d *qemu) addRootDriveConfig(qemuDev map[string]any, mountInfo *storagePools.MountInfo, bootIndexes map[string]int, rootDriveConf deviceConfig.MountEntryItem) (monitorHook, error) {
74+
if rootDriveConf.TargetPath != "/" {
75+
return nil, fmt.Errorf("Non-root drive config supplied")
76+
}
77+
@@ -3992,7 +3992,7 @@ func (d *qemu) addDriveDirConfig(cfg *[]cfgSection, bus *qemuBus, fdFiles *[]*os
78+
}
79+
80+
// addDriveConfig adds the qemu config required for adding a supplementary drive.
81+
-func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string]int, driveConf deviceConfig.MountEntryItem) (monitorHook, error) {
82+
+func (d *qemu) addDriveConfig(qemuDev map[string]any, bootIndexes map[string]int, driveConf deviceConfig.MountEntryItem) (monitorHook, error) {
83+
aioMode := "native" // Use native kernel async IO and O_DIRECT by default.
84+
cacheMode := "none" // Bypass host cache, use O_DIRECT semantics by default.
85+
media := "disk"
86+
@@ -4248,7 +4248,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string]
87+
}
88+
89+
if qemuDev == nil {
90+
- qemuDev = map[string]string{}
91+
+ qemuDev = map[string]any{}
92+
}
93+
94+
qemuDev["id"] = fmt.Sprintf("%s%s", qemuDeviceIDPrefix, escapedDeviceName)
95+
@@ -4256,8 +4256,8 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string]
96+
qemuDev["serial"] = fmt.Sprintf("%s%s", qemuBlockDevIDPrefix, escapedDeviceName)
97+
98+
if bus == "virtio-scsi" {
99+
- qemuDev["channel"] = "0"
100+
- qemuDev["lun"] = "1"
101+
+ qemuDev["channel"] = 0
102+
+ qemuDev["lun"] = 1
103+
qemuDev["bus"] = "qemu_scsi.0"
104+
105+
if media == "disk" {
106+
@@ -4282,7 +4282,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string]
107+
}
108+
109+
if bootIndexes != nil {
110+
- qemuDev["bootindex"] = strconv.Itoa(bootIndexes[driveConf.DevName])
111+
+ qemuDev["bootindex"] = bootIndexes[driveConf.DevName]
112+
}
113+
114+
monHook := func(m *qmp.Monitor) error {
115+
@@ -4336,7 +4336,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string]
116+
}
117+
118+
if driveConf.Limits != nil {
119+
- err = m.SetBlockThrottle(qemuDev["id"], int(driveConf.Limits.ReadBytes), int(driveConf.Limits.WriteBytes), int(driveConf.Limits.ReadIOps), int(driveConf.Limits.WriteIOps))
120+
+ err = m.SetBlockThrottle(qemuDev["id"].(string), int(driveConf.Limits.ReadBytes), int(driveConf.Limits.WriteBytes), int(driveConf.Limits.ReadIOps), int(driveConf.Limits.WriteIOps))
121+
if err != nil {
122+
return fmt.Errorf("Failed applying limits for disk device %q: %w", driveConf.DevName, err)
123+
}
124+
@@ -4351,7 +4351,7 @@ func (d *qemu) addDriveConfig(qemuDev map[string]string, bootIndexes map[string]
125+
126+
// addNetDevConfig adds the qemu config required for adding a network device.
127+
// The qemuDev map is expected to be preconfigured with the settings for an existing port to use for the device.
128+
-func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIndexes map[string]int, nicConfig []deviceConfig.RunConfigItem) (monitorHook, error) {
129+
+func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]any, bootIndexes map[string]int, nicConfig []deviceConfig.RunConfigItem) (monitorHook, error) {
130+
reverter := revert.New()
131+
defer reverter.Fail()
132+
133+
@@ -4382,7 +4382,7 @@ func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIn
134+
if len(bootIndexes) > 0 {
135+
bootIndex, found := bootIndexes[devName]
136+
if found {
137+
- qemuDev["bootindex"] = strconv.Itoa(bootIndex)
138+
+ qemuDev["bootindex"] = bootIndex
139+
}
140+
}
141+
142+
@@ -4400,9 +4400,9 @@ func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIn
143+
// Number of vectors is number of vCPUs * 2 (RX/TX) + 2 (config/control MSI-X).
144+
vectors := 2*queueCount + 2
145+
if vectors > 0 {
146+
- qemuDev["mq"] = "on"
147+
+ qemuDev["mq"] = true
148+
if slices.Contains([]string{"pcie", "pci"}, busName) {
149+
- qemuDev["vectors"] = strconv.Itoa(vectors)
150+
+ qemuDev["vectors"] = vectors
151+
}
152+
}
153+
154+
@@ -4591,9 +4591,9 @@ func (d *qemu) addNetDevConfig(busName string, qemuDev map[string]string, bootIn
155+
}
156+
157+
qemuDev["netdev"] = qemuNetDev["id"].(string)
158+
- qemuDev["page-per-vq"] = "on"
159+
- qemuDev["iommu_platform"] = "on"
160+
- qemuDev["disable-legacy"] = "on"
161+
+ qemuDev["page-per-vq"] = true
162+
+ qemuDev["iommu_platform"] = true
163+
+ qemuDev["disable-legacy"] = true
164+
165+
err = m.AddNIC(qemuNetDev, qemuDev)
166+
if err != nil {
167+
@@ -4819,7 +4819,7 @@ func (d *qemu) addGPUDevConfig(cfg *[]cfgSection, bus *qemuBus, gpuConfig []devi
168+
}
169+
170+
func (d *qemu) addUSBDeviceConfig(usbDev deviceConfig.USBDeviceItem) (monitorHook, error) {
171+
- device := map[string]string{
172+
+ qemuDev := map[string]any{
173+
"id": fmt.Sprintf("%s%s", qemuDeviceIDPrefix, usbDev.DeviceName),
174+
"driver": "usb-host",
175+
"bus": "qemu_usb.0",
176+
@@ -4836,18 +4836,18 @@ func (d *qemu) addUSBDeviceConfig(usbDev deviceConfig.USBDeviceItem) (monitorHoo
177+
178+
defer func() { _ = f.Close() }()
179+
180+
- info, err := m.SendFileWithFDSet(device["id"], f, false)
181+
+ info, err := m.SendFileWithFDSet(qemuDev["id"].(string), f, false)
182+
if err != nil {
183+
return fmt.Errorf("Failed to send file descriptor: %w", err)
184+
}
185+
186+
revert.Add(func() {
187+
- _ = m.RemoveFDFromFDSet(device["id"])
188+
+ _ = m.RemoveFDFromFDSet(qemuDev["id"].(string))
189+
})
190+
191+
- device["hostdevice"] = fmt.Sprintf("/dev/fdset/%d", info.ID)
192+
+ qemuDev["hostdevice"] = fmt.Sprintf("/dev/fdset/%d", info.ID)
193+
194+
- err = m.AddDevice(device)
195+
+ err = m.AddDevice(qemuDev)
196+
if err != nil {
197+
return fmt.Errorf("Failed to add device: %w", err)
198+
}
199+
@@ -9188,19 +9188,19 @@ func (d *qemu) setCPUs(monitor *qmp.Monitor, count int) error {
200+
201+
devID := fmt.Sprintf("cpu%d%d%d", cpu.Props.SocketID, cpu.Props.CoreID, cpu.Props.ThreadID)
202+
203+
- dev := map[string]string{
204+
+ qemuDev := map[string]any{
205+
"id": devID,
206+
"driver": cpu.Type,
207+
- "core-id": fmt.Sprintf("%d", cpu.Props.CoreID),
208+
+ "core-id": cpu.Props.CoreID,
209+
}
210+
211+
// No such thing as sockets and threads on s390x.
212+
if d.architecture != osarch.ARCH_64BIT_S390_BIG_ENDIAN {
213+
- dev["socket-id"] = fmt.Sprintf("%d", cpu.Props.SocketID)
214+
- dev["thread-id"] = fmt.Sprintf("%d", cpu.Props.ThreadID)
215+
+ qemuDev["socket-id"] = cpu.Props.SocketID
216+
+ qemuDev["thread-id"] = cpu.Props.ThreadID
217+
}
218+
219+
- err := monitor.AddDevice(dev)
220+
+ err := monitor.AddDevice(qemuDev)
221+
if err != nil {
222+
return fmt.Errorf("Failed to add device: %w", err)
223+
}
224+
@@ -9229,12 +9229,12 @@ func (d *qemu) setCPUs(monitor *qmp.Monitor, count int) error {
225+
}
226+
227+
revert.Add(func() {
228+
- err := monitor.AddDevice(map[string]string{
229+
+ err := monitor.AddDevice(map[string]any{
230+
"id": devID,
231+
"driver": cpu.Type,
232+
- "socket-id": fmt.Sprintf("%d", cpu.Props.SocketID),
233+
- "core-id": fmt.Sprintf("%d", cpu.Props.CoreID),
234+
- "thread-id": fmt.Sprintf("%d", cpu.Props.ThreadID),
235+
+ "socket-id": cpu.Props.SocketID,
236+
+ "core-id": cpu.Props.CoreID,
237+
+ "thread-id": cpu.Props.ThreadID,
238+
})
239+
d.logger.Warn("Failed to add CPU device", logger.Ctx{"err": err})
240+
})
241+
diff --git a/internal/server/instance/drivers/qmp/commands.go b/internal/server/instance/drivers/qmp/commands.go
242+
index 3e9752780c5..d81da8ff4f4 100644
243+
--- a/internal/server/instance/drivers/qmp/commands.go
244+
+++ b/internal/server/instance/drivers/qmp/commands.go
245+
@@ -538,7 +538,7 @@ func (m *Monitor) SetMemoryBalloonSizeBytes(sizeBytes int64) error {
246+
}
247+
248+
// AddBlockDevice adds a block device.
249+
-func (m *Monitor) AddBlockDevice(blockDev map[string]any, device map[string]string) error {
250+
+func (m *Monitor) AddBlockDevice(blockDev map[string]any, device map[string]any) error {
251+
revert := revert.New()
252+
defer revert.Fail()
253+
254+
@@ -624,7 +624,7 @@ func (m *Monitor) RemoveCharDevice(deviceID string) error {
255+
}
256+
257+
// AddDevice adds a new device.
258+
-func (m *Monitor) AddDevice(device map[string]string) error {
259+
+func (m *Monitor) AddDevice(device map[string]any) error {
260+
if device != nil {
261+
err := m.Run("device_add", device, nil)
262+
if err != nil {
263+
@@ -656,7 +656,7 @@ func (m *Monitor) RemoveDevice(deviceID string) error {
264+
}
265+
266+
// AddNIC adds a NIC device.
267+
-func (m *Monitor) AddNIC(netDev map[string]any, device map[string]string) error {
268+
+func (m *Monitor) AddNIC(netDev map[string]any, device map[string]any) error {
269+
revert := revert.New()
270+
defer revert.Fail()
271+

pkgs/by-name/in/incus/package.nix

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@ import ./generic.nix {
22
hash = "sha256-Ir+cT+2xA+L4kBXhwA0XXE/D8zjMPGYiwW0VrEdobZ4=";
33
version = "6.8.0";
44
vendorHash = "sha256-CDLq41AB2Y9nYlTuXZaAOgwXIin9CbqSXCFoigsc14A=";
5-
patches = [ ];
5+
patches = [
6+
# qemu 9.2 support
7+
./1531.diff
8+
];
69
}

0 commit comments

Comments
 (0)