提交 7e490cda 编写于 作者: L Laine Stump

conf: utility function to update entry in def->nets array

A virDomainNetDef object in a domain's nets array might contain a
virDomainHostdevDef, and when this is the case, the domain's hostdevs
array will also have a pointer to this embedded hostdev (this is done
so that internal functions that need to perform some operation on all
hostdevs won't leave out the type='hostdev' network interfaces).

When a network device was updated with virDomainUpdateDeviceFlags(),
we were replacing the entry in the nets array (and free'ing the
original) but forgetting about the pointer in the hostdevs array
(which would then point to the now-free'd hostdev contained in the old
net object.) This often resulted in a libvirtd crash.

The solution is to add a function, virDomainNetUpdate(), called by
qemuDomainUpdateDeviceConfig(), that updates the hostdevs array
appropriately along with the nets array.

Resolves: https://bugzilla.redhat.com/1558934Signed-off-by: NLaine Stump <laine@redhat.com>
Reviewed-by: NMichal Privoznik <mprivozn@redhat.com>
上级 4e9d72be
......@@ -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)
{
......
......@@ -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);
......
......@@ -508,6 +508,7 @@ virDomainNetSetModelString;
virDomainNetTypeFromString;
virDomainNetTypeSharesHostView;
virDomainNetTypeToString;
virDomainNetUpdate;
virDomainNostateReasonTypeFromString;
virDomainNostateReasonTypeToString;
virDomainObjAssignDef;
......
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册