virDomainDiskDefPtr disk;
virStorageSourcePtr baseSource = NULL;
unsigned int baseIndex = 0;
+ char *basePath = NULL;
+ char *backingPath = NULL;
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
goto cleanup;
}
+ if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("flag VIR_DOMAIN_BLOCK_REBASE_RELATIVE is valid only "
+ "with non-null base"));
+ goto cleanup;
+ }
+
priv = vm->privateData;
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC)) {
async = true;
base, baseIndex, NULL))))
goto endjob;
+ if (baseSource) {
+ if (qemuGetDriveSourceString(baseSource, NULL, &basePath) < 0)
+ goto endjob;
+
+ if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHANGE_BACKING_FILE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this QEMU binary doesn't support relative "
+ "block pull/rebase"));
+ goto endjob;
+ }
+
+ if (virStorageFileGetRelativeBackingPath(disk->src->backingStore,
+ baseSource,
+ &backingPath) < 0)
+ goto endjob;
+
+
+ if (!backingPath) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("can't keep relative backing relationship"));
+ goto endjob;
+ }
+ }
+ }
+
qemuDomainObjEnterMonitor(driver, vm);
- ret = qemuMonitorBlockJob(priv->mon, device,
- baseIndex ? baseSource->path : base,
- NULL, bandwidth, info, mode, async);
+ ret = qemuMonitorBlockJob(priv->mon, device, basePath, backingPath,
+ bandwidth, info, mode, async);
qemuDomainObjExitMonitor(driver, vm);
if (ret < 0)
goto endjob;
}
cleanup:
+ VIR_FREE(basePath);
+ VIR_FREE(backingPath);
VIR_FREE(device);
if (vm)
virObjectUnlock(vm);
virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
VIR_DOMAIN_BLOCK_REBASE_COPY |
- VIR_DOMAIN_BLOCK_REBASE_COPY_RAW, -1);
+ VIR_DOMAIN_BLOCK_REBASE_COPY_RAW |
+ VIR_DOMAIN_BLOCK_REBASE_RELATIVE, -1);
if (!(vm = qemuDomObjFromDomain(dom)))
return -1;