diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c290baf953..7d83a3d1c6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -17169,6 +17169,47 @@ virDomainNetRemove(virDomainDefPtr def, size_t i) return net; } + +int +virDomainNetUpdate(virDomainDefPtr def, + size_t netidx, + virDomainNetDefPtr newnet) +{ + size_t hostdevidx; + virDomainNetDefPtr oldnet = def->nets[netidx]; + virDomainHostdevDefPtr oldhostdev = virDomainNetGetActualHostdev(oldnet); + virDomainHostdevDefPtr newhostdev = virDomainNetGetActualHostdev(newnet); + + /* + * if newnet or oldnet has a valid hostdev*, we need to update the + * hostdevs list + */ + if (oldhostdev) { + for (hostdevidx = 0; hostdevidx < def->nhostdevs; hostdevidx++) { + if (def->hostdevs[hostdevidx] == oldhostdev) + break; + } + } + + if (oldhostdev && hostdevidx < def->nhostdevs) { + if (newhostdev) { + /* update existing entry in def->hostdevs */ + def->hostdevs[hostdevidx] = newhostdev; + } else { + /* delete oldhostdev from def->hostdevs */ + virDomainHostdevRemove(def, hostdevidx); + } + } else if (newhostdev) { + /* add newhostdev to end of def->hostdevs */ + if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, newhostdev) < 0) + return -1; + } + + def->nets[netidx] = newnet; + return 0; +} + + int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 53bdee22fb..2884af49d8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3174,6 +3174,7 @@ virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device); virDomainNetDefPtr virDomainNetFindByName(virDomainDefPtr def, const char *ifname); bool virDomainHasNet(virDomainDefPtr def, virDomainNetDefPtr net); int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net); +int virDomainNetUpdate(virDomainDefPtr def, size_t netidx, virDomainNetDefPtr newnet); virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i); void virDomainNetRemoveHostdev(virDomainDefPtr def, virDomainNetDefPtr net); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 287e63bffa..2b10a1030e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -508,6 +508,7 @@ virDomainNetSetModelString; virDomainNetTypeFromString; virDomainNetTypeSharesHostView; virDomainNetTypeToString; +virDomainNetUpdate; virDomainNostateReasonTypeFromString; virDomainNostateReasonTypeToString; virDomainObjAssignDef; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 5453f49064..cf1dd1428e 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3486,8 +3486,10 @@ lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef, false) < 0) return -1; - virDomainNetDefFree(vmdef->nets[idx]); - vmdef->nets[idx] = net; + if (virDomainNetUpdate(vmdef, idx, net) < 0) + return -1; + + virDomainNetDefFree(oldDev.data.net); dev->data.net = NULL; ret = 0; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0c65414a1a..286f5bd984 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -8786,8 +8786,10 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, false) < 0) return -1; - virDomainNetDefFree(vmdef->nets[pos]); - vmdef->nets[pos] = net; + if (virDomainNetUpdate(vmdef, pos, net)) + return -1; + + virDomainNetDefFree(oldDev.data.net); dev->data.net = NULL; break;