A bug will be hitted with libvirt+qemu+kvm when doing follow steps:
1.initial status :vm = base+z(z is a snapshot)
2. call snapshotCreateXML( ): vm = base+z +z'
3. call blockRebase( ): vm = base+z''(z rebase to z')
4.(after rebasing work done) vm shutdown and then start
an error occured like this:
"unable to set user and group to '0:0' on '
/path/to/disk': No such file or directory
A second start may sucess.
The error message reported by virSecurityDACSetSecurityDiskLabel
when the disk chain is misused(that is base+z +z', after rebase,
but z' was deleted yet).virSecurityDACSetSecurityDiskLabel used
an old disk chain after rebasing.
In qemuProcessHandleBlockJob when rebase complete, the disk chain
in vm->def is updated but vm->newDef is not(when vm->newDef is not
null). In shutdown( actrully in qemuProcessStop ), if vm->newDef
is not null , vm->def will be replaced by vm->newDef, which
contains a wrong disk chain!!! Then the next start will failed with
above message.
To fix it, update disk chain in vm->newDef in qemuProcessHandleBlockJob.
Signed-off-by: Weiwei Li <nuonuoli(a)tencent.com>
---
src/qemu/qemu_process.c | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 24e5f0f..0491249 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1033,6 +1033,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon
ATTRIBUTE_UNUSED,
virDomainDiskDefPtr disk;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainDiskDefPtr persistDisk = NULL;
+ virDomainDiskDefPtr newDisk = NULL;
bool save = false;
virObjectLock(vm);
@@ -1101,6 +1102,32 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon
ATTRIBUTE_UNUSED,
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
true, true));
+ /* Chang vm->newDef disk chain */
+ if (!persistDisk && vm->newDef){
+ int indx = virDomainDiskIndexByName(vm->newDef,
+ disk->dst,
+ false);
+ virStorageSourcePtr copy = NULL;
+
+ if (indx >=0){
+ newDisk = vm->newDef->disks[indx];
+ copy = virStorageSourceCopy(disk->src, false);
+ if (virStorageSourceInitChainElement(copy,
+ newDisk->src,
+ false) < 0) {
+ VIR_WARN("Unable to update newDef definition "
+ "on vm %s after block job",
+ vm->def->name);
+ virStorageSourceFree(copy);
+ copy = NULL;
+ newDisk = NULL;
+ }
+ }
+ if (copy){
+ virStorageSourceFree(newDisk->src);
+ newDisk->src = copy;
+ }
+ }
} else if (disk->mirror &&
(type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY ||
type == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT)) {
--
1.7.1