[libvirt] [PATCH v3 5/6] qemu: Add support to Add/Delete IOThreads

John Ferlan jferlan at redhat.com
Tue Apr 21 17:24:00 UTC 2015



On 04/21/2015 09:45 AM, Peter Krempa wrote:
> On Tue, Apr 14, 2015 at 21:18:25 -0400, John Ferlan wrote:
>> Add qemuDomainAddIOThread and qemuDomainDelIOThread in order to add or
>> remove an IOThread to/from the host either for live or config optoins
>>
>> The implementation for the 'live' option will use the iothreadpids list
>> in order to make decision, while the 'config' option will use the
>> iothreadids list.  Additionally, for deletion each may have to adjust
>> the iothreadpin list.
>>
>> IOThreads are implemented by qmp objects, the code makes use of the existing
>> qemuMonitorAddObject or qemuMonitorDelObject APIs.
>>
>> Signed-off-by: John Ferlan <jferlan at redhat.com>
>> ---
>>  src/conf/domain_audit.c  |   9 +
>>  src/conf/domain_audit.h  |   6 +
>>  src/libvirt_private.syms |   1 +
>>  src/qemu/qemu_driver.c   | 431 +++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 447 insertions(+)
>>
> 
> ...
> 
>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
>> index 008258f..f42d4fb 100644
>> --- a/src/qemu/qemu_driver.c
>> +++ b/src/qemu/qemu_driver.c
>> @@ -6179,6 +6179,435 @@ qemuDomainPinIOThread(virDomainPtr dom,
>>      return ret;
>>  }
>>  
>> +static int
>> +qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
>> +                             virDomainObjPtr vm,
>> +                             unsigned int iothread_id)
>> +{
>> +    qemuDomainObjPrivatePtr priv = vm->privateData;
>> +    char *alias = NULL;
>> +    size_t idx;
>> +    int rc = -1;
>> +    int ret = -1;
>> +    unsigned int orig_niothreads = vm->def->iothreads;
>> +    unsigned int exp_niothreads = vm->def->iothreads;
>> +    int new_niothreads = 0;
>> +    qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
>> +    unsigned int idval = 0;
>> +    virCgroupPtr cgroup_iothread = NULL;
>> +    char *mem_mask = NULL;
>> +    virDomainIOThreadIDDefPtr iothrid;
>> +
>> +    if (virDomainIOThreadIDFind(vm->def, iothread_id)) {
>> +        virReportError(VIR_ERR_INVALID_ARG,
>> +                       _("an IOThread is already using iothread_id '%u'"),
>> +                       iothread_id);
>> +        goto cleanup;
>> +    }
>> +
>> +    if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
>> +        return -1;
>> +
>> +    qemuDomainObjEnterMonitor(driver, vm);
>> +
>> +    rc = qemuMonitorAddObject(priv->mon, "iothread", alias, NULL);
>> +    exp_niothreads++;
>> +    if (rc < 0)
>> +        goto exit_monitor;
>> +
>> +    /* After hotplugging the IOThreads we need to re-detect the
>> +     * IOThreads thread_id's, adjust the cgroups, thread affinity,
>> +     * and add the thread_id to the vm->def->iothreadids list.
>> +     */
>> +    if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon,
>> +                                                  &new_iothreads)) < 0)
> 
> Since we are not doing any fancy iothread naming, this function can
> parse the iothread IDs from the alias right away ... [1]
> 
> 
>> +        goto exit_monitor;
>> +
>> +    if (qemuDomainObjExitMonitor(driver, vm) < 0)
>> +        goto cleanup;
>> +
>> +    if (new_niothreads != exp_niothreads) {
>> +        virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                       _("got wrong number of IOThread ids from QEMU monitor. "
>> +                         "got %d, wanted %d"),
>> +                       new_niothreads, exp_niothreads);
>> +        vm->def->iothreads = new_niothreads;
>> +        goto cleanup;
>> +    }
>> +    vm->def->iothreads = exp_niothreads;
>> +
>> +    if (virDomainNumatuneGetMode(vm->def->numa, -1) ==
>> +        VIR_DOMAIN_NUMATUNE_MEM_STRICT &&
>> +        virDomainNumatuneMaybeFormatNodeset(vm->def->numa,
>> +                                            priv->autoNodeset,
>> +                                            &mem_mask, -1) < 0)
>> +        goto cleanup;
>> +
>> +
>> +    /*
>> +     * If we've successfully added an IOThread, find out where we added it
>> +     * in the QEMU IOThread list, so we can add it to our iothreadids list
>> +     */
> 
> The message seems obvious when looking at the code.
> 
>> +    for (idx = 0; idx < new_niothreads; idx++) {
>> +        if (qemuDomainParseIOThreadAlias(new_iothreads[idx]->name, &idval) < 0)
> 
> ... [1] so that you don't have to do it manually.
> 

IOW: 
    if (STREQ(alias, new_iothreads[idx]->name))
        break

        
>> +            goto cleanup;
>> +        if (iothread_id == idval)
>> +            break;
>> +    }
>> +
>> +    if (idval != iothread_id) {

And of course idx != new_niothreads, plus removing 'idval'

>> +        virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                       _("cannot find new IOThread '%u' in QEMU monitor."),
>> +                       iothread_id);
>> +        goto cleanup;
>> +    }
>> +
>> +    if (virDomainIOThreadIDAdd(vm->def, iothread_id) < 0)
> 
> virDomainIOThreadIDAdd could return the pointer to the created item ...
> 

OK, now we have

    if (!(iothrid = virDomainIOThreadIDAdd(vm->def, iothread_id)))
        goto cleanup;
    
    iothrid->thread_id = new_iothreads[idx]->thread_id;

>> +        goto cleanup;
>> +
>> +    if (!(iothrid = virDomainIOThreadIDFind(vm->def, iothread_id))) {
>> +        virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                       _("cannot find just added IOThread '%u'"),
>> +                       iothread_id);
> 
> So that you don't have to look it up right after adding it.
> 
>> +        goto cleanup;
>> +    }
>> +
>> +    iothrid->thread_id = new_iothreads[idx]->thread_id;
>> +
>> +    /* Add IOThread to cgroup if present */
>> +    if (priv->cgroup) {
>> +        cgroup_iothread =
>> +            qemuDomainAddCgroupForThread(priv->cgroup,
>> +                                         VIR_CGROUP_THREAD_IOTHREAD,
>> +                                         iothread_id, mem_mask,
>> +                                         iothrid->thread_id);
>> +        if (!cgroup_iothread)
>> +            goto cleanup;
>> +    }
>> +
>> +    /* Inherit def->cpuset */
>> +    if (vm->def->cpumask) {
> 
> Automatic NUMA placement(priv->autoCpuset) needs to be taken into account too.
> 

Meaning?  There's a reference for that in qemuDomainAddCgroupForThread.

Obviously I'm following the model of qemuDomainHotplugVcpus when
"if (nvcpus > oldvcpus) {"


>> +        if (qemuDomainHotplugAddPin(vm->def->cpumask, iothread_id,
>> +                                    &vm->def->cputune.iothreadspin,
>> +                                    &vm->def->cputune.niothreadspin) < 0)
>> +
>> +            goto cleanup;
>> +
>> +        if (qemuDomainHotplugPinThread(vm->def->cpumask, iothread_id,
>> +                                       iothrid->thread_id, cgroup_iothread) < 0)
>> +            goto cleanup;
>> +
>> +        if (qemuProcessSetSchedParams(iothread_id, iothrid->thread_id,
>> +                                      vm->def->cputune.niothreadsched,
>> +                                      vm->def->cputune.iothreadsched) < 0)
> 
> qemuProcessSetSchedParams won't do anything since the new thread doesn't
> have any scheduler assigned.
> 

So it's wrong in qemuDomainHotplugVcpus ? Is someone else fixing that?

Is the expectation that I just remove this?

>> +            goto cleanup;
>> +    }
>> +
>> +    ret = 0;
>> +
>> + cleanup:
>> +    if (new_iothreads) {
>> +        for (idx = 0; idx < new_niothreads; idx++)
>> +            qemuMonitorIOThreadInfoFree(new_iothreads[idx]);
>> +        VIR_FREE(new_iothreads);
>> +    }
>> +    VIR_FREE(mem_mask);
>> +    virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
>> +                           "update", rc == 0);
>> +    if (cgroup_iothread)
>> +        virCgroupFree(&cgroup_iothread);
> 
> virCgroupFree() handles NULL just fine.
> 

OK - again copied from qemuDomainHotplugVcpus

>> +    VIR_FREE(alias);
>> +    return ret;
>> +
>> + exit_monitor:
>> +    ignore_value(qemuDomainObjExitMonitor(driver, vm));
>> +    goto cleanup;
>> +}
>> +
>> +static int
>> +qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
>> +                             virDomainObjPtr vm,
>> +                             unsigned int iothread_id)
>> +{
>> +    qemuDomainObjPrivatePtr priv = vm->privateData;
>> +    size_t idx;
>> +    char *alias = NULL;
>> +    int rc = -1;
>> +    int ret = -1;
>> +    unsigned int orig_niothreads = vm->def->iothreads;
>> +    unsigned int exp_niothreads = vm->def->iothreads;
>> +    int new_niothreads = 0;
>> +    qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
>> +    char *mem_mask = NULL;
>> +
>> +    /* Normally would use virDomainIOThreadIDFind, but we need the index
>> +     * from whence to delete for later...
>> +     */
>> +    for (idx = 0; idx < vm->def->niothreadids; idx++) {
>> +        if (iothread_id == vm->def->iothreadids[idx]->iothread_id)
>> +            break;
>> +    }
>> +
>> +    if (idx == vm->def->niothreadids) {
>> +        virReportError(VIR_ERR_INVALID_ARG,
>> +                       _("cannot find IOThread '%u' in iothreadids list"),
>> +                       iothread_id);
>> +        return -1;
>> +    }
>> +
>> +    if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
>> +        return -1;
>> +
>> +    qemuDomainObjEnterMonitor(driver, vm);
>> +
>> +    rc = qemuMonitorDelObject(priv->mon, alias);
>> +    exp_niothreads--;
>> +    if (rc < 0)
>> +        goto exit_monitor;
>> +
>> +    /* After hotplugging the IOThreads we need to re-detect the
>> +     * IOThreads thread_id's, adjust the cgroups, thread affinity,
>> +     * and the vm->def->iothreadids list.
>> +     */
> 
> You've removed the thread here, so thread affinity was destroyed by the
> thread exitting.
> 

relic of me cut-n-paste from formerly combined code.

removed the comment completely, no replacement.

>> +    if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon,
>> +                                                  &new_iothreads)) < 0)
>> +        goto exit_monitor;
>> +
>> +    if (qemuDomainObjExitMonitor(driver, vm) < 0)
>> +        goto cleanup;
>> +
>> +    if (new_niothreads != exp_niothreads) {
>> +        virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                       _("got wrong number of IOThread ids from QEMU monitor. "
>> +                         "got %d, wanted %d"),
>> +                       new_niothreads, exp_niothreads);
>> +        vm->def->iothreads = new_niothreads;
>> +        goto cleanup;
>> +    }
>> +    vm->def->iothreads = exp_niothreads;
>> +
>> +    if (virDomainNumatuneGetMode(vm->def->numa, -1) ==
>> +        VIR_DOMAIN_NUMATUNE_MEM_STRICT &&
>> +        virDomainNumatuneMaybeFormatNodeset(vm->def->numa,
>> +                                            priv->autoNodeset,
>> +                                            &mem_mask, -1) < 0)
> 
> Why do you need the memory node mask when you are deleting the cgroup?
> 

Oh right - relic of the copy...  gone.

>> +        goto cleanup;
>> +
>> +    if (VIR_DELETE_ELEMENT(vm->def->iothreadids, idx,
>> +                           vm->def->niothreadids) < 0)
>> +        goto cleanup;
> 
> You've added virDomainIOThreadIDDel
> 

yep, change to :

    virDomainIOThreadIDDel(vm->def, iothread_id);

>> +
>> +    if (qemuDomainDelCgroupForThread(priv->cgroup,
>> +                                     VIR_CGROUP_THREAD_IOTHREAD,
>> +                                     iothread_id) < 0)
>> +        goto cleanup;
>> +
>> +    virDomainPinDel(&vm->def->cputune.iothreadspin,
>> +                    &vm->def->cputune.niothreadspin,
>> +                    iothread_id);
>> +
>> +    ret = 0;
>> +
>> + cleanup:
>> +    if (new_iothreads) {
>> +        for (idx = 0; idx < new_niothreads; idx++)
>> +            qemuMonitorIOThreadInfoFree(new_iothreads[idx]);
>> +        VIR_FREE(new_iothreads);
>> +    }
>> +    VIR_FREE(mem_mask);
>> +    virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
>> +                           "update", rc == 0);
>> +    VIR_FREE(alias);
>> +    return ret;
>> +
>> + exit_monitor:
>> +    ignore_value(qemuDomainObjExitMonitor(driver, vm));
>> +    goto cleanup;
>> +}
>> +
>> +static int
>> +qemuDomainChgIOThread(virQEMUDriverPtr driver,
>> +                      virDomainObjPtr vm,
>> +                      unsigned int iothread_id,
>> +                      bool add,
>> +                      unsigned int flags)
>> +{
>> +    virQEMUDriverConfigPtr cfg = NULL;
>> +    virCapsPtr caps = NULL;
>> +    qemuDomainObjPrivatePtr priv;
>> +    virCgroupPtr cgroup_temp = NULL;
>> +    virBitmapPtr all_nodes = NULL;
>> +    char *all_nodes_str = NULL;
>> +    char *mem_mask = NULL;
>> +    virDomainDefPtr persistentDef;
>> +    int ret = -1;
>> +
>> +    cfg = virQEMUDriverGetConfig(driver);
>> +
>> +    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
>> +        goto cleanup;
>> +
>> +    priv = vm->privateData;
>> +
>> +    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
>> +        goto cleanup;
>> +
>> +    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
>> +                                        &persistentDef) < 0)
>> +        goto endjob;
>> +
>> +    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
>> +        if (!virDomainObjIsActive(vm)) {
>> +            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
>> +                           _("cannot change IOThreads for an inactive domain"));
>> +            goto endjob;
>> +        }
>> +
>> +        if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
>> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
>> +                           _("IOThreads not supported with this binary"));
>> +            goto endjob;
>> +        }
>> +
>> +        if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
> 
> Wrong cgroup type. Additionally qemuDomainHotplugAddIOThread() will add
> the thread so adding it here doesn't make sense.
> 

See qemuDomainSetVcpusFlags, it too uses VIR_CGROUP_THREAD_EMULATOR so this
is no different... In fact I suppose I could have created some sort of common
API, but didn't.

One thing I just noticed - commit id '6cf1e11' added a "&& virNumaIsAvailable()"
check in qemuDomainSetVcpusFlags, so I suppose to follow that - I can add
the extra check.

Beyond that I'm not sure what you want.


>> +                               false, &cgroup_temp) < 0)
>> +            goto endjob;
>> +
>> +        if (!(all_nodes = virNumaGetHostNodeset()))
>> +            goto endjob;
>> +
>> +        if (!(all_nodes_str = virBitmapFormat(all_nodes)))
>> +            goto endjob;
>> +
>> +        if (virCgroupGetCpusetMems(cgroup_temp, &mem_mask) < 0 ||
>> +            virCgroupSetCpusetMems(cgroup_temp, all_nodes_str) < 0)
>> +            goto endjob;
>> +
>> +        if (add) {
>> +            if (qemuDomainHotplugAddIOThread(driver, vm, iothread_id) < 0)
>> +                goto endjob;
>> +        } else {
>> +            if (qemuDomainHotplugDelIOThread(driver, vm, iothread_id) < 0)
>> +                goto endjob;
>> +        }
>> +
>> +        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
>> +            goto endjob;
>> +    }
>> +
>> +    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
>> +        if (add) {
>> +            if (virDomainIOThreadIDAdd(persistentDef, iothread_id) < 0)
>> +                goto endjob;
>> +
>> +            /* Nothing to do in iothreadspin list (that's a separate command) */
>> +
>> +            persistentDef->iothreads++;
>> +        } else {
>> +            if (!virDomainIOThreadIDFind(persistentDef, iothread_id)) {
>> +                virReportError(VIR_ERR_INVALID_ARG,
>> +                               _("cannot find IOThread '%u' in persistent "
>> +                                 "iothreadids"),
>> +                               iothread_id);
>> +                goto cleanup;
>> +            }
>> +
>> +            virDomainIOThreadIDDel(persistentDef, iothread_id);
>> +            virDomainPinDel(&persistentDef->cputune.iothreadspin,
>> +                            &persistentDef->cputune.niothreadspin,
>> +                            iothread_id);
> 
> This is the reason why I've requested in the previous review that the
> pinning information would be merged into the iothread data structure.
> You then would not have to synchronise two data structures.
> 

Understood ...  I started down that path, but then got bogged down in cputune
information inside iothreadid's and the difference with the vCPU code.  So I
kept it this way to reduce the number of changes.

I think it's worthy of being done, but I hope a follow-up patch will be acceptable. 

>> +            persistentDef->iothreads--;
>> +        }
>> +
>> +        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
>> +            goto endjob;
>> +    }
>> +
>> +    ret = 0;
>> +
>> + endjob:
>> +    if (mem_mask) {
>> +        virErrorPtr err = virSaveLastError();
>> +        virCgroupSetCpusetMems(cgroup_temp, mem_mask);
>> +        virSetError(err);
>> +        virFreeError(err);
>> +    }
>> +    qemuDomainObjEndJob(driver, vm);
>> +
>> + cleanup:
>> +    VIR_FREE(mem_mask);
>> +    VIR_FREE(all_nodes_str);
>> +    virBitmapFree(all_nodes);
>> +    virCgroupFree(&cgroup_temp);
>> +    virObjectUnref(caps);
>> +    virObjectUnref(cfg);
>> +    return ret;
>> +}
>> +
>> +static int
>> +qemuDomainAddIOThread(virDomainPtr dom,
>> +                      unsigned int iothread_id,
>> +                      unsigned int flags)
>> +{
>> +    virQEMUDriverPtr driver = dom->conn->privateData;
>> +    virDomainObjPtr vm = NULL;
>> +    int ret = -1;
>> +
>> +    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
>> +                  VIR_DOMAIN_AFFECT_CONFIG, -1);
>> +
>> +    if (!(vm = qemuDomObjFromDomain(dom)))
>> +        goto cleanup;
>> +
>> +    if (virDomainAddIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
>> +        goto cleanup;
>> +
>> +    ret = qemuDomainChgIOThread(driver, vm, iothread_id, true, flags);
>> +
>> + cleanup:
>> +    qemuDomObjEndAPI(&vm);
>> +    return ret;
>> +}
>> +
>> +
>> +static int
>> +qemuDomainDelIOThread(virDomainPtr dom,
>> +                      unsigned int iothread_id,
>> +                      unsigned int flags)
>> +{
>> +    virQEMUDriverPtr driver = dom->conn->privateData;
>> +    virDomainObjPtr vm = NULL;
>> +    int ret = -1;
>> +    size_t i;
>> +
>> +    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
>> +                  VIR_DOMAIN_AFFECT_CONFIG, -1);
>> +
>> +    if (!(vm = qemuDomObjFromDomain(dom)))
>> +        goto cleanup;
>> +
>> +    if (virDomainDelIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
>> +           goto cleanup;
>> +
>> +    /* If there is a disk using the IOThread to be removed, then fail. */
>> +    for (i = 0; i < vm->def->ndisks; i++) {
>> +        if (vm->def->disks[i]->iothread == iothread_id) {
>> +            virReportError(VIR_ERR_INVALID_ARG,
>> +                           _("cannot remove IOThread %u since it "
>> +                             "is being used by disk path '%s'"),
>> +                           iothread_id,
>> +                           NULLSTR(vm->def->disks[i]->src->path));
> 
> Alternatively you can use vm->def->disks[i]->dst which should be always
> set.
> 
OK

>> +            goto cleanup;
>> +        }
>> +    }
>> +
>> +    ret = qemuDomainChgIOThread(driver, vm, iothread_id, false, flags);
>> +
>> + cleanup:
>> +    qemuDomObjEndAPI(&vm);
>> +    return ret;
>> +}
>> +
>>  static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
>>  {
>>      virQEMUDriverPtr driver = dom->conn->privateData;

So with all that the changes that would be sqashed in:

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5d3c7fc..e1fdeb5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6188,7 +6188,6 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
     unsigned int exp_niothreads = vm->def->iothreads;
     int new_niothreads = 0;
     qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
-    unsigned int idval = 0;
     virCgroupPtr cgroup_iothread = NULL;
     char *mem_mask = NULL;
     virDomainIOThreadIDDefPtr iothrid;
@@ -6244,29 +6243,20 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
      * in the QEMU IOThread list, so we can add it to our iothreadids list
      */
     for (idx = 0; idx < new_niothreads; idx++) {
-        if (qemuDomainParseIOThreadAlias(new_iothreads[idx]->name, &idval) < 0)
-            goto cleanup;
-        if (iothread_id == idval)
+        if (STREQ(new_iothreads[idx]->name, alias))
             break;
     }
 
-    if (idval != iothread_id) {
+    if (idx != new_niothreads) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find new IOThread '%u' in QEMU monitor."),
                        iothread_id);
         goto cleanup;
     }
 
-    if (virDomainIOThreadIDAdd(vm->def, iothread_id) < 0)
+    if (!(iothrid = virDomainIOThreadIDAdd(vm->def, iothread_id)))
         goto cleanup;
 
-    if (!(iothrid = virDomainIOThreadIDFind(vm->def, iothread_id))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("cannot find just added IOThread '%u'"),
-                       iothread_id);
-        goto cleanup;
-    }
-
     iothrid->thread_id = new_iothreads[idx]->thread_id;
 
     /* Add IOThread to cgroup if present */
@@ -6309,8 +6299,7 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
     VIR_FREE(mem_mask);
     virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
                            "update", rc == 0);
-    if (cgroup_iothread)
-        virCgroupFree(&cgroup_iothread);
+    virCgroupFree(&cgroup_iothread);
     VIR_FREE(alias);
     return ret;
 
@@ -6333,7 +6322,6 @@ qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
     unsigned int exp_niothreads = vm->def->iothreads;
     int new_niothreads = 0;
     qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
-    char *mem_mask = NULL;
 
     /* Normally would use virDomainIOThreadIDFind, but we need the index
      * from whence to delete for later...
@@ -6360,10 +6348,6 @@ qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
     if (rc < 0)
         goto exit_monitor;
 
-    /* After hotplugging the IOThreads we need to re-detect the
-     * IOThreads thread_id's, adjust the cgroups, thread affinity,
-     * and the vm->def->iothreadids list.
-     */
     if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon,
                                                   &new_iothreads)) < 0)
         goto exit_monitor;
@@ -6381,16 +6365,7 @@ qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
     }
     vm->def->iothreads = exp_niothreads;
 
-    if (virDomainNumatuneGetMode(vm->def->numa, -1) ==
-        VIR_DOMAIN_NUMATUNE_MEM_STRICT &&
-        virDomainNumatuneMaybeFormatNodeset(vm->def->numa,
-                                            priv->autoNodeset,
-                                            &mem_mask, -1) < 0)
-        goto cleanup;
-
-    if (VIR_DELETE_ELEMENT(vm->def->iothreadids, idx,
-                           vm->def->niothreadids) < 0)
-        goto cleanup;
+    virDomainIOThreadIDDel(vm->def, iothread_id);
 
     if (qemuDomainDelCgroupForThread(priv->cgroup,
                                      VIR_CGROUP_THREAD_IOTHREAD,
@@ -6409,7 +6384,6 @@ qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
             qemuMonitorIOThreadInfoFree(new_iothreads[idx]);
         VIR_FREE(new_iothreads);
     }
-    VIR_FREE(mem_mask);
     virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
                            "update", rc == 0);
     VIR_FREE(alias);
@@ -6464,19 +6438,21 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
             goto endjob;
         }
 
-        if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
-                               false, &cgroup_temp) < 0)
-            goto endjob;
+        if (virNumaIsAvailable()) {
+            if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
+                                   false, &cgroup_temp) < 0)
+                goto endjob;
 
-        if (!(all_nodes = virNumaGetHostNodeset()))
-            goto endjob;
+            if (!(all_nodes = virNumaGetHostNodeset()))
+                goto endjob;
 
-        if (!(all_nodes_str = virBitmapFormat(all_nodes)))
-            goto endjob;
+            if (!(all_nodes_str = virBitmapFormat(all_nodes)))
+                goto endjob;
 
-        if (virCgroupGetCpusetMems(cgroup_temp, &mem_mask) < 0 ||
-            virCgroupSetCpusetMems(cgroup_temp, all_nodes_str) < 0)
-            goto endjob;
+            if (virCgroupGetCpusetMems(cgroup_temp, &mem_mask) < 0 ||
+                virCgroupSetCpusetMems(cgroup_temp, all_nodes_str) < 0)
+                goto endjob;
+        }
 
         if (add) {
             if (qemuDomainHotplugAddIOThread(driver, vm, iothread_id) < 0)
@@ -6492,7 +6468,7 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
 
     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
         if (add) {
-            if (virDomainIOThreadIDAdd(persistentDef, iothread_id) < 0)
+            if (!virDomainIOThreadIDAdd(persistentDef, iothread_id))
                 goto endjob;
 
             /* Nothing to do in iothreadspin list (that's a separate command) */
@@ -6590,8 +6566,7 @@ qemuDomainDelIOThread(virDomainPtr dom,
             virReportError(VIR_ERR_INVALID_ARG,
                            _("cannot remove IOThread %u since it "
                              "is being used by disk path '%s'"),
-                           iothread_id,
-                           NULLSTR(vm->def->disks[i]->src->path));
+                           iothread_id, vm->def->disks[i]->dst);
             goto cleanup;
         }
     }




More information about the libvir-list mailing list