On Fri, Jul 26, 2024 at 10:52:18 +0200, Adam Julis wrote: > GSList of iothreads is not allowed to be changed while the > virtual machine is running. > > Resolves: https://issues.redhat.com/browse/RHEL-23607 > Signed-off-by: Adam Julis <ajulis@xxxxxxxxxx> > --- > While the qemuDomainDiskChangeSupported() design primarily uses > its macros (CHECK_EQ and CHECK_STREQ_NULLABLE), the logic for comparing 2 > GSList of iothreads could perhaps be extracted into a separate function > (e.g. IothreadsGslistCompare(GSList *first, GSList *second)). I am > absolutely not sure about this idea so feel free to comment. > > src/qemu/qemu_domain.c | 53 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 53 insertions(+) > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index 298f4bfb9e..2b5222c685 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -8505,6 +8505,59 @@ qemuDomainDiskChangeSupported(virDomainDiskDef *disk, > CHECK_EQ(discard, "discard", true); > CHECK_EQ(iothread, "iothread", true); > > + /* compare list of iothreads, no change allowed */ This is a bit too long for the existing function and thus should be put into it's own: static bool qemuDomainDiskChangeSupportedIothreads(virDomainDiskDef *disk, virDomainDiskDef *orig_disk) > + if (orig_disk->iothreads != disk->iothreads) { These are pointers which will be equal only if both are NULL. While this is technically correct it's confusing at first glance. Since the loop below needs to handle mismatched-lenght GSlists anyways there's no need to do this check before. > + GSList *old; > + GSList *new = disk->iothreads; > + bool print_err = true; > + > + for (old = orig_disk->iothreads; old; old = old->next) { > + virDomainDiskIothreadDef *orig = old->data; > + virDomainDiskIothreadDef *update; > + print_err = false; > + > + if (new == NULL) { > + print_err = true; > + break; > + } The two styles of iterating through the two GSlists are also confusing at the first glance. In order to make the code more readable I'll change it to a uniform style. > + > + update = new->data; > + > + if (orig->id != update->id) { > + print_err = true; > + break; > + } > + > + if (orig->nqueues != update->nqueues) { > + print_err = true; > + break; > + } > + > + if (orig->nqueues != 0) { > + ssize_t i = 0; 'nqueues' is a 'size_t' so no need for ssize_t. > + > + while (i < orig->nqueues) { > + if (orig->queues[i] != update->queues[i]) { > + print_err = true; > + break; > + } This loop doesn't have an increment, so it'll loop forever if the first entry matches. > + } > + } > + > + new = new->next; > + if (new) > + print_err = true; > + } > + > + if (print_err) { > + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, > + _("cannot modify field '%1$s' (or it's parts) of the disk"), > + "iothreads"); This is translation unfriendly: https://www.libvirt.org/coding-style.html#error-message-format I'll post a v2.