[libvirt] [PATCH] qemu: fix EFI nvram removal on domain undefine
Pavel Mores
pmores at redhat.com
Tue Oct 15 13:15:12 UTC 2019
On Tue, Oct 15, 2019 at 01:51:32PM +0200, Michal Privoznik wrote:
> On 10/15/19 10:31 AM, Pavel Mores wrote:
> > When undefining a UEFI domain its nvram file has to be properly handled as
> > well. It's mandatory to use one of --nvram and --keep-nvram options when
> > 'virsh undefine <domain>' is issued for a UEFI domain. To fix the bug as
> > reported, virsh should return an error message if neither option is used
> > and the nvram file should be removed when --nvram is given.
> >
> > The cause of the problem is that when qemuDomainUndefineFlags() is invoked
> > on an inactive domain the path to its nvram file is empty. This commit
> > aims to fix this by formatting and filling in the path in time for the
> > nvram removal code to run properly.
> >
> > https://bugzilla.redhat.com/show_bug.cgi?id=1751596
> >
> > Signed-off-by: Pavel Mores <pmores at redhat.com>
> > ---
> > src/qemu/qemu_domain.c | 12 +++++++++---
> > src/qemu/qemu_domain.h | 4 ++++
> > src/qemu/qemu_driver.c | 20 +++++++++++++++-----
> > 3 files changed, 28 insertions(+), 8 deletions(-)
> >
> > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> > index 35067c851f..1a0367cc27 100644
> > --- a/src/qemu/qemu_domain.c
> > +++ b/src/qemu/qemu_domain.c
> > @@ -15441,16 +15441,22 @@ qemuDomainDiskIsMissingLocalOptional(virDomainDiskDefPtr disk)
> > }
> > +int
> > +qemuDomainNVRAMPathFormat(virQEMUDriverConfigPtr cfg,
> > + virDomainDefPtr def, char **path)
> > +{
> > + return virAsprintf(path, "%s/%s_VARS.fd", cfg->nvramDir, def->name);
> > +}
> > +
>
> We have two empty lines between functions in this file. And Also, one
> argument per line please.
>
> > int
> > qemuDomainNVRAMPathGenerate(virQEMUDriverConfigPtr cfg,
> > virDomainDefPtr def)
> > {
> > if (def->os.loader &&
> > def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
> > - def->os.loader->readonly == VIR_TRISTATE_SWITCH_ON &&
> > + def->os.loader->readonly == VIR_TRISTATE_BOOL_YES &&
> > !def->os.loader->nvram) {
> > - return virAsprintf(&def->os.loader->nvram, "%s/%s_VARS.fd",
> > - cfg->nvramDir, def->name);
> > + return qemuDomainNVRAMPathFormat(cfg, def, &def->os.loader->nvram);
> > }
> > return 0;
> > diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> > index 01a54d4265..07725c7cc4 100644
> > --- a/src/qemu/qemu_domain.h
> > +++ b/src/qemu/qemu_domain.h
> > @@ -1207,6 +1207,10 @@ qemuDomainIsUsingNoShutdown(qemuDomainObjPrivatePtr priv);
> > bool
> > qemuDomainDiskIsMissingLocalOptional(virDomainDiskDefPtr disk);
> > +int
> > +qemuDomainNVRAMPathFormat(virQEMUDriverConfigPtr cfg,
> > + virDomainDefPtr def, char **path);
> > +
> > int
> > qemuDomainNVRAMPathGenerate(virQEMUDriverConfigPtr cfg,
> > virDomainDefPtr def);
> > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> > index bc0ede2fb0..dcaadbdb52 100644
> > --- a/src/qemu/qemu_driver.c
> > +++ b/src/qemu/qemu_driver.c
> > @@ -7828,6 +7828,8 @@ qemuDomainUndefineFlags(virDomainPtr dom,
> > int nsnapshots;
> > int ncheckpoints;
> > virQEMUDriverConfigPtr cfg = NULL;
> > + char *nvram_path = NULL;
> > + bool need_deallocate_nvram_path = false;
>
> While this works, I'd rather have @nvram_path autofreed, and ... [1]
>
> > virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
> > VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
> > @@ -7905,14 +7907,20 @@ qemuDomainUndefineFlags(virDomainPtr dom,
> > }
> > }
> > - if (vm->def->os.loader &&
> > - vm->def->os.loader->nvram &&
> > - virFileExists(vm->def->os.loader->nvram)) {
> > + if (vm->def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) {
> > + qemuDomainNVRAMPathFormat(cfg, vm->def, &nvram_path);
>
> This needs a check for retval.
>
> > + need_deallocate_nvram_path = true;
> > + } else {
> > + if (vm->def->os.loader)
> > + nvram_path = vm->def->os.loader->nvram;
>
> 1: ... duplicate path here.
>
> > + }
> > +
> > + if (nvram_path && virFileExists(nvram_path)) {
> > if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
> > - if (unlink(vm->def->os.loader->nvram) < 0) {
> > + if (unlink(nvram_path) < 0) {
> > virReportSystemError(errno,
> > _("failed to remove nvram: %s"),
> > - vm->def->os.loader->nvram);
> > + nvram_path);
> > goto endjob;
> > }
> > } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
> > @@ -7948,6 +7956,8 @@ qemuDomainUndefineFlags(virDomainPtr dom,
> > virDomainObjEndAPI(&vm);
> > virObjectEventStateQueue(driver->domainEventState, event);
> > virObjectUnref(cfg);
> > + if (need_deallocate_nvram_path)
> > + VIR_FREE(nvram_path);
> > return ret;
> > }
> >
>
> Reviewed-by: Michal Privoznik <mprivozn at redhat.com> and pushed.
Cheers! One question though - the pushed version duplicates the path as you
mention in [1] above, and if the strdup fails it does 'goto endjob'. This
means that a failure in an avoidable string copy operation might make the whole
domain undefinition fail, making this formulation slightly less robust I
believe.
Now, this is probably mostly theoretical, with no effect in practice. I
thought though I'd mention it in case there was a corner case after all where
this could make a difference.
Thanks,
pvl
More information about the libvir-list
mailing list