|
|
357786 |
From 0223091bd8c515f4eab85de49c039f1275dd8a66 Mon Sep 17 00:00:00 2001
|
|
|
357786 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
357786 |
Date: Tue, 26 Jun 2018 09:47:59 +0200
|
|
|
357786 |
Subject: [PATCH 30/89] job: Create Job, JobDriver and job_create()
|
|
|
357786 |
|
|
|
357786 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
357786 |
Message-id: <20180626094856.6924-17-kwolf@redhat.com>
|
|
|
357786 |
Patchwork-id: 81124
|
|
|
357786 |
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH v2 16/73] job: Create Job, JobDriver and job_create()
|
|
|
357786 |
Bugzilla: 1513543
|
|
|
357786 |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
357786 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
357786 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
357786 |
|
|
|
357786 |
This is the first step towards creating an infrastructure for generic
|
|
|
357786 |
background jobs that aren't tied to a block device. For now, Job only
|
|
|
357786 |
stores its ID and JobDriver, the rest stays in BlockJob.
|
|
|
357786 |
|
|
|
357786 |
The following patches will move over more parts of BlockJob to Job if
|
|
|
357786 |
they are meaningful outside the context of a block job.
|
|
|
357786 |
|
|
|
357786 |
BlockJob.driver is now redundant, but this patch leaves it around to
|
|
|
357786 |
avoid unnecessary churn. The next patches will get rid of almost all of
|
|
|
357786 |
its uses anyway so that it can be removed later with much less churn.
|
|
|
357786 |
|
|
|
357786 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
357786 |
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
|
357786 |
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
|
357786 |
(cherry picked from commit 33e9e9bd62d9ae00880d9e12ad8a5b7d2c00e8a5)
|
|
|
357786 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
357786 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
357786 |
---
|
|
|
357786 |
MAINTAINERS | 2 ++
|
|
|
357786 |
Makefile.objs | 2 +-
|
|
|
357786 |
block/backup.c | 4 ++-
|
|
|
357786 |
block/commit.c | 4 ++-
|
|
|
357786 |
block/mirror.c | 10 +++++---
|
|
|
357786 |
block/stream.c | 4 ++-
|
|
|
357786 |
blockjob.c | 46 ++++++++++++++++-----------------
|
|
|
357786 |
include/block/blockjob.h | 9 +++----
|
|
|
357786 |
include/block/blockjob_int.h | 4 +--
|
|
|
357786 |
include/qemu/job.h | 60 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
357786 |
job.c | 48 +++++++++++++++++++++++++++++++++++
|
|
|
357786 |
tests/test-bdrv-drain.c | 4 ++-
|
|
|
357786 |
tests/test-blockjob-txn.c | 4 ++-
|
|
|
357786 |
tests/test-blockjob.c | 12 ++++++---
|
|
|
357786 |
14 files changed, 169 insertions(+), 44 deletions(-)
|
|
|
357786 |
create mode 100644 include/qemu/job.h
|
|
|
357786 |
create mode 100644 job.c
|
|
|
357786 |
|
|
|
357786 |
diff --git a/MAINTAINERS b/MAINTAINERS
|
|
|
357786 |
index ad5edc8..c5e3dfb 100644
|
|
|
357786 |
--- a/MAINTAINERS
|
|
|
357786 |
+++ b/MAINTAINERS
|
|
|
357786 |
@@ -1371,6 +1371,8 @@ L: qemu-block@nongnu.org
|
|
|
357786 |
S: Supported
|
|
|
357786 |
F: blockjob.c
|
|
|
357786 |
F: include/block/blockjob.h
|
|
|
357786 |
+F: job.c
|
|
|
357786 |
+F: include/block/job.h
|
|
|
357786 |
F: block/backup.c
|
|
|
357786 |
F: block/commit.c
|
|
|
357786 |
F: block/stream.c
|
|
|
357786 |
diff --git a/Makefile.objs b/Makefile.objs
|
|
|
357786 |
index c6c9b8f..92b73fc 100644
|
|
|
357786 |
--- a/Makefile.objs
|
|
|
357786 |
+++ b/Makefile.objs
|
|
|
357786 |
@@ -63,7 +63,7 @@ chardev-obj-y = chardev/
|
|
|
357786 |
# block-obj-y is code used by both qemu system emulation and qemu-img
|
|
|
357786 |
|
|
|
357786 |
block-obj-y += nbd/
|
|
|
357786 |
-block-obj-y += block.o blockjob.o
|
|
|
357786 |
+block-obj-y += block.o blockjob.o job.o
|
|
|
357786 |
block-obj-y += block/ scsi/
|
|
|
357786 |
block-obj-y += qemu-io-cmds.o
|
|
|
357786 |
block-obj-$(CONFIG_REPLICATION) += replication.o
|
|
|
357786 |
diff --git a/block/backup.c b/block/backup.c
|
|
|
357786 |
index e14d995..9e672bb 100644
|
|
|
357786 |
--- a/block/backup.c
|
|
|
357786 |
+++ b/block/backup.c
|
|
|
357786 |
@@ -523,7 +523,9 @@ static void coroutine_fn backup_run(void *opaque)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver backup_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(BackupBlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(BackupBlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.job_type = BLOCK_JOB_TYPE_BACKUP,
|
|
|
357786 |
.start = backup_run,
|
|
|
357786 |
.commit = backup_commit,
|
|
|
357786 |
diff --git a/block/commit.c b/block/commit.c
|
|
|
357786 |
index ba5df6a..18cbb2f 100644
|
|
|
357786 |
--- a/block/commit.c
|
|
|
357786 |
+++ b/block/commit.c
|
|
|
357786 |
@@ -215,7 +215,9 @@ out:
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver commit_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(CommitBlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(CommitBlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.job_type = BLOCK_JOB_TYPE_COMMIT,
|
|
|
357786 |
.start = commit_run,
|
|
|
357786 |
};
|
|
|
357786 |
diff --git a/block/mirror.c b/block/mirror.c
|
|
|
357786 |
index a4197bb..aa1d6b7 100644
|
|
|
357786 |
--- a/block/mirror.c
|
|
|
357786 |
+++ b/block/mirror.c
|
|
|
357786 |
@@ -913,7 +913,7 @@ static void mirror_complete(BlockJob *job, Error **errp)
|
|
|
357786 |
|
|
|
357786 |
if (!s->synced) {
|
|
|
357786 |
error_setg(errp, "The active block job '%s' cannot be completed",
|
|
|
357786 |
- job->id);
|
|
|
357786 |
+ job->job.id);
|
|
|
357786 |
return;
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
@@ -986,7 +986,9 @@ static void mirror_drain(BlockJob *job)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver mirror_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(MirrorBlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(MirrorBlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.job_type = BLOCK_JOB_TYPE_MIRROR,
|
|
|
357786 |
.start = mirror_run,
|
|
|
357786 |
.complete = mirror_complete,
|
|
|
357786 |
@@ -996,7 +998,9 @@ static const BlockJobDriver mirror_job_driver = {
|
|
|
357786 |
};
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver commit_active_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(MirrorBlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(MirrorBlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.job_type = BLOCK_JOB_TYPE_COMMIT,
|
|
|
357786 |
.start = mirror_run,
|
|
|
357786 |
.complete = mirror_complete,
|
|
|
357786 |
diff --git a/block/stream.c b/block/stream.c
|
|
|
357786 |
index df9660d..f88fc75 100644
|
|
|
357786 |
--- a/block/stream.c
|
|
|
357786 |
+++ b/block/stream.c
|
|
|
357786 |
@@ -209,7 +209,9 @@ out:
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver stream_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(StreamBlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(StreamBlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.job_type = BLOCK_JOB_TYPE_STREAM,
|
|
|
357786 |
.start = stream_run,
|
|
|
357786 |
};
|
|
|
357786 |
diff --git a/blockjob.c b/blockjob.c
|
|
|
357786 |
index 112672a..1464856 100644
|
|
|
357786 |
--- a/blockjob.c
|
|
|
357786 |
+++ b/blockjob.c
|
|
|
357786 |
@@ -34,7 +34,6 @@
|
|
|
357786 |
#include "qapi/qapi-events-block-core.h"
|
|
|
357786 |
#include "qapi/qmp/qerror.h"
|
|
|
357786 |
#include "qemu/coroutine.h"
|
|
|
357786 |
-#include "qemu/id.h"
|
|
|
357786 |
#include "qemu/timer.h"
|
|
|
357786 |
|
|
|
357786 |
/* Right now, this mutex is only needed to synchronize accesses to job->busy
|
|
|
357786 |
@@ -92,7 +91,8 @@ static int block_job_apply_verb(BlockJob *job, BlockJobVerb bv, Error **errp)
|
|
|
357786 |
return 0;
|
|
|
357786 |
}
|
|
|
357786 |
error_setg(errp, "Job '%s' in state '%s' cannot accept command verb '%s'",
|
|
|
357786 |
- job->id, BlockJobStatus_str(job->status), BlockJobVerb_str(bv));
|
|
|
357786 |
+ job->job.id, BlockJobStatus_str(job->status),
|
|
|
357786 |
+ BlockJobVerb_str(bv));
|
|
|
357786 |
return -EPERM;
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
@@ -159,7 +159,7 @@ BlockJob *block_job_get(const char *id)
|
|
|
357786 |
BlockJob *job;
|
|
|
357786 |
|
|
|
357786 |
QLIST_FOREACH(job, &block_jobs, job_list) {
|
|
|
357786 |
- if (job->id && !strcmp(id, job->id)) {
|
|
|
357786 |
+ if (job->job.id && !strcmp(id, job->job.id)) {
|
|
|
357786 |
return job;
|
|
|
357786 |
}
|
|
|
357786 |
}
|
|
|
357786 |
@@ -261,7 +261,7 @@ void block_job_unref(BlockJob *job)
|
|
|
357786 |
block_job_detach_aio_context, job);
|
|
|
357786 |
blk_unref(job->blk);
|
|
|
357786 |
error_free(job->blocker);
|
|
|
357786 |
- g_free(job->id);
|
|
|
357786 |
+ g_free(job->job.id);
|
|
|
357786 |
assert(!timer_pending(&job->sleep_timer));
|
|
|
357786 |
g_free(job);
|
|
|
357786 |
}
|
|
|
357786 |
@@ -311,7 +311,7 @@ static char *child_job_get_parent_desc(BdrvChild *c)
|
|
|
357786 |
BlockJob *job = c->opaque;
|
|
|
357786 |
return g_strdup_printf("%s job '%s'",
|
|
|
357786 |
BlockJobType_str(job->driver->job_type),
|
|
|
357786 |
- job->id);
|
|
|
357786 |
+ job->job.id);
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static void child_job_drained_begin(BdrvChild *c)
|
|
|
357786 |
@@ -365,7 +365,7 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
|
|
357786 |
|
|
|
357786 |
bool block_job_is_internal(BlockJob *job)
|
|
|
357786 |
{
|
|
|
357786 |
- return (job->id == NULL);
|
|
|
357786 |
+ return (job->job.id == NULL);
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static bool block_job_started(BlockJob *job)
|
|
|
357786 |
@@ -705,13 +705,13 @@ int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
|
|
|
357786 |
void block_job_complete(BlockJob *job, Error **errp)
|
|
|
357786 |
{
|
|
|
357786 |
/* Should not be reachable via external interface for internal jobs */
|
|
|
357786 |
- assert(job->id);
|
|
|
357786 |
+ assert(job->job.id);
|
|
|
357786 |
if (block_job_apply_verb(job, BLOCK_JOB_VERB_COMPLETE, errp)) {
|
|
|
357786 |
return;
|
|
|
357786 |
}
|
|
|
357786 |
if (job->pause_count || job->cancelled || !job->driver->complete) {
|
|
|
357786 |
error_setg(errp, "The active block job '%s' cannot be completed",
|
|
|
357786 |
- job->id);
|
|
|
357786 |
+ job->job.id);
|
|
|
357786 |
return;
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
@@ -720,7 +720,7 @@ void block_job_complete(BlockJob *job, Error **errp)
|
|
|
357786 |
|
|
|
357786 |
void block_job_finalize(BlockJob *job, Error **errp)
|
|
|
357786 |
{
|
|
|
357786 |
- assert(job && job->id);
|
|
|
357786 |
+ assert(job && job->job.id);
|
|
|
357786 |
if (block_job_apply_verb(job, BLOCK_JOB_VERB_FINALIZE, errp)) {
|
|
|
357786 |
return;
|
|
|
357786 |
}
|
|
|
357786 |
@@ -731,7 +731,7 @@ void block_job_dismiss(BlockJob **jobptr, Error **errp)
|
|
|
357786 |
{
|
|
|
357786 |
BlockJob *job = *jobptr;
|
|
|
357786 |
/* similarly to _complete, this is QMP-interface only. */
|
|
|
357786 |
- assert(job->id);
|
|
|
357786 |
+ assert(job->job.id);
|
|
|
357786 |
if (block_job_apply_verb(job, BLOCK_JOB_VERB_DISMISS, errp)) {
|
|
|
357786 |
return;
|
|
|
357786 |
}
|
|
|
357786 |
@@ -848,7 +848,7 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
|
|
|
357786 |
}
|
|
|
357786 |
info = g_new0(BlockJobInfo, 1);
|
|
|
357786 |
info->type = g_strdup(BlockJobType_str(job->driver->job_type));
|
|
|
357786 |
- info->device = g_strdup(job->id);
|
|
|
357786 |
+ info->device = g_strdup(job->job.id);
|
|
|
357786 |
info->len = job->len;
|
|
|
357786 |
info->busy = atomic_read(&job->busy);
|
|
|
357786 |
info->paused = job->pause_count > 0;
|
|
|
357786 |
@@ -879,7 +879,7 @@ static void block_job_event_cancelled(BlockJob *job)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
qapi_event_send_block_job_cancelled(job->driver->job_type,
|
|
|
357786 |
- job->id,
|
|
|
357786 |
+ job->job.id,
|
|
|
357786 |
job->len,
|
|
|
357786 |
job->offset,
|
|
|
357786 |
job->speed,
|
|
|
357786 |
@@ -893,7 +893,7 @@ static void block_job_event_completed(BlockJob *job, const char *msg)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
qapi_event_send_block_job_completed(job->driver->job_type,
|
|
|
357786 |
- job->id,
|
|
|
357786 |
+ job->job.id,
|
|
|
357786 |
job->len,
|
|
|
357786 |
job->offset,
|
|
|
357786 |
job->speed,
|
|
|
357786 |
@@ -907,7 +907,7 @@ static int block_job_event_pending(BlockJob *job)
|
|
|
357786 |
block_job_state_transition(job, BLOCK_JOB_STATUS_PENDING);
|
|
|
357786 |
if (!job->auto_finalize && !block_job_is_internal(job)) {
|
|
|
357786 |
qapi_event_send_block_job_pending(job->driver->job_type,
|
|
|
357786 |
- job->id,
|
|
|
357786 |
+ job->job.id,
|
|
|
357786 |
&error_abort);
|
|
|
357786 |
}
|
|
|
357786 |
return 0;
|
|
|
357786 |
@@ -945,12 +945,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|
|
357786 |
error_setg(errp, "Cannot specify job ID for internal block job");
|
|
|
357786 |
return NULL;
|
|
|
357786 |
}
|
|
|
357786 |
-
|
|
|
357786 |
- if (!id_wellformed(job_id)) {
|
|
|
357786 |
- error_setg(errp, "Invalid job ID '%s'", job_id);
|
|
|
357786 |
- return NULL;
|
|
|
357786 |
- }
|
|
|
357786 |
-
|
|
|
357786 |
if (block_job_get(job_id)) {
|
|
|
357786 |
error_setg(errp, "Job ID '%s' already in use", job_id);
|
|
|
357786 |
return NULL;
|
|
|
357786 |
@@ -964,9 +958,13 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|
|
357786 |
return NULL;
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
- job = g_malloc0(driver->instance_size);
|
|
|
357786 |
+ job = job_create(job_id, &driver->job_driver, errp);
|
|
|
357786 |
+ if (job == NULL) {
|
|
|
357786 |
+ blk_unref(blk);
|
|
|
357786 |
+ return NULL;
|
|
|
357786 |
+ }
|
|
|
357786 |
+
|
|
|
357786 |
job->driver = driver;
|
|
|
357786 |
- job->id = g_strdup(job_id);
|
|
|
357786 |
job->blk = blk;
|
|
|
357786 |
job->cb = cb;
|
|
|
357786 |
job->opaque = opaque;
|
|
|
357786 |
@@ -1187,7 +1185,7 @@ void block_job_event_ready(BlockJob *job)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
qapi_event_send_block_job_ready(job->driver->job_type,
|
|
|
357786 |
- job->id,
|
|
|
357786 |
+ job->job.id,
|
|
|
357786 |
job->len,
|
|
|
357786 |
job->offset,
|
|
|
357786 |
job->speed, &error_abort);
|
|
|
357786 |
@@ -1217,7 +1215,7 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
|
|
|
357786 |
abort();
|
|
|
357786 |
}
|
|
|
357786 |
if (!block_job_is_internal(job)) {
|
|
|
357786 |
- qapi_event_send_block_job_error(job->id,
|
|
|
357786 |
+ qapi_event_send_block_job_error(job->job.id,
|
|
|
357786 |
is_read ? IO_OPERATION_TYPE_READ :
|
|
|
357786 |
IO_OPERATION_TYPE_WRITE,
|
|
|
357786 |
action, &error_abort);
|
|
|
357786 |
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
|
|
|
357786 |
index 0f56f72..640e649 100644
|
|
|
357786 |
--- a/include/block/blockjob.h
|
|
|
357786 |
+++ b/include/block/blockjob.h
|
|
|
357786 |
@@ -26,6 +26,7 @@
|
|
|
357786 |
#ifndef BLOCKJOB_H
|
|
|
357786 |
#define BLOCKJOB_H
|
|
|
357786 |
|
|
|
357786 |
+#include "qemu/job.h"
|
|
|
357786 |
#include "block/block.h"
|
|
|
357786 |
#include "qemu/ratelimit.h"
|
|
|
357786 |
|
|
|
357786 |
@@ -40,6 +41,9 @@ typedef struct BlockJobTxn BlockJobTxn;
|
|
|
357786 |
* Long-running operation on a BlockDriverState.
|
|
|
357786 |
*/
|
|
|
357786 |
typedef struct BlockJob {
|
|
|
357786 |
+ /** Data belonging to the generic Job infrastructure */
|
|
|
357786 |
+ Job job;
|
|
|
357786 |
+
|
|
|
357786 |
/** The job type, including the job vtable. */
|
|
|
357786 |
const BlockJobDriver *driver;
|
|
|
357786 |
|
|
|
357786 |
@@ -47,11 +51,6 @@ typedef struct BlockJob {
|
|
|
357786 |
BlockBackend *blk;
|
|
|
357786 |
|
|
|
357786 |
/**
|
|
|
357786 |
- * The ID of the block job. May be NULL for internal jobs.
|
|
|
357786 |
- */
|
|
|
357786 |
- char *id;
|
|
|
357786 |
-
|
|
|
357786 |
- /**
|
|
|
357786 |
* The coroutine that executes the job. If not NULL, it is
|
|
|
357786 |
* reentered when busy is false and the job is cancelled.
|
|
|
357786 |
*/
|
|
|
357786 |
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
|
|
|
357786 |
index 62ec964..e8eca44 100644
|
|
|
357786 |
--- a/include/block/blockjob_int.h
|
|
|
357786 |
+++ b/include/block/blockjob_int.h
|
|
|
357786 |
@@ -35,8 +35,8 @@
|
|
|
357786 |
* A class type for block job driver.
|
|
|
357786 |
*/
|
|
|
357786 |
struct BlockJobDriver {
|
|
|
357786 |
- /** Derived BlockJob struct size */
|
|
|
357786 |
- size_t instance_size;
|
|
|
357786 |
+ /** Generic JobDriver callbacks and settings */
|
|
|
357786 |
+ JobDriver job_driver;
|
|
|
357786 |
|
|
|
357786 |
/** String describing the operation, part of query-block-jobs QMP API */
|
|
|
357786 |
BlockJobType job_type;
|
|
|
357786 |
diff --git a/include/qemu/job.h b/include/qemu/job.h
|
|
|
357786 |
new file mode 100644
|
|
|
357786 |
index 0000000..b4b49f1
|
|
|
357786 |
--- /dev/null
|
|
|
357786 |
+++ b/include/qemu/job.h
|
|
|
357786 |
@@ -0,0 +1,60 @@
|
|
|
357786 |
+/*
|
|
|
357786 |
+ * Declarations for background jobs
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * Copyright (c) 2011 IBM Corp.
|
|
|
357786 |
+ * Copyright (c) 2012, 2018 Red Hat, Inc.
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
357786 |
+ * of this software and associated documentation files (the "Software"), to deal
|
|
|
357786 |
+ * in the Software without restriction, including without limitation the rights
|
|
|
357786 |
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
357786 |
+ * copies of the Software, and to permit persons to whom the Software is
|
|
|
357786 |
+ * furnished to do so, subject to the following conditions:
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * The above copyright notice and this permission notice shall be included in
|
|
|
357786 |
+ * all copies or substantial portions of the Software.
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
357786 |
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
357786 |
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
357786 |
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
357786 |
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
357786 |
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
357786 |
+ * THE SOFTWARE.
|
|
|
357786 |
+ */
|
|
|
357786 |
+
|
|
|
357786 |
+#ifndef JOB_H
|
|
|
357786 |
+#define JOB_H
|
|
|
357786 |
+
|
|
|
357786 |
+typedef struct JobDriver JobDriver;
|
|
|
357786 |
+
|
|
|
357786 |
+/**
|
|
|
357786 |
+ * Long-running operation.
|
|
|
357786 |
+ */
|
|
|
357786 |
+typedef struct Job {
|
|
|
357786 |
+ /** The ID of the job. May be NULL for internal jobs. */
|
|
|
357786 |
+ char *id;
|
|
|
357786 |
+
|
|
|
357786 |
+ /** The type of this job. */
|
|
|
357786 |
+ const JobDriver *driver;
|
|
|
357786 |
+} Job;
|
|
|
357786 |
+
|
|
|
357786 |
+/**
|
|
|
357786 |
+ * Callbacks and other information about a Job driver.
|
|
|
357786 |
+ */
|
|
|
357786 |
+struct JobDriver {
|
|
|
357786 |
+ /** Derived Job struct size */
|
|
|
357786 |
+ size_t instance_size;
|
|
|
357786 |
+};
|
|
|
357786 |
+
|
|
|
357786 |
+
|
|
|
357786 |
+/**
|
|
|
357786 |
+ * Create a new long-running job and return it.
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * @job_id: The id of the newly-created job, or %NULL for internal jobs
|
|
|
357786 |
+ * @driver: The class object for the newly-created job.
|
|
|
357786 |
+ * @errp: Error object.
|
|
|
357786 |
+ */
|
|
|
357786 |
+void *job_create(const char *job_id, const JobDriver *driver, Error **errp);
|
|
|
357786 |
+
|
|
|
357786 |
+#endif
|
|
|
357786 |
diff --git a/job.c b/job.c
|
|
|
357786 |
new file mode 100644
|
|
|
357786 |
index 0000000..87fd484
|
|
|
357786 |
--- /dev/null
|
|
|
357786 |
+++ b/job.c
|
|
|
357786 |
@@ -0,0 +1,48 @@
|
|
|
357786 |
+/*
|
|
|
357786 |
+ * Background jobs (long-running operations)
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * Copyright (c) 2011 IBM Corp.
|
|
|
357786 |
+ * Copyright (c) 2012, 2018 Red Hat, Inc.
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
357786 |
+ * of this software and associated documentation files (the "Software"), to deal
|
|
|
357786 |
+ * in the Software without restriction, including without limitation the rights
|
|
|
357786 |
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
357786 |
+ * copies of the Software, and to permit persons to whom the Software is
|
|
|
357786 |
+ * furnished to do so, subject to the following conditions:
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * The above copyright notice and this permission notice shall be included in
|
|
|
357786 |
+ * all copies or substantial portions of the Software.
|
|
|
357786 |
+ *
|
|
|
357786 |
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
357786 |
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
357786 |
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
357786 |
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
357786 |
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
357786 |
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
357786 |
+ * THE SOFTWARE.
|
|
|
357786 |
+ */
|
|
|
357786 |
+
|
|
|
357786 |
+#include "qemu/osdep.h"
|
|
|
357786 |
+#include "qemu-common.h"
|
|
|
357786 |
+#include "qapi/error.h"
|
|
|
357786 |
+#include "qemu/job.h"
|
|
|
357786 |
+#include "qemu/id.h"
|
|
|
357786 |
+
|
|
|
357786 |
+void *job_create(const char *job_id, const JobDriver *driver, Error **errp)
|
|
|
357786 |
+{
|
|
|
357786 |
+ Job *job;
|
|
|
357786 |
+
|
|
|
357786 |
+ if (job_id) {
|
|
|
357786 |
+ if (!id_wellformed(job_id)) {
|
|
|
357786 |
+ error_setg(errp, "Invalid job ID '%s'", job_id);
|
|
|
357786 |
+ return NULL;
|
|
|
357786 |
+ }
|
|
|
357786 |
+ }
|
|
|
357786 |
+
|
|
|
357786 |
+ job = g_malloc0(driver->instance_size);
|
|
|
357786 |
+ job->driver = driver;
|
|
|
357786 |
+ job->id = g_strdup(job_id);
|
|
|
357786 |
+
|
|
|
357786 |
+ return job;
|
|
|
357786 |
+}
|
|
|
357786 |
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
|
|
|
357786 |
index 7673de1..fe9f412 100644
|
|
|
357786 |
--- a/tests/test-bdrv-drain.c
|
|
|
357786 |
+++ b/tests/test-bdrv-drain.c
|
|
|
357786 |
@@ -520,7 +520,9 @@ static void test_job_complete(BlockJob *job, Error **errp)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
BlockJobDriver test_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(TestBlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(TestBlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.start = test_job_start,
|
|
|
357786 |
.complete = test_job_complete,
|
|
|
357786 |
};
|
|
|
357786 |
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
|
|
|
357786 |
index 5789893..48b12d1 100644
|
|
|
357786 |
--- a/tests/test-blockjob-txn.c
|
|
|
357786 |
+++ b/tests/test-blockjob-txn.c
|
|
|
357786 |
@@ -74,7 +74,9 @@ static void test_block_job_cb(void *opaque, int ret)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver test_block_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(TestBlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(TestBlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.start = test_block_job_run,
|
|
|
357786 |
};
|
|
|
357786 |
|
|
|
357786 |
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
|
|
|
357786 |
index 8946bfd..b820261 100644
|
|
|
357786 |
--- a/tests/test-blockjob.c
|
|
|
357786 |
+++ b/tests/test-blockjob.c
|
|
|
357786 |
@@ -17,7 +17,9 @@
|
|
|
357786 |
#include "sysemu/block-backend.h"
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver test_block_job_driver = {
|
|
|
357786 |
- .instance_size = sizeof(BlockJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(BlockJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
};
|
|
|
357786 |
|
|
|
357786 |
static void block_job_cb(void *opaque, int ret)
|
|
|
357786 |
@@ -38,9 +40,9 @@ static BlockJob *mk_job(BlockBackend *blk, const char *id,
|
|
|
357786 |
g_assert_null(errp);
|
|
|
357786 |
g_assert_nonnull(job);
|
|
|
357786 |
if (id) {
|
|
|
357786 |
- g_assert_cmpstr(job->id, ==, id);
|
|
|
357786 |
+ g_assert_cmpstr(job->job.id, ==, id);
|
|
|
357786 |
} else {
|
|
|
357786 |
- g_assert_cmpstr(job->id, ==, blk_name(blk));
|
|
|
357786 |
+ g_assert_cmpstr(job->job.id, ==, blk_name(blk));
|
|
|
357786 |
}
|
|
|
357786 |
} else {
|
|
|
357786 |
g_assert_nonnull(errp);
|
|
|
357786 |
@@ -192,7 +194,9 @@ static void coroutine_fn cancel_job_start(void *opaque)
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static const BlockJobDriver test_cancel_driver = {
|
|
|
357786 |
- .instance_size = sizeof(CancelJob),
|
|
|
357786 |
+ .job_driver = {
|
|
|
357786 |
+ .instance_size = sizeof(CancelJob),
|
|
|
357786 |
+ },
|
|
|
357786 |
.start = cancel_job_start,
|
|
|
357786 |
.complete = cancel_job_complete,
|
|
|
357786 |
};
|
|
|
357786 |
--
|
|
|
357786 |
1.8.3.1
|
|
|
357786 |
|