hw/display/virtio-gpu: Avoid leaking migration blocker
virtio_gpu_base_device_realize() leaks a migration blocker if a check of the output list fails after adding one. Perform the check before adding a migration blocker to avoid the leak. This also simplifies the code by merging two loops. Fixes: d3a4969dc5ac ("Support per-head resolutions with virtio-gpu") Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260725-virgl-v1-1-58bb51e60da5@rsg.ci.i.u-tokyo.ac.jp>
Akihiko Odaki committed
Jul 25, 2026 at 16:14 UTC
8dc8449a678f56ea0746e1c002f3c671ef9c456d
1 file changed
+16
-21
hw/display/virtio-gpu-base.c
+16
-21
@@ -195,6 +195,11 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
195
return false;
196
}
197
198
+ g->enabled_output_bitmask = 1;
199
+
200
+ g->req_state[0].width = g->conf.xres;
201
+ g->req_state[0].height = g->conf.yres;
202
+
203
for (output_idx = 0, node = g->conf.outputs;
204
node; output_idx++, node = node->next) {
205
if (output_idx == g->conf.max_outputs) {
@@ -207,6 +212,17 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
212
node->value->name, EDID_NAME_MAX_LENGTH);
213
return false;
214
}
215
+ if (node->value->has_xres != node->value->has_yres) {
216
+ error_setg(errp,
217
+ "must set both outputs[%zd].xres and outputs[%zd].yres",
218
+ output_idx, output_idx);
219
+ return false;
220
+ }
221
+ if (node->value->has_xres && node->value->has_yres) {
222
+ g->enabled_output_bitmask |= (1 << output_idx);
223
+ g->req_state[output_idx].width = node->value->xres;
224
+ g->req_state[output_idx].height = node->value->yres;
225
+ }
226
}
227
228
if (virtio_gpu_virgl_enabled(g->conf)) {
@@ -229,27 +245,6 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
245
virtio_add_queue(vdev, 16, cursor_cb);
246
}
247
232
- g->enabled_output_bitmask = 1;
233
-
234
- g->req_state[0].width = g->conf.xres;
235
- g->req_state[0].height = g->conf.yres;
236
-
237
- for (output_idx = 0, node = g->conf.outputs;
238
- node && output_idx < g->conf.max_outputs;
239
- output_idx++, node = node->next) {
240
- if (node->value->has_xres != node->value->has_yres) {
241
- error_setg(errp,
242
- "must set both outputs[%zd].xres and outputs[%zd].yres",
243
- output_idx, output_idx);
244
- return false;
245
- }
246
- if (node->value->has_xres && node->value->has_yres) {
247
- g->enabled_output_bitmask |= (1 << output_idx);
248
- g->req_state[output_idx].width = node->value->xres;
249
- g->req_state[output_idx].height = node->value->yres;
250
- }
251
- }
252
-
248
g->hw_ops = &virtio_gpu_ops;
249
for (i = 0; i < g->conf.max_outputs; i++) {
250
g->scanout[i].con =