when appropriate, of course. If the config for a domain specifies boot
order with <boot dev='blah'/> elements, e.g.:
<os>
...
<boot dev='hd'/>
<boot dev='network'/>
</os>
Then the first disk device in the config will have ",bootindex=1"
appended to its qemu commandline -device options, and the first (and
*only* the first) network interface device will get ",bootindex=2".
However, if the first network interface device is a "hostdev" device
(an SRIOV Virtual Function (VF) being assigned to the domain with
vfio), then the bootindex option will *not* be appended. This happens
because the bootindex=n option corresponding to the order of "<boot
dev='network'/>" is added to the -device for the first network device
when network device commandline args are constructed, but if it's a
hostdev network device, its commandline arg is instead constructed in
the loop for hostdevs.
This patch fixes that omission by noticing (in bootHostdevNet) if the
first network device was a hostdev, and if so passing on the proper
bootindex to the commandline generator for hostdev devices - the
result is that ",bootindex=2" will be properly appended to the first
"network" device in the config even if it is really a hostdev
(including if it is assigned from a libvirt network pool). (note that
this is only the case if there is no <bootmenu enabled='yes'/> element
in the config ("-boot menu-on" in qemu) , since the two are mutually
exclusive - when the bootmenu is enabled, the individual per-device
bootindex options can't be used by qemu, and we revert to using "-boot
order=xyz" instead).
If a greater level of control over boot order is desired (e.g., more
than one network device should be tried, or a network device other
than the first one encountered in the config), then <boot
dev='network'/> in the <os> element should not be used; instead, the
individual device elements in the config should be given a "<boot
order='n'/>
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1278421
---
src/qemu/qemu_command.c | 31 ++++++++++++++++++++++++++++---
src/qemu/qemu_command.h | 1 +
src/qemu/qemu_hotplug.c | 4 ++--
3 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4d00fd9..183ab97 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5978,6 +5978,7 @@ qemuOpenPCIConfig(virDomainHostdevDefPtr dev)
char *
qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
virDomainHostdevDefPtr dev,
+ int bootIndex, /* used iff dev->info->bootIndex == 0 */
const char *configfd,
virQEMUCapsPtr qemuCaps)
{
@@ -6020,7 +6021,9 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
pcisrc->addr.function);
virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
if (dev->info->bootIndex)
- virBufferAsprintf(&buf, ",bootindex=%d",
dev->info->bootIndex);
+ bootIndex = dev->info->bootIndex;
+ if (bootIndex)
+ virBufferAsprintf(&buf, ",bootindex=%d", bootIndex);
if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
goto error;
if (qemuBuildRomStr(&buf, dev->info, qemuCaps) < 0)
@@ -9166,7 +9169,8 @@ qemuBuildCommandLine(virConnectPtr conn,
char *boot_order_str = NULL, *boot_opts_str = NULL;
virBuffer fdc_opts = VIR_BUFFER_INITIALIZER;
char *fdc_opts_str = NULL;
- int bootCD = 0, bootFloppy = 0, bootDisk = 0;
+ int bootCD = 0, bootFloppy = 0, bootDisk = 0, bootHostdevNet = 0;
+
VIR_DEBUG("conn=%p driver=%p def=%p mon=%p json=%d "
"qemuCaps=%p migrateURI=%s snapshot=%p vmop=%d",
@@ -10154,6 +10158,16 @@ qemuBuildCommandLine(virConnectPtr conn,
goto error;
last_good_net = i;
+ /* if this interface is a type='hostdev' interface and we
+ * haven't yet added a "bootindex" parameter to an
+ * emulated network device, save the bootindex - hostdev
+ * interface commandlines will be built later on when we
+ * cycle through all the hostdevs, and we'll use it then.
+ */
+ if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+ bootHostdevNet == 0) {
+ bootHostdevNet = bootNet;
+ }
bootNet = 0;
}
}
@@ -10871,6 +10885,16 @@ qemuBuildCommandLine(virConnectPtr conn,
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
char *configfd_name = NULL;
+ int bootIndex = hostdev->info->bootIndex;
+
+ /* bootNet will be non-0 if boot order was set and no other
+ * net devices were encountered
+ */
+ if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+ bootIndex == 0) {
+ bootIndex = bootHostdevNet;
+ bootHostdevNet = 0;
+ }
if ((backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) &&
virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) {
int configfd = qemuOpenPCIConfig(hostdev);
@@ -10886,7 +10910,8 @@ qemuBuildCommandLine(virConnectPtr conn,
}
}
virCommandAddArg(cmd, "-device");
- devstr = qemuBuildPCIHostdevDevStr(def, hostdev, configfd_name,
qemuCaps);
+ devstr = qemuBuildPCIHostdevDevStr(def, hostdev, bootIndex,
+ configfd_name, qemuCaps);
VIR_FREE(configfd_name);
if (!devstr)
goto error;
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index bebdd27..c773b8f 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -180,6 +180,7 @@ char *qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev,
/* Current, best practice */
char *qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
virDomainHostdevDefPtr dev,
+ int bootIndex,
const char *configfd,
virQEMUCapsPtr qemuCaps);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 8804d3d..872ebcd 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1321,8 +1321,8 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
goto error;
}
- if (!(devstr = qemuBuildPCIHostdevDevStr(vm->def, hostdev, configfd_name,
- priv->qemuCaps)))
+ if (!(devstr = qemuBuildPCIHostdevDevStr(vm->def, hostdev, 0,
+ configfd_name, priv->qemuCaps)))
goto error;
qemuDomainObjEnterMonitor(driver, vm);
--
2.4.3