[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v5 3/3] dump: use jobs framework for dump guest memory
From: |
Hogan Wang |
Subject: |
[PATCH v5 3/3] dump: use jobs framework for dump guest memory |
Date: |
Tue, 2 Aug 2022 10:53:05 +0800 |
There's no way to cancel the current executing dump process, lead to the
virtual machine manager daemon((e.g. libvirtd) cannot restore the dump
job after daemon restart.
When caller pass the 'job-id' argument, create a job for dump process.
And then caller can use job-cancel QMP command to cancel the detached
dump process, use job-dismiss QMP command to release job object.
Examples:
Start dump job:
{"execute": "dump-guest-memory", "arguments": { "job-id": "dump-guest-memory",
"protocol": "file:/tmp/vm.dump",
"paging": false,
"format": "elf",
"detach": true
}}
Cancel dump job:
{"execute": "job-cancel", "arguments": { "id": "dump-guest-memory" }}
Dismiss dump job:
{"execute": "job-dismiss", "arguments": { "id": "dump-guest-memory" }}
Signed-off-by: Hogan Wang <hogan.wang@huawei.com>
---
dump/dump.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/dump/dump.c b/dump/dump.c
index cec9be30b4..f2f3b6726f 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -98,6 +98,7 @@ static int dump_cleanup(DumpState *s)
{
guest_phys_blocks_free(&s->guest_phys_blocks);
memory_mapping_list_free(&s->list);
+ s->job = NULL;
close(s->fd);
g_free(s->guest_note);
s->guest_note = NULL;
@@ -1542,6 +1543,14 @@ static void get_max_mapnr(DumpState *s)
static DumpState dump_state_global = { .status = DUMP_STATUS_NONE };
+typedef struct DumpJob {
+ Job common;
+ DumpState *state;
+ Coroutine *co;
+ Error **errp;
+} DumpJob;
+
+
static void dump_state_prepare(DumpState *s)
{
/* zero the struct, setting status to active */
@@ -1894,6 +1903,53 @@ DumpQueryResult *qmp_query_dump(Error **errp)
return result;
}
+static void *dump_job_thread(void *opaque)
+{
+ DumpJob *job = (DumpJob *)opaque;
+ job_progress_set_remaining(&job->common, 1);
+ dump_process(job->state, job->errp);
+ job_progress_update(&job->common, 1);
+ aio_co_wake(job->co);
+ return NULL;
+}
+
+static int coroutine_fn dump_guest_memory_job_run(Job *job, Error **errp)
+{
+ DumpJob *s = container_of(job, DumpJob, common);
+ DumpState *state = &dump_state_global;
+
+ s->errp = errp;
+ s->co = qemu_coroutine_self();
+
+ /* detached dump */
+ qemu_thread_create(&s->state->dump_thread, "dump_thread",
+ dump_job_thread, job, QEMU_THREAD_DETACHED);
+ qemu_coroutine_yield();
+ return qatomic_read(&state->status) == DUMP_STATUS_COMPLETED ? 0 : -1;
+}
+
+static const JobDriver dump_guest_memory_job_driver = {
+ .instance_size = sizeof(DumpJob),
+ .job_type = JOB_TYPE_DUMP_GUEST_MEMORY,
+ .run = dump_guest_memory_job_run,
+};
+
+static void dump_job_start(DumpState *state, const char *job_id, Error **errp)
+{
+ DumpJob *job;
+
+ job = job_create(job_id, &dump_guest_memory_job_driver, NULL,
+ qemu_get_aio_context(), JOB_MANUAL_DISMISS,
+ NULL, NULL, errp);
+ if (!job) {
+ return;
+ }
+ state->detached = true;
+ state->job = &job->common;
+ job->state = state;
+ job_start(&job->common);
+}
+
void qmp_dump_guest_memory(bool paging, const char *file,
bool has_job_id, const char *job_id,
bool has_detach, bool detach,
@@ -2010,6 +2066,15 @@ void qmp_dump_guest_memory(bool paging, const char *file,
return;
}
+ if (has_job_id) {
+ dump_job_start(s, job_id, errp);
+ if (*errp) {
+ qatomic_set(&s->status, DUMP_STATUS_FAILED);
+ dump_cleanup(s);
+ }
+ return;
+ }
+
if (detach_p) {
/* detached dump */
s->detached = true;
--
2.33.0