[libvirt] [PATCH 0/4] test_driver: implement IOThread related APIs

Ilias Stamatis (4): test_driver: implement virDomainAddIOThread test_driver: implement virDomainDelIOThread test_driver: implement virDomainPinIOThread test_driver: implement virDomainGetIOThreadInfo src/test/test_driver.c | 248 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) -- 2.22.0

Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 2e33a9dd55..313cf5e7ef 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2603,6 +2603,56 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus, } +static int +testDomainAddIOThread(virDomainPtr dom, + unsigned int iothread_id, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + virDomainIOThreadIDDefPtr iothrid = NULL; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (iothread_id == 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid value of 0 for iothread_id")); + return -1; + } + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (virDomainIOThreadIDFind(def, iothread_id)) { + virReportError(VIR_ERR_INVALID_ARG, + _("an IOThread is already using iothread_id '%u'"), + iothread_id); + goto cleanup; + } + + if (VIR_ALLOC(iothrid) < 0) + goto cleanup; + + iothrid->iothread_id = iothread_id; + + if (VIR_APPEND_ELEMENT_COPY(def->iothreadids, def->niothreadids, iothrid) < 0) + goto cleanup; + + ret = 0; + + cleanup: + if (ret < 0) + virDomainIOThreadIDDefFree(iothrid); + virDomainObjEndAPI(&vm); + return ret; +} + + static int testDomainSetUserPassword(virDomainPtr dom, const char *user ATTRIBUTE_UNUSED, @@ -7742,6 +7792,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainSaveImageGetXMLDesc = testDomainSaveImageGetXMLDesc, /* 5.5.0 */ .domainCoreDump = testDomainCoreDump, /* 0.3.2 */ .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */ + .domainAddIOThread = testDomainAddIOThread, /* 5.6.0 */ .domainSetUserPassword = testDomainSetUserPassword, /* 5.6.0 */ .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */ .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */ -- 2.22.0

On Tue, Jul 23, 2019 at 12:17:54PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- ...
+ + if (VIR_ALLOC(iothrid) < 0) + goto cleanup; + + iothrid->iothread_id = iothread_id; + + if (VIR_APPEND_ELEMENT_COPY(def->iothreadids, def->niothreadids, iothrid) < 0) + goto cleanup;
virDomainIOThreadIDAdd could be used ^here, Reviewed-by: Erik Skultety <eskultet@redhat.com>

Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 313cf5e7ef..29262e4d34 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2653,6 +2653,77 @@ testDomainAddIOThread(virDomainPtr dom, } +static int +testDomainDelIOThread(virDomainPtr dom, + unsigned int iothread_id, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + size_t i, j; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (iothread_id == 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid value of 0 for iothread_id")); + return -1; + } + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (!virDomainIOThreadIDFind(def, iothread_id)) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot find IOThread '%u' in iothreadids list"), + iothread_id); + goto cleanup; + } + + for (i = 0; i < def->ndisks; i++) { + if (def->disks[i]->iothread == iothread_id) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot remove IOThread %u since it " + "is being used by disk '%s'"), + iothread_id, def->disks[i]->dst); + goto cleanup; + } + } + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->iothread == iothread_id) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot remove IOThread '%u' since it " + "is being used by controller"), + iothread_id); + goto cleanup; + } + } + + for (i = 0; i < def->niothreadids; i++) { + if (def->iothreadids[i]->iothread_id == iothread_id) { + for (j = i + 1; j < def->niothreadids; j++) + def->iothreadids[j]->autofill = false; + + virDomainIOThreadIDDefFree(def->iothreadids[i]); + VIR_DELETE_ELEMENT(def->iothreadids, i, def->niothreadids); + + break; + } + } + + ret = 0; + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + static int testDomainSetUserPassword(virDomainPtr dom, const char *user ATTRIBUTE_UNUSED, @@ -7793,6 +7864,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainCoreDump = testDomainCoreDump, /* 0.3.2 */ .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */ .domainAddIOThread = testDomainAddIOThread, /* 5.6.0 */ + .domainDelIOThread = testDomainDelIOThread, /* 5.6.0 */ .domainSetUserPassword = testDomainSetUserPassword, /* 5.6.0 */ .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */ .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */ -- 2.22.0

On Tue, Jul 23, 2019 at 12:17:55PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 313cf5e7ef..29262e4d34 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2653,6 +2653,77 @@ testDomainAddIOThread(virDomainPtr dom, }
+static int +testDomainDelIOThread(virDomainPtr dom, + unsigned int iothread_id, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + size_t i, j; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (iothread_id == 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid value of 0 for iothread_id")); + return -1; + } + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (!virDomainIOThreadIDFind(def, iothread_id)) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot find IOThread '%u' in iothreadids list"), + iothread_id); + goto cleanup; + } + + for (i = 0; i < def->ndisks; i++) { + if (def->disks[i]->iothread == iothread_id) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot remove IOThread %u since it " + "is being used by disk '%s'"), + iothread_id, def->disks[i]->dst); + goto cleanup; + } + } + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->iothread == iothread_id) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot remove IOThread '%u' since it " + "is being used by controller"), + iothread_id); + goto cleanup; + } + } + + for (i = 0; i < def->niothreadids; i++) { + if (def->iothreadids[i]->iothread_id == iothread_id) { + for (j = i + 1; j < def->niothreadids; j++) + def->iothreadids[j]->autofill = false;
So, I read both the commit and the commentary in the QEMU driver which added ^this autofill clearing hunk. I haven't tried with QEMU, but just from reading those, I'm still not clear why it's actually needed. Even more so in test driver, I tried to remove the nested loop and everything seemed to be working, I had half of the thread defined, half of them autofilled, removed from the beginning, middle of the list, basically from anywhere and the data that libvirt reported were intact, both in the XML and the dedicated API. Right now, it's magic to me. Erik

On Thu, Jul 25, 2019 at 5:47 PM Erik Skultety <eskultet@redhat.com> wrote:
On Tue, Jul 23, 2019 at 12:17:55PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 313cf5e7ef..29262e4d34 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2653,6 +2653,77 @@ testDomainAddIOThread(virDomainPtr dom, }
+static int +testDomainDelIOThread(virDomainPtr dom, + unsigned int iothread_id, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + size_t i, j; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (iothread_id == 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid value of 0 for iothread_id")); + return -1; + } + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (!virDomainIOThreadIDFind(def, iothread_id)) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot find IOThread '%u' in iothreadids list"), + iothread_id); + goto cleanup; + } + + for (i = 0; i < def->ndisks; i++) { + if (def->disks[i]->iothread == iothread_id) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot remove IOThread %u since it " + "is being used by disk '%s'"), + iothread_id, def->disks[i]->dst); + goto cleanup; + } + } + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->iothread == iothread_id) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot remove IOThread '%u' since it " + "is being used by controller"), + iothread_id); + goto cleanup; + } + } + + for (i = 0; i < def->niothreadids; i++) { + if (def->iothreadids[i]->iothread_id == iothread_id) { + for (j = i + 1; j < def->niothreadids; j++) + def->iothreadids[j]->autofill = false;
So, I read both the commit and the commentary in the QEMU driver which added ^this autofill clearing hunk. I haven't tried with QEMU, but just from reading those, I'm still not clear why it's actually needed. Even more so in test driver, I tried to remove the nested loop and everything seemed to be working, I had half of the thread defined, half of them autofilled, removed from the beginning, middle of the list, basically from anywhere and the data that libvirt reported were intact, both in the XML and the dedicated API. Right now, it's magic to me.
Erik
Tbh, I also didn't understand it when I read it but I thought since it's there let's just copy it to make sure. Maybe somebody that touched that code could explain? If you checked that there are no side-effects when removing it then sure let's remove it. From the test driver at least. Ilias

Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 29262e4d34..47e28a01ec 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2724,6 +2724,56 @@ testDomainDelIOThread(virDomainPtr dom, } +static int +testDomainPinIOThread(virDomainPtr dom, + unsigned int iothread_id, + unsigned char *cpumap, + int maplen, + unsigned int flags) +{ + int ret = -1; + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + virDomainIOThreadIDDefPtr iothrid = NULL; + virBitmapPtr cpumask = NULL; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (!(cpumask = virBitmapNewData(cpumap, maplen))) + goto cleanup; + + if (virBitmapIsAllClear(cpumask)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Empty iothread cpumap list for pinning")); + goto cleanup; + } + + if (!(iothrid = virDomainIOThreadIDFind(def, iothread_id))) { + virReportError(VIR_ERR_INVALID_ARG, + _("iothreadid %d not found"), iothread_id); + goto cleanup; + } + + virBitmapFree(iothrid->cpumask); + iothrid->cpumask = cpumask; + iothrid->autofill = false; + + ret = 0; + cleanup: + if (ret < 0) + virBitmapFree(cpumask); + virDomainObjEndAPI(&vm); + return ret; +} + + static int testDomainSetUserPassword(virDomainPtr dom, const char *user ATTRIBUTE_UNUSED, @@ -7865,6 +7915,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */ .domainAddIOThread = testDomainAddIOThread, /* 5.6.0 */ .domainDelIOThread = testDomainDelIOThread, /* 5.6.0 */ + .domainPinIOThread = testDomainPinIOThread, /* 5.6.0 */ .domainSetUserPassword = testDomainSetUserPassword, /* 5.6.0 */ .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */ .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */ -- 2.22.0

Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 47e28a01ec..4c6f3db8de 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2774,6 +2774,79 @@ testDomainPinIOThread(virDomainPtr dom, } +static int +testDomainGetIOThreadInfo(virDomainPtr dom, + virDomainIOThreadInfoPtr **info, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + virBitmapPtr cpumask = NULL; + virBitmapPtr bitmap = NULL; + virDomainIOThreadInfoPtr *info_ret = NULL; + size_t i; + int hostcpus; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (def->niothreadids == 0) + return 0; + + if ((hostcpus = virHostCPUGetCount()) < 0) + goto cleanup; + + if (VIR_ALLOC_N(info_ret, def->niothreadids) < 0) + goto cleanup; + + for (i = 0; i < def->niothreadids; i++) { + if (VIR_ALLOC(info_ret[i]) < 0) + goto cleanup; + + info_ret[i]->iothread_id = def->iothreadids[i]->iothread_id; + + cpumask = def->iothreadids[i]->cpumask; + if (!cpumask) { + if (def->cpumask) { + cpumask = def->cpumask; + } else { + if (!(bitmap = virBitmapNew(hostcpus))) + goto cleanup; + virBitmapSetAll(bitmap); + cpumask = bitmap; + } + } + + if (virBitmapToData(cpumask, &info_ret[i]->cpumap, + &info_ret[i]->cpumaplen) < 0) + goto cleanup; + + virBitmapFree(bitmap); + bitmap = NULL; + } + + VIR_STEAL_PTR(*info, info_ret); + ret = def->niothreadids; + + cleanup: + if (info_ret) { + for (i = 0; i < def->niothreadids; i++) + virDomainIOThreadInfoFree(info_ret[i]); + VIR_FREE(info_ret); + } + virBitmapFree(bitmap); + virDomainObjEndAPI(&vm); + return ret; +} + + static int testDomainSetUserPassword(virDomainPtr dom, const char *user ATTRIBUTE_UNUSED, @@ -7916,6 +7989,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainAddIOThread = testDomainAddIOThread, /* 5.6.0 */ .domainDelIOThread = testDomainDelIOThread, /* 5.6.0 */ .domainPinIOThread = testDomainPinIOThread, /* 5.6.0 */ + .domainGetIOThreadInfo = testDomainGetIOThreadInfo, /* 5.6.0 */ .domainSetUserPassword = testDomainSetUserPassword, /* 5.6.0 */ .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */ .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */ -- 2.22.0

On Tue, Jul 23, 2019 at 12:17:54PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> ---
One more thing, this patch will break virsh-optparse again, more specifically some of the cpu-stats tests (yeah, those are very bad tests). The offending ones need to be removed in a standalone patch related to this one. Ultimately, the whole optparse thing will need to be re-written in a different manner. Erik

On Thu, Jul 25, 2019 at 02:09:01PM +0200, Erik Skultety wrote:
On Tue, Jul 23, 2019 at 12:17:54PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> ---
One more thing, this patch will break virsh-optparse again, more specifically some of the cpu-stats tests (yeah, those are very bad tests). The offending ones need to be removed in a standalone patch related to this one. Ultimately, the whole optparse thing will need to be re-written in a different manner.
Erik
Sigh...^this response was meant for the CPUStats patch...please ignore it in context of the iothread series. Erik

On Tue, Jul 23, 2019 at 12:17:57PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 47e28a01ec..4c6f3db8de 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2774,6 +2774,79 @@ testDomainPinIOThread(virDomainPtr dom, }
+static int +testDomainGetIOThreadInfo(virDomainPtr dom, + virDomainIOThreadInfoPtr **info, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + virBitmapPtr cpumask = NULL; + virBitmapPtr bitmap = NULL; + virDomainIOThreadInfoPtr *info_ret = NULL; + size_t i; + int hostcpus; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (def->niothreadids == 0) + return 0;
^This will leave the object locked, so once you do Info, anything else after that will deadlock, so goto is needed. Erik

On Thu, Jul 25, 2019 at 5:43 PM Erik Skultety <eskultet@redhat.com> wrote:
On Tue, Jul 23, 2019 at 12:17:57PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 47e28a01ec..4c6f3db8de 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2774,6 +2774,79 @@ testDomainPinIOThread(virDomainPtr dom, }
+static int +testDomainGetIOThreadInfo(virDomainPtr dom, + virDomainIOThreadInfoPtr **info, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + virBitmapPtr cpumask = NULL; + virBitmapPtr bitmap = NULL; + virDomainIOThreadInfoPtr *info_ret = NULL; + size_t i; + int hostcpus; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (def->niothreadids == 0) + return 0;
^This will leave the object locked, so once you do Info, anything else after that will deadlock, so goto is needed.
Erik
Of course... I don't know how I missed that. I guess I don't need to re-send it though only for this change? Ilias

On Fri, Jul 26, 2019 at 12:55:20PM +0200, Ilias Stamatis wrote:
On Thu, Jul 25, 2019 at 5:43 PM Erik Skultety <eskultet@redhat.com> wrote:
On Tue, Jul 23, 2019 at 12:17:57PM +0200, Ilias Stamatis wrote:
Signed-off-by: Ilias Stamatis <stamatis.iliass@gmail.com> --- src/test/test_driver.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 47e28a01ec..4c6f3db8de 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2774,6 +2774,79 @@ testDomainPinIOThread(virDomainPtr dom, }
+static int +testDomainGetIOThreadInfo(virDomainPtr dom, + virDomainIOThreadInfoPtr **info, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + virBitmapPtr cpumask = NULL; + virBitmapPtr bitmap = NULL; + virDomainIOThreadInfoPtr *info_ret = NULL; + size_t i; + int hostcpus; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + + if (def->niothreadids == 0) + return 0;
^This will leave the object locked, so once you do Info, anything else after that will deadlock, so goto is needed.
Erik
Of course... I don't know how I missed that. I guess I don't need to re-send it though only for this change?
No need, this can go straight in, I still need to look more closely on the iothread deletion API though. so for this one: Reviewed-by: Erik Skultety <eskultet@redhat.com>
participants (2)
-
Erik Skultety
-
Ilias Stamatis