The event will be fired when the domain memory only dump completes.
Alloc a return buffer to store/pass along the dump statistics that
will be eventually shared by a query-dump command.
Signed-off-by: John Ferlan <jferlan@redhat.com>
---
src/qemu/qemu_monitor.c | 29 ++++++++++++++++++++
src/qemu/qemu_monitor.h | 31 +++++++++++++++++++++
src/qemu/qemu_monitor_json.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 125 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index fc146bdbf..23153967c 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -210,6 +210,10 @@ VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
"ok", "failed", "nospace")
+VIR_ENUM_IMPL(qemuMonitorDumpStatus,
+ QEMU_MONITOR_DUMP_STATUS_LAST,
+ "none", "active", "completed", "failed")
+
char *
qemuMonitorEscapeArg(const char *in)
{
@@ -1667,6 +1671,21 @@ qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon,
int
+qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
+ qemuMonitorDumpStatsPtr stats,
+ const char *error)
+{
+ int ret = -1;
+
+ VIR_DEBUG("mon=%p", mon);
+
+ QEMU_MONITOR_CALLBACK(mon, ret, domainDumpCompleted, mon->vm, stats, error);
+
+ return ret;
+}
+
+
+int
qemuMonitorSetCapabilities(qemuMonitorPtr mon)
{
QEMU_CHECK_MONITOR(mon);
@@ -4359,3 +4378,13 @@ qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
return qemuMonitorJSONSetWatchdogAction(mon, action);
}
+
+
+void
+qemuMonitorEventDumpStatsFree(qemuMonitorDumpStatsPtr stats)
+{
+ if (!stats)
+ return;
+
+ VIR_FREE(stats);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 67b785e60..37f335e9f 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -246,6 +246,30 @@ typedef int (*qemuMonitorDomainBlockThresholdCallback)(qemuMonitorPtr mon,
unsigned long long excess,
void *opaque);
+typedef enum {
+ QEMU_MONITOR_DUMP_STATUS_NONE,
+ QEMU_MONITOR_DUMP_STATUS_ACTIVE,
+ QEMU_MONITOR_DUMP_STATUS_COMPLETED,
+ QEMU_MONITOR_DUMP_STATUS_FAILED,
+
+ QEMU_MONITOR_DUMP_STATUS_LAST,
+} qemuMonitorDumpStatus;
+
+VIR_ENUM_DECL(qemuMonitorDumpStatus)
+
+typedef struct _qemuMonitorDumpStats qemuMonitorDumpStats;
+typedef qemuMonitorDumpStats *qemuMonitorDumpStatsPtr;
+struct _qemuMonitorDumpStats {
+ int status; /* qemuMonitorDumpStatus */
+ unsigned long long completed; /* bytes written */
+ unsigned long long total; /* total bytes to be written */
+};
+
+typedef int (*qemuMonitorDomainDumpCompletedCallback)(qemuMonitorPtr mon,
+ virDomainObjPtr vm,
+ qemuMonitorDumpStatsPtr stats,
+ const char *error,
+ void *opaque);
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
@@ -279,6 +303,7 @@ struct _qemuMonitorCallbacks {
qemuMonitorDomainMigrationPassCallback domainMigrationPass;
qemuMonitorDomainAcpiOstInfoCallback domainAcpiOstInfo;
qemuMonitorDomainBlockThresholdCallback domainBlockThreshold;
+ qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
};
char *qemuMonitorEscapeArg(const char *in);
@@ -408,6 +433,10 @@ int qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon,
unsigned long long threshold,
unsigned long long excess);
+int qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
+ qemuMonitorDumpStatsPtr stats,
+ const char *error);
+
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
@@ -1146,4 +1175,6 @@ virJSONValuePtr qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon);
int qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
const char *action);
+
+void qemuMonitorEventDumpStatsFree(qemuMonitorDumpStatsPtr stats);
#endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 5ddd85575..a8cb8ce6b 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -90,6 +90,7 @@ static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, virJSONValu
static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
typedef struct {
const char *type;
@@ -106,6 +107,7 @@ static qemuEventHandler eventHandlers[] = {
{ "BLOCK_WRITE_THRESHOLD", qemuMonitorJSONHandleBlockThreshold, },
{ "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
{ "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
+ { "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, },
{ "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
{ "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
{ "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
@@ -1143,6 +1145,69 @@ qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data)
}
+static qemuMonitorDumpStatsPtr
+qemuMonitorJSONExtractDumpStats(virJSONValuePtr result)
+{
+ qemuMonitorDumpStatsPtr ret;
+ const char *statusstr;
+
+ if (VIR_ALLOC(ret) < 0)
+ return NULL;
+
+ if (!(statusstr = virJSONValueObjectGetString(result, "status"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("incomplete result, failed to get status"));
+ goto error;
+ }
+
+ ret->status = qemuMonitorDumpStatusTypeFromString(statusstr);
+ if (ret->status < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("incomplete result, unknown status string '%s'"),
+ statusstr);
+ goto error;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(result, "completed", &ret->completed) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("incomplete result, failed to get completed"));
+ goto error;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(result, "total", &ret->total) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("incomplete result, failed to get total"));
+ goto error;
+ }
+
+ return ret;
+
+ error:
+ qemuMonitorEventDumpStatsFree(ret);
+ return NULL;
+}
+
+
+static void
+qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon,
+ virJSONValuePtr data)
+{
+ virJSONValuePtr result;
+ qemuMonitorDumpStatsPtr stats = NULL;
+ const char *error = NULL;
+
+ if (!(result = virJSONValueObjectGetObject(data, "result"))) {
+ VIR_WARN("missing result in dump completed event");
+ return;
+ }
+
+ stats = qemuMonitorJSONExtractDumpStats(result);
+ error = virJSONValueObjectGetString(data, "error");
+
+ qemuMonitorEmitDumpCompleted(mon, stats, error);
+}
+
+
int
qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
const char *cmd_str,
--
2.13.6
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Mon, Jan 29, 2018 at 11:31:59 -0500, John Ferlan wrote:
> The event will be fired when the domain memory only dump completes.
>
> Alloc a return buffer to store/pass along the dump statistics that
> will be eventually shared by a query-dump command.
>
> Signed-off-by: John Ferlan <jferlan@redhat.com>
> ---
> src/qemu/qemu_monitor.c | 29 ++++++++++++++++++++
> src/qemu/qemu_monitor.h | 31 +++++++++++++++++++++
> src/qemu/qemu_monitor_json.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 125 insertions(+)
>
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index fc146bdbf..23153967c 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -210,6 +210,10 @@ VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
> QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
> "ok", "failed", "nospace")
>
> +VIR_ENUM_IMPL(qemuMonitorDumpStatus,
> + QEMU_MONITOR_DUMP_STATUS_LAST,
> + "none", "active", "completed", "failed")
> +
> char *
> qemuMonitorEscapeArg(const char *in)
> {
> @@ -1667,6 +1671,21 @@ qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon,
>
>
> int
> +qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
> + qemuMonitorDumpStatsPtr stats,
> + const char *error)
> +{
> + int ret = -1;
> +
> + VIR_DEBUG("mon=%p", mon);
> +
> + QEMU_MONITOR_CALLBACK(mon, ret, domainDumpCompleted, mon->vm, stats, error);
> +
> + return ret;
> +}
> +
> +
> +int
> qemuMonitorSetCapabilities(qemuMonitorPtr mon)
> {
> QEMU_CHECK_MONITOR(mon);
> @@ -4359,3 +4378,13 @@ qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
>
> return qemuMonitorJSONSetWatchdogAction(mon, action);
> }
> +
> +
> +void
> +qemuMonitorEventDumpStatsFree(qemuMonitorDumpStatsPtr stats)
> +{
> + if (!stats)
> + return;
> +
> + VIR_FREE(stats);
> +}
The caller can just use VIR_FREE() directly and benefit from it
automatically resetting the pointer to NULL. Anyway, I don't think we
need to ever free this structure.
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 67b785e60..37f335e9f 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -246,6 +246,30 @@ typedef int (*qemuMonitorDomainBlockThresholdCallback)(qemuMonitorPtr mon,
> unsigned long long excess,
> void *opaque);
>
> +typedef enum {
> + QEMU_MONITOR_DUMP_STATUS_NONE,
> + QEMU_MONITOR_DUMP_STATUS_ACTIVE,
> + QEMU_MONITOR_DUMP_STATUS_COMPLETED,
> + QEMU_MONITOR_DUMP_STATUS_FAILED,
> +
> + QEMU_MONITOR_DUMP_STATUS_LAST,
> +} qemuMonitorDumpStatus;
> +
> +VIR_ENUM_DECL(qemuMonitorDumpStatus)
> +
> +typedef struct _qemuMonitorDumpStats qemuMonitorDumpStats;
> +typedef qemuMonitorDumpStats *qemuMonitorDumpStatsPtr;
> +struct _qemuMonitorDumpStats {
> + int status; /* qemuMonitorDumpStatus */
> + unsigned long long completed; /* bytes written */
> + unsigned long long total; /* total bytes to be written */
> +};
> +
> +typedef int (*qemuMonitorDomainDumpCompletedCallback)(qemuMonitorPtr mon,
> + virDomainObjPtr vm,
> + qemuMonitorDumpStatsPtr stats,
> + const char *error,
> + void *opaque);
>
> typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
> typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
> @@ -279,6 +303,7 @@ struct _qemuMonitorCallbacks {
> qemuMonitorDomainMigrationPassCallback domainMigrationPass;
> qemuMonitorDomainAcpiOstInfoCallback domainAcpiOstInfo;
> qemuMonitorDomainBlockThresholdCallback domainBlockThreshold;
> + qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
> };
>
> char *qemuMonitorEscapeArg(const char *in);
> @@ -408,6 +433,10 @@ int qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon,
> unsigned long long threshold,
> unsigned long long excess);
>
> +int qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
> + qemuMonitorDumpStatsPtr stats,
> + const char *error);
> +
> int qemuMonitorStartCPUs(qemuMonitorPtr mon,
> virConnectPtr conn);
> int qemuMonitorStopCPUs(qemuMonitorPtr mon);
> @@ -1146,4 +1175,6 @@ virJSONValuePtr qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon);
>
> int qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
> const char *action);
> +
> +void qemuMonitorEventDumpStatsFree(qemuMonitorDumpStatsPtr stats);
> #endif /* QEMU_MONITOR_H */
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 5ddd85575..a8cb8ce6b 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -90,6 +90,7 @@ static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, virJSONValu
> static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, virJSONValuePtr data);
> static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data);
> static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data);
> +static void qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
>
> typedef struct {
> const char *type;
> @@ -106,6 +107,7 @@ static qemuEventHandler eventHandlers[] = {
> { "BLOCK_WRITE_THRESHOLD", qemuMonitorJSONHandleBlockThreshold, },
> { "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
> { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
> + { "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, },
> { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
> { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
> { "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
> @@ -1143,6 +1145,69 @@ qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data)
> }
>
>
> +static qemuMonitorDumpStatsPtr
> +qemuMonitorJSONExtractDumpStats(virJSONValuePtr result)
> +{
> + qemuMonitorDumpStatsPtr ret;
> + const char *statusstr;
> +
> + if (VIR_ALLOC(ret) < 0)
> + return NULL;
I think it would be better if this just worked on an existing reference
to qemuMonitorDumpStats passed as an additional argument.
> +
> + if (!(statusstr = virJSONValueObjectGetString(result, "status"))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("incomplete result, failed to get status"));
> + goto error;
> + }
> +
> + ret->status = qemuMonitorDumpStatusTypeFromString(statusstr);
> + if (ret->status < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("incomplete result, unknown status string '%s'"),
> + statusstr);
> + goto error;
> + }
> +
> + if (virJSONValueObjectGetNumberUlong(result, "completed", &ret->completed) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("incomplete result, failed to get completed"));
> + goto error;
> + }
> +
> + if (virJSONValueObjectGetNumberUlong(result, "total", &ret->total) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("incomplete result, failed to get total"));
> + goto error;
> + }
> +
> + return ret;
> +
> + error:
> + qemuMonitorEventDumpStatsFree(ret);
> + return NULL;
> +}
> +
> +
> +static void
> +qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon,
> + virJSONValuePtr data)
> +{
> + virJSONValuePtr result;
> + qemuMonitorDumpStatsPtr stats = NULL;
> + const char *error = NULL;
> +
> + if (!(result = virJSONValueObjectGetObject(data, "result"))) {
> + VIR_WARN("missing result in dump completed event");
> + return;
> + }
> +
> + stats = qemuMonitorJSONExtractDumpStats(result);
> + error = virJSONValueObjectGetString(data, "error");
> +
> + qemuMonitorEmitDumpCompleted(mon, stats, error);
Using stats allocated on the stack would resolve the memory leak here.
Jirka
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On 02/01/2018 09:37 AM, Jiri Denemark wrote:
> On Mon, Jan 29, 2018 at 11:31:59 -0500, John Ferlan wrote:
>> The event will be fired when the domain memory only dump completes.
>>
>> Alloc a return buffer to store/pass along the dump statistics that
>> will be eventually shared by a query-dump command.
>>
>> Signed-off-by: John Ferlan <jferlan@redhat.com>
>> ---
>> src/qemu/qemu_monitor.c | 29 ++++++++++++++++++++
>> src/qemu/qemu_monitor.h | 31 +++++++++++++++++++++
>> src/qemu/qemu_monitor_json.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 125 insertions(+)
>>
>> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
>> index fc146bdbf..23153967c 100644
>> --- a/src/qemu/qemu_monitor.c
>> +++ b/src/qemu/qemu_monitor.c
>> @@ -210,6 +210,10 @@ VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
>> QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
>> "ok", "failed", "nospace")
>>
>> +VIR_ENUM_IMPL(qemuMonitorDumpStatus,
>> + QEMU_MONITOR_DUMP_STATUS_LAST,
>> + "none", "active", "completed", "failed")
>> +
>> char *
>> qemuMonitorEscapeArg(const char *in)
>> {
>> @@ -1667,6 +1671,21 @@ qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon,
>>
>>
>> int
>> +qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
>> + qemuMonitorDumpStatsPtr stats,
>> + const char *error)
>> +{
>> + int ret = -1;
>> +
>> + VIR_DEBUG("mon=%p", mon);
>> +
>> + QEMU_MONITOR_CALLBACK(mon, ret, domainDumpCompleted, mon->vm, stats, error);
>> +
>> + return ret;
>> +}
>> +
>> +
>> +int
>> qemuMonitorSetCapabilities(qemuMonitorPtr mon)
>> {
>> QEMU_CHECK_MONITOR(mon);
>> @@ -4359,3 +4378,13 @@ qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
>>
>> return qemuMonitorJSONSetWatchdogAction(mon, action);
>> }
>> +
>> +
>> +void
>> +qemuMonitorEventDumpStatsFree(qemuMonitorDumpStatsPtr stats)
>> +{
>> + if (!stats)
>> + return;
>> +
>> + VIR_FREE(stats);
>> +}
>
> The caller can just use VIR_FREE() directly and benefit from it
> automatically resetting the pointer to NULL. Anyway, I don't think we
> need to ever free this structure.
>
I was following (to a degree) qemuMonitorJSONHandleGuestPanic...
>> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
>> index 67b785e60..37f335e9f 100644
>> --- a/src/qemu/qemu_monitor.h
>> +++ b/src/qemu/qemu_monitor.h
>> @@ -246,6 +246,30 @@ typedef int (*qemuMonitorDomainBlockThresholdCallback)(qemuMonitorPtr mon,
>> unsigned long long excess,
>> void *opaque);
>>
>> +typedef enum {
>> + QEMU_MONITOR_DUMP_STATUS_NONE,
>> + QEMU_MONITOR_DUMP_STATUS_ACTIVE,
>> + QEMU_MONITOR_DUMP_STATUS_COMPLETED,
>> + QEMU_MONITOR_DUMP_STATUS_FAILED,
>> +
>> + QEMU_MONITOR_DUMP_STATUS_LAST,
>> +} qemuMonitorDumpStatus;
>> +
>> +VIR_ENUM_DECL(qemuMonitorDumpStatus)
>> +
>> +typedef struct _qemuMonitorDumpStats qemuMonitorDumpStats;
>> +typedef qemuMonitorDumpStats *qemuMonitorDumpStatsPtr;
>> +struct _qemuMonitorDumpStats {
>> + int status; /* qemuMonitorDumpStatus */
>> + unsigned long long completed; /* bytes written */
>> + unsigned long long total; /* total bytes to be written */
>> +};
>> +
>> +typedef int (*qemuMonitorDomainDumpCompletedCallback)(qemuMonitorPtr mon,
>> + virDomainObjPtr vm,
>> + qemuMonitorDumpStatsPtr stats,
>> + const char *error,
>> + void *opaque);
>>
>> typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
>> typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
>> @@ -279,6 +303,7 @@ struct _qemuMonitorCallbacks {
>> qemuMonitorDomainMigrationPassCallback domainMigrationPass;
>> qemuMonitorDomainAcpiOstInfoCallback domainAcpiOstInfo;
>> qemuMonitorDomainBlockThresholdCallback domainBlockThreshold;
>> + qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
>> };
>>
>> char *qemuMonitorEscapeArg(const char *in);
>> @@ -408,6 +433,10 @@ int qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon,
>> unsigned long long threshold,
>> unsigned long long excess);
>>
>> +int qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
>> + qemuMonitorDumpStatsPtr stats,
>> + const char *error);
>> +
>> int qemuMonitorStartCPUs(qemuMonitorPtr mon,
>> virConnectPtr conn);
>> int qemuMonitorStopCPUs(qemuMonitorPtr mon);
>> @@ -1146,4 +1175,6 @@ virJSONValuePtr qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon);
>>
>> int qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
>> const char *action);
>> +
>> +void qemuMonitorEventDumpStatsFree(qemuMonitorDumpStatsPtr stats);
>> #endif /* QEMU_MONITOR_H */
>> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
>> index 5ddd85575..a8cb8ce6b 100644
>> --- a/src/qemu/qemu_monitor_json.c
>> +++ b/src/qemu/qemu_monitor_json.c
>> @@ -90,6 +90,7 @@ static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, virJSONValu
>> static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, virJSONValuePtr data);
>> static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data);
>> static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data);
>> +static void qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
>>
>> typedef struct {
>> const char *type;
>> @@ -106,6 +107,7 @@ static qemuEventHandler eventHandlers[] = {
>> { "BLOCK_WRITE_THRESHOLD", qemuMonitorJSONHandleBlockThreshold, },
>> { "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
>> { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
>> + { "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, },
>> { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
>> { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
>> { "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
>> @@ -1143,6 +1145,69 @@ qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data)
>> }
>>
>>
>> +static qemuMonitorDumpStatsPtr
>> +qemuMonitorJSONExtractDumpStats(virJSONValuePtr result)
>> +{
>> + qemuMonitorDumpStatsPtr ret;
>> + const char *statusstr;
>> +
>> + if (VIR_ALLOC(ret) < 0)
>> + return NULL;
>
> I think it would be better if this just worked on an existing reference
> to qemuMonitorDumpStats passed as an additional argument.
>
... OK - that's fine - I take that option instead and repost.
>> +
>> + if (!(statusstr = virJSONValueObjectGetString(result, "status"))) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("incomplete result, failed to get status"));
>> + goto error;
>> + }
>> +
>> + ret->status = qemuMonitorDumpStatusTypeFromString(statusstr);
>> + if (ret->status < 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR,
>> + _("incomplete result, unknown status string '%s'"),
>> + statusstr);
>> + goto error;
>> + }
>> +
>> + if (virJSONValueObjectGetNumberUlong(result, "completed", &ret->completed) < 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("incomplete result, failed to get completed"));
>> + goto error;
>> + }
>> +
>> + if (virJSONValueObjectGetNumberUlong(result, "total", &ret->total) < 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("incomplete result, failed to get total"));
>> + goto error;
>> + }
>> +
>> + return ret;
>> +
>> + error:
>> + qemuMonitorEventDumpStatsFree(ret);
>> + return NULL;
>> +}
>> +
>> +
>> +static void
>> +qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon,
>> + virJSONValuePtr data)
>> +{
>> + virJSONValuePtr result;
>> + qemuMonitorDumpStatsPtr stats = NULL;
>> + const char *error = NULL;
>> +
>> + if (!(result = virJSONValueObjectGetObject(data, "result"))) {
>> + VIR_WARN("missing result in dump completed event");
>> + return;
>> + }
>> +
>> + stats = qemuMonitorJSONExtractDumpStats(result);
>> + error = virJSONValueObjectGetString(data, "error");
>> +
>> + qemuMonitorEmitDumpCompleted(mon, stats, error);
>
> Using stats allocated on the stack would resolve the memory leak here.
>
Or as you found in patch 2, it was freed... Hazards of trying to extract
into small chunks of patches.
John
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2026 Red Hat, Inc.