From nobody Mon May 6 08:55:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1509528497212103.3284833032842; Wed, 1 Nov 2017 02:28:17 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4044681DF2; Wed, 1 Nov 2017 09:28:15 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A290960602; Wed, 1 Nov 2017 09:28:14 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 638644BB79; Wed, 1 Nov 2017 09:28:12 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id vA19SA1D025259 for ; Wed, 1 Nov 2017 05:28:11 -0400 Received: by smtp.corp.redhat.com (Postfix) id DC59F60CA2; Wed, 1 Nov 2017 09:28:10 +0000 (UTC) Received: from mx1.redhat.com (ext-mx03.extmail.prod.ext.phx2.redhat.com [10.5.110.27]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D55BE60CA0 for ; Wed, 1 Nov 2017 09:28:08 +0000 (UTC) Received: from relay.sw.ru (mailhub.sw.ru [195.214.232.25]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6C6106A7CE for ; Wed, 1 Nov 2017 09:28:04 +0000 (UTC) Received: from dim-vz7.qa.sw.ru (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id vA19S1hh017515 for ; Wed, 1 Nov 2017 12:28:01 +0300 (MSK) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4044681DF2 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=fail (p=none dis=none) header.from=virtuozzo.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 4044681DF2 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6C6106A7CE Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=pass (p=none dis=none) header.from=virtuozzo.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=nshirokovskiy@virtuozzo.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 6C6106A7CE From: Nikolay Shirokovskiy To: libvir-list@redhat.com Date: Wed, 1 Nov 2017 12:27:40 +0300 Message-Id: <1509528460-910858-1-git-send-email-nshirokovskiy@virtuozzo.com> X-Greylist: Delayed for 21:21:14 by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 01 Nov 2017 09:28:06 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 01 Nov 2017 09:28:06 +0000 (UTC) for IP:'195.214.232.25' DOMAIN:'mailhub.sw.ru' HELO:'relay.sw.ru' FROM:'nshirokovskiy@virtuozzo.com' RCPT:'' X-RedHat-Spam-Score: -0.001 (SPF_PASS) 195.214.232.25 mailhub.sw.ru 195.214.232.25 mailhub.sw.ru X-Scanned-By: MIMEDefang 2.78 on 10.5.110.27 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH RFC v2] lib: provide error message in new block job error event X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 01 Nov 2017 09:28:15 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" If block job is completed with error qemu additionally provides error message. This patch introduces new event VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR to pass error message to client. This error message has no semantics and should not be interpreted. API and RPC layer also have reserved 'code' field to pass semantics loaded error code value in the future. --- The patch is applied on top of [1] patch series (not yet pushed though). Diff from v1 [2]: 1. Replace block job event version 3 with block job error event. 2. Add code field to API/RPC to pass error code in the future. Peter, I decided not to use enum/union as this looks like to much effort t= o extend code generation for this simple case. Using typed params looks unsuitable = too. [1] https://www.redhat.com/archives/libvir-list/2017-October/msg01292.html [2] https://www.redhat.com/archives/libvir-list/2017-October/msg01369.html daemon/remote.c | 48 +++++++++++++++++++ examples/object-events/event-test.c | 20 ++++++++ include/libvirt/libvirt-domain.h | 25 ++++++++++ src/conf/domain_event.c | 96 +++++++++++++++++++++++++++++++++= ++++ src/conf/domain_event.h | 13 +++++ src/libvirt_private.syms | 2 + src/qemu/qemu_blockjob.c | 9 +++- src/qemu/qemu_blockjob.h | 3 +- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 10 ++-- src/qemu/qemu_process.c | 12 +++-- src/remote/remote_driver.c | 34 +++++++++++++ src/remote/remote_protocol.x | 17 ++++++- src/remote_protocol-structs | 9 ++++ tools/virsh-domain.c | 24 ++++++++++ 15 files changed, 313 insertions(+), 10 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 3f7d2d3..545bf67 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1342,6 +1342,53 @@ remoteRelayDomainEventBlockThreshold(virConnectPtr c= onn, } =20 =20 +static int +remoteRelayDomainEventBlockJobError(virConnectPtr conn, + virDomainPtr dom, + const char *dev, + int type, + unsigned int code, + const char *message, + void *opaque) +{ + daemonClientEventCallbackPtr callback =3D opaque; + remote_domain_event_block_job_error_msg msg; + + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) + return -1; + + VIR_DEBUG("Relaying domain block job error event %s %d %s %i %u %s, ca= llback %d", + dom->name, dom->id, dev, type, code, NULLSTR(message), + callback->callbackID); + + memset(&msg, 0, sizeof(msg)); + msg.callbackID =3D callback->callbackID; + if (VIR_STRDUP(msg.dev, dev) < 0) + return -1; + if (message) { + if (VIR_ALLOC(msg.message) < 0 || + VIR_STRDUP(*(msg.message), message) < 0) + goto error; + } + msg.type =3D type; + msg.code =3D code; + make_nonnull_domain(&msg.dom, dom); + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR, + (xdrproc_t)xdr_remote_domain_event_block= _job_error_msg, + &msg); + return 0; + + error: + VIR_FREE(msg.dev); + VIR_FREE(msg.message); + + return -1; +} + + static virConnectDomainEventGenericCallback domainEventCallbacks[] =3D { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), @@ -1368,6 +1415,7 @@ static virConnectDomainEventGenericCallback domainEve= ntCallbacks[] =3D { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold), + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJobError), }; =20 verify(ARRAY_CARDINALITY(domainEventCallbacks) =3D=3D VIR_DOMAIN_EVENT_ID_= LAST); diff --git a/examples/object-events/event-test.c b/examples/object-events/e= vent-test.c index a144638..43a3878 100644 --- a/examples/object-events/event-test.c +++ b/examples/object-events/event-test.c @@ -936,6 +936,25 @@ myDomainEventBlockJobCallback(virConnectPtr conn ATTRI= BUTE_UNUSED, =20 =20 static int +myDomainEventBlockJobErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *dev, + int type, + unsigned int code, + const char *message, + void *opaque) +{ + const char *eventName =3D opaque; + + printf("%s EVENT: Domain %s(%d) block job error callback '%s' disk '%s= ', " + "type '%s' code '%u' message '%s'", + __func__, virDomainGetName(dom), virDomainGetID(dom), eventName, + dev, blockJobTypeToStr(type), code, NULLSTR(message)); + return 0; +} + + +static int myDomainEventBlockThresholdCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *dev, @@ -1082,6 +1101,7 @@ struct domainEventData domainEvents[] =3D { DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventD= eviceRemovalFailedCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadat= aChangeCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockTh= resholdCallback), + DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR, myDomainEventBlockJo= bErrorCallback), }; =20 struct storagePoolEventData { diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-dom= ain.h index 4048acf..9f5c1ba 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4363,6 +4363,30 @@ typedef void (*virConnectDomainEventBlockThresholdCa= llback)(virConnectPtr conn, unsigned long = long excess, void *opaque); =20 + +/** + * virConnectDomainEventBlockJobErrorCallback: + * @conn: connection object + * @dom: domain on which the event occurred + * @dev: name associated with the affected disk or storage backing chain + * element + * @type: type of block job (virDomainBlockJobType) + * @code: always 0, reserved for future use + * @message: error message with no semantics, can be NULL + * @opaque: application specified data + * + * The callback occurs when block job is completed with error and provides + * error message in @message. + * + */ +typedef void (*virConnectDomainEventBlockJobErrorCallback)(virConnectPtr c= onn, + virDomainPtr do= m, + const char *dev, + int type, + unsigned int co= de, + const char *mes= sage, + void *opaque); + /** * VIR_DOMAIN_EVENT_CALLBACK: * @@ -4405,6 +4429,7 @@ typedef enum { VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED =3D 22, /* virConnectDomainE= ventDeviceRemovalFailedCallback */ VIR_DOMAIN_EVENT_ID_METADATA_CHANGE =3D 23, /* virConnectDomainEventMe= tadataChangeCallback */ VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD =3D 24, /* virConnectDomainEventBl= ockThresholdCallback */ + VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR =3D 25, /* virConnectDomainEventBl= ockJobErrorCallback */ =20 # ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_ID_LAST diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 7baccd5..3a98de7 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -47,6 +47,7 @@ static virClassPtr virDomainEventWatchdogClass; static virClassPtr virDomainEventIOErrorClass; static virClassPtr virDomainEventGraphicsClass; static virClassPtr virDomainEventBlockJobClass; +static virClassPtr virDomainEventBlockJobErrorClass; static virClassPtr virDomainEventDiskChangeClass; static virClassPtr virDomainEventTrayChangeClass; static virClassPtr virDomainEventBalloonChangeClass; @@ -69,6 +70,7 @@ static void virDomainEventWatchdogDispose(void *obj); static void virDomainEventIOErrorDispose(void *obj); static void virDomainEventGraphicsDispose(void *obj); static void virDomainEventBlockJobDispose(void *obj); +static void virDomainEventBlockJobErrorDispose(void *obj); static void virDomainEventDiskChangeDispose(void *obj); static void virDomainEventTrayChangeDispose(void *obj); static void virDomainEventBalloonChangeDispose(void *obj); @@ -151,6 +153,17 @@ struct _virDomainEventBlockJob { typedef struct _virDomainEventBlockJob virDomainEventBlockJob; typedef virDomainEventBlockJob *virDomainEventBlockJobPtr; =20 +struct _virDomainEventBlockJobError { + virDomainEvent parent; + + char *dev; + int type; + unsigned int code; + char *message; +}; +typedef struct _virDomainEventBlockJobError virDomainEventBlockJobError; +typedef virDomainEventBlockJobError *virDomainEventBlockJobErrorPtr; + struct _virDomainEventGraphics { virDomainEvent parent; =20 @@ -337,6 +350,12 @@ virDomainEventsOnceInit(void) sizeof(virDomainEventBlockJob), virDomainEventBlockJobDispose))) return -1; + if (!(virDomainEventBlockJobErrorClass =3D + virClassNew(virDomainEventClass, + "virDomainEventBlockJobError", + sizeof(virDomainEventBlockJobError), + virDomainEventBlockJobErrorDispose))) + return -1; if (!(virDomainEventDiskChangeClass =3D virClassNew(virDomainEventClass, "virDomainEventDiskChange", @@ -504,6 +523,16 @@ virDomainEventBlockJobDispose(void *obj) } =20 static void +virDomainEventBlockJobErrorDispose(void *obj) +{ + virDomainEventBlockJobErrorPtr event =3D obj; + VIR_DEBUG("obj=3D%p", event); + + VIR_FREE(event->dev); + VIR_FREE(event->message); +} + +static void virDomainEventDiskChangeDispose(void *obj) { virDomainEventDiskChangePtr event =3D obj; @@ -1061,6 +1090,59 @@ virDomainEventBlockJob2NewFromDom(virDomainPtr dom, dst, type, status); } =20 +static virObjectEventPtr +virDomainEventBlockJobErrorNew(int id, + const char *name, + unsigned char *uuid, + const char *dev, + int type, + unsigned int code, + const char *message) +{ + virDomainEventBlockJobErrorPtr ev; + + if (virDomainEventsInitialize() < 0) + return NULL; + + if (!(ev =3D virDomainEventNew(virDomainEventBlockJobErrorClass, + VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR, + id, name, uuid))) + return NULL; + + if (VIR_STRDUP(ev->dev, dev) < 0) { + virObjectUnref(ev); + return NULL; + } + ignore_value(VIR_STRDUP_QUIET(ev->message, message)); + ev->type =3D type; + ev->code =3D code; + + return (virObjectEventPtr)ev; +} + +virObjectEventPtr +virDomainEventBlockJobErrorNewFromObj(virDomainObjPtr obj, + const char *dev, + int type, + unsigned int code, + const char *message) +{ + return virDomainEventBlockJobErrorNew(obj->def->id, obj->def->name, + obj->def->uuid, dev, type, code, + message); +} + +virObjectEventPtr +virDomainEventBlockJobErrorNewFromDom(virDomainPtr dom, + const char *dev, + int type, + unsigned int code, + const char *message) +{ + return virDomainEventBlockJobErrorNew(dom->id, dom->name, dom->uuid, + dev, type, code, message); +} + virObjectEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom) { @@ -1871,6 +1953,20 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, goto cleanup; } =20 + case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR: + { + virDomainEventBlockJobErrorPtr blockJobErrorEvent; + + blockJobErrorEvent =3D (virDomainEventBlockJobErrorPtr)event; + ((virConnectDomainEventBlockJobErrorCallback)cb)(conn, dom, + blockJobError= Event->dev, + blockJobError= Event->type, + blockJobError= Event->code, + blockJobError= Event->message, + cbopaque); + goto cleanup; + } + case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: { virDomainEventDiskChangePtr diskChangeEvent; diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index 3992a29..456026c 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -138,6 +138,19 @@ virDomainEventBlockJob2NewFromDom(virDomainPtr dom, int status); =20 virObjectEventPtr +virDomainEventBlockJobErrorNewFromObj(virDomainObjPtr obj, + const char *dev, + int type, + unsigned int code, + const char *message); +virObjectEventPtr +virDomainEventBlockJobErrorNewFromDom(virDomainPtr dom, + const char *dev, + int type, + unsigned int code, + const char *message); + +virObjectEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, const char *oldSrcPath, const char *newSrcPath, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 448d962..594c792 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -562,6 +562,8 @@ virDomainEventBalloonChangeNewFromDom; virDomainEventBalloonChangeNewFromObj; virDomainEventBlockJob2NewFromDom; virDomainEventBlockJob2NewFromObj; +virDomainEventBlockJobErrorNewFromDom; +virDomainEventBlockJobErrorNewFromObj; virDomainEventBlockJobNewFromDom; virDomainEventBlockJobNewFromObj; virDomainEventBlockThresholdNewFromDom; diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index 0b1616a..7edc30a 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -70,7 +70,8 @@ qemuBlockJobUpdate(virQEMUDriverPtr driver, if (status !=3D -1) { qemuBlockJobEventProcess(driver, vm, disk, asyncJob, diskPriv->blockJobType, - diskPriv->blockJobStatus); + diskPriv->blockJobStatus, + diskPriv->blockJobError); diskPriv->blockJobStatus =3D -1; if (error) VIR_STEAL_PTR(*error, diskPriv->blockJobError); @@ -100,10 +101,12 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver, virDomainDiskDefPtr disk, qemuDomainAsyncJob asyncJob, int type, - int status) + int status, + const char *error) { virObjectEventPtr event =3D NULL; virObjectEventPtr event2 =3D NULL; + virObjectEventPtr event3 =3D NULL; const char *path; virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); virDomainDiskDefPtr persistDisk =3D NULL; @@ -123,6 +126,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver, path =3D virDomainDiskGetSource(disk); event =3D virDomainEventBlockJobNewFromObj(vm, path, type, status); event2 =3D virDomainEventBlockJob2NewFromObj(vm, disk->dst, type, stat= us); + event3 =3D virDomainEventBlockJobErrorNewFromObj(vm, disk->dst, type, = 0, error); =20 /* If we completed a block pull or commit, then update the XML * to match. */ @@ -212,6 +216,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver, =20 qemuDomainEventQueue(driver, event); qemuDomainEventQueue(driver, event2); + qemuDomainEventQueue(driver, event3); =20 virObjectUnref(cfg); } diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h index e71d691..18bcaaa 100644 --- a/src/qemu/qemu_blockjob.h +++ b/src/qemu/qemu_blockjob.h @@ -36,7 +36,8 @@ void qemuBlockJobEventProcess(virQEMUDriverPtr driver, virDomainDiskDefPtr disk, qemuDomainAsyncJob asyncJob, int type, - int status); + int status, + const char *error); =20 void qemuBlockJobSyncBegin(virDomainDiskDefPtr disk); void qemuBlockJobSyncEnd(virQEMUDriverPtr driver, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 735e810..99a71b3 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -457,6 +457,7 @@ struct qemuProcessEvent { int action; int status; void *data; + char *error; }; =20 typedef struct _qemuDomainLogContext qemuDomainLogContext; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 725b46a..c6626bb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4715,7 +4715,8 @@ processBlockJobEvent(virQEMUDriverPtr driver, virDomainObjPtr vm, char *diskAlias, int type, - int status) + int status, + char *error) { virDomainDiskDefPtr disk; =20 @@ -4728,12 +4729,14 @@ processBlockJobEvent(virQEMUDriverPtr driver, } =20 if ((disk =3D qemuProcessFindDomainDiskByAlias(vm, diskAlias))) - qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE, ty= pe, status); + qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE, + type, status, error); =20 endjob: qemuDomainObjEndJob(driver, vm); cleanup: VIR_FREE(diskAlias); + VIR_FREE(error); } =20 =20 @@ -4815,7 +4818,8 @@ static void qemuProcessEventHandler(void *data, void = *opaque) processBlockJobEvent(driver, vm, processEvent->data, processEvent->action, - processEvent->status); + processEvent->status, + processEvent->error); break; case QEMU_PROCESS_EVENT_MONITOR_EOF: processMonitorEOFEvent(driver, vm); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4bfad5d..6a3d9bc 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1008,6 +1008,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUT= E_UNUSED, virDomainDiskDefPtr disk; qemuDomainDiskPrivatePtr diskPriv; char *data =3D NULL; + char *errorCopy =3D NULL; =20 virObjectLock(vm); =20 @@ -1018,13 +1019,14 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIB= UTE_UNUSED, goto error; diskPriv =3D QEMU_DOMAIN_DISK_PRIVATE(disk); =20 + ignore_value(VIR_STRDUP_QUIET(errorCopy, error)); + if (diskPriv->blockJobSync) { /* We have a SYNC API waiting for this event, dispatch it back */ diskPriv->blockJobType =3D type; diskPriv->blockJobStatus =3D status; VIR_FREE(diskPriv->blockJobError); - if (error && VIR_STRDUP_QUIET(diskPriv->blockJobError, error) < 0) - VIR_WARN("Can not pass error message further: %s", error); + VIR_STEAL_PTR(diskPriv->blockJobError, errorCopy); virDomainObjBroadcast(vm); } else { /* there is no waiting SYNC API, dispatch the update to a thread */ @@ -1038,6 +1040,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUT= E_UNUSED, processEvent->vm =3D vm; processEvent->action =3D type; processEvent->status =3D status; + VIR_STEAL_PTR(processEvent->error, errorCopy); =20 virObjectRef(vm); if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0)= { @@ -1047,11 +1050,14 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIB= UTE_UNUSED, } =20 cleanup: + VIR_FREE(errorCopy); virObjectUnlock(vm); return 0; error: - if (processEvent) + if (processEvent) { VIR_FREE(processEvent->data); + VIR_FREE(processEvent->error); + } VIR_FREE(processEvent); goto cleanup; } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 06719bb..69d93aa 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -405,6 +405,11 @@ remoteConnectNotifyEventConnectionClosed(virNetClientP= rogramPtr prog ATTRIBUTE_U virNetClientPtr client ATTRIBUTE_= UNUSED, void *evdata, void *opaque); =20 +static void +remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + static virNetClientProgramEvent remoteEvents[] =3D { { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, remoteDomainBuildEventLifecycle, @@ -611,6 +616,10 @@ static virNetClientProgramEvent remoteEvents[] =3D { remoteDomainBuildEventBlockThreshold, sizeof(remote_domain_event_block_threshold_msg), (xdrproc_t)xdr_remote_domain_event_block_threshold_msg }, + { REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR, + remoteDomainBuildEventBlockJobError, + sizeof(remote_domain_event_block_job_error_msg), + (xdrproc_t)xdr_remote_domain_event_block_job_error_msg }, }; =20 static void @@ -5610,6 +5619,31 @@ remoteDomainBuildEventBlockThreshold(virNetClientPro= gramPtr prog ATTRIBUTE_UNUSE } =20 =20 +static void +remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog ATTRIBUTE_= UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSE= D, + void *evdata, void *opaque) +{ + virConnectPtr conn =3D opaque; + remote_domain_event_block_job_error_msg *msg =3D evdata; + struct private_data *priv =3D conn->privateData; + virDomainPtr dom; + virObjectEventPtr event =3D NULL; + + dom =3D get_nonnull_domain(conn, msg->dom); + if (!dom) + return; + + event =3D virDomainEventBlockJobErrorNewFromDom(dom, msg->dev, msg->ty= pe, + msg->code, + msg->message ? *msg->mes= sage : NULL); + + virObjectUnref(dom); + + remoteEventQueue(priv, event, msg->callbackID); +} + + static int remoteStreamSend(virStreamPtr st, const char *data, diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 0aed252..3aba4a3 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3095,6 +3095,15 @@ struct remote_domain_event_block_job_2_msg { int status; }; =20 +struct remote_domain_event_block_job_error_msg { + int callbackID; + remote_nonnull_domain dom; + remote_nonnull_string dev; + int type; + int code; + remote_string message; +}; + struct remote_domain_event_block_threshold_msg { int callbackID; remote_nonnull_domain dom; @@ -6120,5 +6129,11 @@ enum remote_procedure { * @generate: both * @acl: domain:write */ - REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION =3D 390 + REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION =3D 390, + + /** + * @generate: none + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR =3D 391 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 59b0ace..29dcfc1 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2535,6 +2535,14 @@ struct remote_domain_event_block_job_2_msg { int type; int status; }; +struct remote_domain_event_block_job_error_msg { + int callbackID; + remote_nonnull_domain dom; + remote_nonnull_string dev; + int type; + int code; + remote_string message; +}; struct remote_domain_event_block_threshold_msg { int callbackID; remote_nonnull_domain dom; @@ -3262,4 +3270,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MANAGED_SAVE_GET_XML_DESC =3D 388, REMOTE_PROC_DOMAIN_MANAGED_SAVE_DEFINE_XML =3D 389, REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION =3D 390, + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_3 =3D 391, }; diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 1e33e82..7fec0b3 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -13253,6 +13253,28 @@ virshEventBlockThresholdPrint(virConnectPtr conn A= TTRIBUTE_UNUSED, } =20 =20 +static void +virshEventBlockJobErrorPrint(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *dev, + int type, + unsigned int code ATTRIBUTE_UNUSED, + const char *message, + void *opaque) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + + virBufferAsprintf(&buf, _("event '%s' for domain %s: %s for %s, " + "error: %s\n"), + ((virshDomEventData *) opaque)->cb->name, + virDomainGetName(dom), + virshDomainBlockJobToString(type), + dev, + NULLSTR(message)); + virshEventPrint(opaque, &buf); +} + + static vshEventCallback vshEventCallbacks[] =3D { { "lifecycle", VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), }, @@ -13302,6 +13324,8 @@ static vshEventCallback vshEventCallbacks[] =3D { VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), }, { "block-threshold", VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), }, + { "block-job-error", + VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockJobErrorPrint), }, }; verify(VIR_DOMAIN_EVENT_ID_LAST =3D=3D ARRAY_CARDINALITY(vshEventCallbacks= )); =20 --=20 1.8.3.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list