Blame SOURCES/kvm-job-Create-Job-JobDriver-and-job_create.patch

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