diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index c1b46f7d0a439c86ec946f56e10a754b5a7847e5..a85ae949dcec45d6d532419524b8c2b19ee95299 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -35,6 +35,7 @@ #include "virthread.h" #include "virtime.h" #include "locking/domain_lock.h" +#include "viralloc.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -66,6 +67,7 @@ qemuBlockJobUpdate(virQEMUDriverPtr driver, diskPriv->blockJobType, diskPriv->blockJobStatus); diskPriv->blockJobStatus = -1; + VIR_FREE(diskPriv->blockJobError); } return status; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e8e03134f5cec3d08fe76b90506898db7b844e8b..cd213479cae06863bc4d983c763a60ff80236a26 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -892,6 +892,7 @@ qemuDomainSecretInfoFree(qemuDomainSecretInfoPtr *secinfo) static virClassPtr qemuDomainDiskPrivateClass; +static void qemuDomainDiskPrivateDispose(void *obj); static int qemuDomainDiskPrivateOnceInit(void) @@ -899,7 +900,7 @@ qemuDomainDiskPrivateOnceInit(void) qemuDomainDiskPrivateClass = virClassNew(virClassForObject(), "qemuDomainDiskPrivate", sizeof(qemuDomainDiskPrivate), - NULL); + qemuDomainDiskPrivateDispose); if (!qemuDomainDiskPrivateClass) return -1; else @@ -922,6 +923,13 @@ qemuDomainDiskPrivateNew(void) return (virObjectPtr) priv; } +static void +qemuDomainDiskPrivateDispose(void *obj) +{ + qemuDomainDiskPrivatePtr priv = obj; + + VIR_FREE(priv->blockJobError); +} static virClassPtr qemuDomainStorageSourcePrivateClass; static void qemuDomainStorageSourcePrivateDispose(void *obj); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index c33af3671b05708c3be9340b658b361ae34f42d2..ba807ca0b8b0ca49f7296d72e7cfdb02f94d0bf9 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -350,6 +350,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 *blockJobError; /* block job completed event error */ bool blockJobSync; /* the block job needs synchronized termination */ bool migrating; /* the disk is being migrated */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 473a52735802184fdc2d935046147c29a13030a1..4db12c512a24ae0acebe3ef5d7943c780cf521d4 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1515,13 +1515,14 @@ int qemuMonitorEmitBlockJob(qemuMonitorPtr mon, const char *diskAlias, int type, - int status) + int status, + const char *error) { int ret = -1; VIR_DEBUG("mon=%p", mon); QEMU_MONITOR_CALLBACK(mon, ret, domainBlockJob, mon->vm, - diskAlias, type, status); + diskAlias, type, status, error); return ret; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index f81fb7f2ad00aaa665a22d4a077bc43a503367cb..67b785e6038530959bd5fea2aa90ee778cf4372a 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -176,6 +176,7 @@ typedef int (*qemuMonitorDomainBlockJobCallback)(qemuMonitorPtr mon, const char *diskAlias, int type, int status, + const char *error, void *opaque); typedef int (*qemuMonitorDomainTrayChangeCallback)(qemuMonitorPtr mon, virDomainObjPtr vm, @@ -375,7 +376,8 @@ int qemuMonitorEmitPMSuspend(qemuMonitorPtr mon); int qemuMonitorEmitBlockJob(qemuMonitorPtr mon, const char *diskAlias, int type, - int status); + int status, + const char *error); 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 64394f76fe67ad2bb2a3e48340bf140ecc5c3c01..e45868b01fc87cb80b8a8bc19901aff9e046d115 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -851,6 +851,7 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon, { const char *device; const char *type_str; + const char *error = NULL; int type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; unsigned long long offset, len; @@ -883,6 +884,7 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon, switch ((virConnectDomainEventBlockJobStatus) event) { case VIR_DOMAIN_BLOCK_JOB_COMPLETED: + error = virJSONValueObjectGetString(data, "error"); /* Make sure the whole device has been processed */ if (offset != len) event = VIR_DOMAIN_BLOCK_JOB_FAILED; @@ -897,7 +899,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 ea70885dd950150334a4e8b78e161d3242632cf0..93a24cde15503c57908fc1be2020e6a1188b0dc0 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1000,6 +1000,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *diskAlias, int type, int status, + const char *error, void *opaque) { virQEMUDriverPtr driver = opaque; @@ -1021,6 +1022,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->blockJobError); + ignore_value(VIR_STRDUP_QUIET(diskPriv->blockJobError, error)); virDomainObjBroadcast(vm); } else { /* there is no waiting SYNC API, dispatch the update to a thread */