yeahuh / rpms / qemu-kvm

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