---
src/qemu/qemu_blockjob.c | 13 +++++++++++--
src/qemu/qemu_blockjob.h | 3 ++-
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 4 ++--
src/qemu/qemu_migration.c | 34 ++++++++++++++++++++++------------
src/qemu/qemu_monitor.c | 5 +++--
src/qemu/qemu_monitor.h | 4 +++-
src/qemu/qemu_monitor_json.c | 2 +-
src/qemu/qemu_process.c | 3 +++
9 files changed, 48 insertions(+), 21 deletions(-)
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 83a5a3f..937d931 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -33,6 +33,7 @@
#include "virstoragefile.h"
#include "virthread.h"
#include "virtime.h"
+#include "viralloc.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -53,16 +54,24 @@ VIR_LOG_INIT("qemu.qemu_blockjob");
int
qemuBlockJobUpdate(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- virDomainDiskDefPtr disk)
+ virDomainDiskDefPtr disk,
+ char **error)
{
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
int status = diskPriv->blockJobStatus;
+ if (error)
+ *error = NULL;
+
if (status != -1) {
qemuBlockJobEventProcess(driver, vm, disk,
diskPriv->blockJobType,
diskPriv->blockJobStatus);
diskPriv->blockJobStatus = -1;
+ if (error)
+ VIR_STEAL_PTR(*error, diskPriv->blockJobHint);
+ else
+ VIR_FREE(diskPriv->blockJobHint);
}
return status;
@@ -241,6 +250,6 @@ qemuBlockJobSyncEnd(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk)
{
VIR_DEBUG("disk=%s", disk->dst);
- qemuBlockJobUpdate(driver, vm, disk);
+ qemuBlockJobUpdate(driver, vm, disk, NULL);
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockJobSync = false;
}
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index 775ce95..c452edc 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -27,7 +27,8 @@
int qemuBlockJobUpdate(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- virDomainDiskDefPtr disk);
+ virDomainDiskDefPtr disk,
+ char **error);
void qemuBlockJobEventProcess(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDiskDefPtr disk,
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 521531b..79d88fa 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -290,6 +290,7 @@ struct _qemuDomainDiskPrivate {
/* for some synchronous block jobs, we need to notify the owner */
int blockJobType; /* type of the block job from the event */
int blockJobStatus; /* status of the finished block job */
+ char *blockJobHint; /* hint from block job event (like error message) */
bool blockJobSync; /* the block job needs synchronized termination */
bool migrating; /* the disk is being migrated */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ee16cb5..ac204c3 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -16280,13 +16280,13 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
VIR_DOMAIN_BLOCK_JOB_CANCELED);
} else {
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
- qemuBlockJobUpdate(driver, vm, disk);
+ qemuBlockJobUpdate(driver, vm, disk, NULL);
while (diskPriv->blockjob) {
if (virDomainObjWait(vm) < 0) {
ret = -1;
goto endjob;
}
- qemuBlockJobUpdate(driver, vm, disk);
+ qemuBlockJobUpdate(driver, vm, disk, NULL);
}
}
}
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 8a220d9..0671e23 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1853,17 +1853,20 @@ qemuMigrationDriveMirrorReady(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+ char *error;
if (!diskPriv->migrating)
continue;
- status = qemuBlockJobUpdate(driver, vm, disk);
+ status = qemuBlockJobUpdate(driver, vm, disk, &error);
if (status == VIR_DOMAIN_BLOCK_JOB_FAILED) {
virReportError(VIR_ERR_OPERATION_FAILED,
- _("migration of disk %s failed"),
- disk->dst);
+ _("migration of disk %s failed: %s"),
+ disk->dst, NULLSTR(error));
+ VIR_FREE(error);
return -1;
}
+ VIR_FREE(error);
if (disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_READY)
notReady++;
@@ -1902,17 +1905,18 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+ char *error;
if (!diskPriv->migrating)
continue;
- status = qemuBlockJobUpdate(driver, vm, disk);
+ status = qemuBlockJobUpdate(driver, vm, disk, &error);
switch (status) {
case VIR_DOMAIN_BLOCK_JOB_FAILED:
if (check) {
virReportError(VIR_ERR_OPERATION_FAILED,
- _("migration of disk %s failed"),
- disk->dst);
+ _("migration of disk %s failed: %s"),
+ disk->dst, NULLSTR(error));
failed = true;
}
/* fallthrough */
@@ -1925,6 +1929,7 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
default:
active++;
}
+ VIR_FREE(error);
}
if (failed) {
@@ -1962,24 +1967,28 @@ qemuMigrationCancelOneDriveMirror(virQEMUDriverPtr driver,
{
qemuDomainObjPrivatePtr priv = vm->privateData;
char *diskAlias = NULL;
+ char *error;
int ret = -1;
int status;
int rv;
- status = qemuBlockJobUpdate(driver, vm, disk);
+ status = qemuBlockJobUpdate(driver, vm, disk, &error);
switch (status) {
case VIR_DOMAIN_BLOCK_JOB_FAILED:
case VIR_DOMAIN_BLOCK_JOB_CANCELED:
if (failNoJob) {
virReportError(VIR_ERR_OPERATION_FAILED,
- _("migration of disk %s failed"),
- disk->dst);
- return -1;
+ _("migration of disk %s failed: %s"),
+ disk->dst, NULLSTR(error));
+ ret = -1;
+ goto cleanup;
}
- return 1;
+ ret = 1;
+ goto cleanup;
case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
- return 1;
+ ret = 1;
+ goto cleanup;
}
if (!(diskAlias = qemuAliasFromDisk(disk)))
@@ -1997,6 +2006,7 @@ qemuMigrationCancelOneDriveMirror(virQEMUDriverPtr driver,
cleanup:
VIR_FREE(diskAlias);
+ VIR_FREE(error);
return ret;
}
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 8083a36..3466225 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1458,13 +1458,14 @@ int
qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
const char *diskAlias,
int type,
- int status)
+ int status,
+ const char *hint)
{
int ret = -1;
VIR_DEBUG("mon=%p", mon);
QEMU_MONITOR_CALLBACK(mon, ret, domainBlockJob, mon->vm,
- diskAlias, type, status);
+ diskAlias, type, status, hint);
return ret;
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 7d78e5b..a5d8181 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -146,6 +146,7 @@ typedef int (*qemuMonitorDomainBlockJobCallback)(qemuMonitorPtr mon,
const char *diskAlias,
int type,
int status,
+ const char *hint,
void *opaque);
typedef int (*qemuMonitorDomainTrayChangeCallback)(qemuMonitorPtr mon,
virDomainObjPtr vm,
@@ -332,7 +333,8 @@ int qemuMonitorEmitPMSuspend(qemuMonitorPtr mon);
int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
const char *diskAlias,
int type,
- int status);
+ int status,
+ const char *hint);
int qemuMonitorEmitBalloonChange(qemuMonitorPtr mon,
unsigned long long actual);
int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 8218e12..55b3ed8 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -846,7 +846,7 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
}
out:
- qemuMonitorEmitBlockJob(mon, device, type, event);
+ qemuMonitorEmitBlockJob(mon, device, type, event, error);
}
static void
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 27d04a4..4638994 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -975,6 +975,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
const char *diskAlias,
int type,
int status,
+ const char *hint,
void *opaque)
{
virQEMUDriverPtr driver = opaque;
@@ -996,6 +997,8 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
/* We have a SYNC API waiting for this event, dispatch it back */
diskPriv->blockJobType = type;
diskPriv->blockJobStatus = status;
+ VIR_FREE(diskPriv->blockJobHint);
+ ignore_value(VIR_STRDUP_QUIET(diskPriv->blockJobHint, hint));
virDomainObjBroadcast(vm);
} else {
/* there is no waiting SYNC API, dispatch the update to a thread */
--
1.8.3.1