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: d3a4969dc5 ("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>
This commit is contained in:
Akihiko Odaki 2026-07-25 16:14:21 +09:00 committed by Marc-André Lureau
parent 4ae1c5c7d6
commit 8dc8449a67

View file

@ -195,6 +195,11 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
return false;
}
g->enabled_output_bitmask = 1;
g->req_state[0].width = g->conf.xres;
g->req_state[0].height = g->conf.yres;
for (output_idx = 0, node = g->conf.outputs;
node; output_idx++, node = node->next) {
if (output_idx == g->conf.max_outputs) {
@ -207,6 +212,17 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
node->value->name, EDID_NAME_MAX_LENGTH);
return false;
}
if (node->value->has_xres != node->value->has_yres) {
error_setg(errp,
"must set both outputs[%zd].xres and outputs[%zd].yres",
output_idx, output_idx);
return false;
}
if (node->value->has_xres && node->value->has_yres) {
g->enabled_output_bitmask |= (1 << output_idx);
g->req_state[output_idx].width = node->value->xres;
g->req_state[output_idx].height = node->value->yres;
}
}
if (virtio_gpu_virgl_enabled(g->conf)) {
@ -229,27 +245,6 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
virtio_add_queue(vdev, 16, cursor_cb);
}
g->enabled_output_bitmask = 1;
g->req_state[0].width = g->conf.xres;
g->req_state[0].height = g->conf.yres;
for (output_idx = 0, node = g->conf.outputs;
node && output_idx < g->conf.max_outputs;
output_idx++, node = node->next) {
if (node->value->has_xres != node->value->has_yres) {
error_setg(errp,
"must set both outputs[%zd].xres and outputs[%zd].yres",
output_idx, output_idx);
return false;
}
if (node->value->has_xres && node->value->has_yres) {
g->enabled_output_bitmask |= (1 << output_idx);
g->req_state[output_idx].width = node->value->xres;
g->req_state[output_idx].height = node->value->yres;
}
}
g->hw_ops = &virtio_gpu_ops;
for (i = 0; i < g->conf.max_outputs; i++) {
g->scanout[i].con =