* [PATCH v2 1/3] jobs: add job-common.h
2022-02-08 14:39 [PATCH v2 0/3] job: split job API in driver and monitor Emanuele Giuseppe Esposito
@ 2022-02-08 14:39 ` Emanuele Giuseppe Esposito
2022-02-08 14:39 ` [PATCH v2 2/3] jobs: add job-monitor.h Emanuele Giuseppe Esposito
2022-02-08 14:39 ` [PATCH v2 3/3] jobs: add job-driver.h Emanuele Giuseppe Esposito
2 siblings, 0 replies; 4+ messages in thread
From: Emanuele Giuseppe Esposito @ 2022-02-08 14:39 UTC (permalink / raw)
To: qemu-block
Cc: Emanuele Giuseppe Esposito, Vladimir Sementsov-Ogievskiy,
qemu-devel, Stefan Hajnoczi, Paolo Bonzini, John Snow
job-common.h contains all struct and common function that currently
are in job.h and will be shared by job-monitor and job-driver in
the next commits.
Also move job_type(), job_type_str() and job_is_internal there,
as they are common helper functions.
No functional change intended.
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
---
include/qemu/job-common.h | 357 ++++++++++++++++++++++++++++++++++++++
include/qemu/job.h | 328 +---------------------------------
2 files changed, 358 insertions(+), 327 deletions(-)
create mode 100644 include/qemu/job-common.h
diff --git a/include/qemu/job-common.h b/include/qemu/job-common.h
new file mode 100644
index 0000000000..e9505c864a
--- /dev/null
+++ b/include/qemu/job-common.h
@@ -0,0 +1,357 @@
+/*
+ * Declarations for background jobs
+ *
+ * Copyright (c) 2011 IBM Corp.
+ * Copyright (c) 2012, 2018 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef JOB_COMMON_H
+#define JOB_COMMON_H
+
+#include "qapi/qapi-types-job.h"
+#include "qemu/queue.h"
+#include "qemu/progress_meter.h"
+#include "qemu/coroutine.h"
+#include "block/aio.h"
+
+typedef struct JobDriver JobDriver;
+typedef struct JobTxn JobTxn;
+
+
+/**
+ * Long-running operation.
+ */
+typedef struct Job {
+
+ /* Fields set at initialization (job_create), and never modified */
+
+ /** The ID of the job. May be NULL for internal jobs. */
+ char *id;
+
+ /**
+ * The type of this job.
+ * All callbacks are called with job_mutex *not* held.
+ */
+ const JobDriver *driver;
+
+ /**
+ * The coroutine that executes the job. If not NULL, it is reentered when
+ * busy is false and the job is cancelled.
+ * Initialized in job_start()
+ */
+ Coroutine *co;
+
+ /** True if this job should automatically finalize itself */
+ bool auto_finalize;
+
+ /** True if this job should automatically dismiss itself */
+ bool auto_dismiss;
+
+ /** The completion function that will be called when the job completes. */
+ BlockCompletionFunc *cb;
+
+ /** The opaque value that is passed to the completion function. */
+ void *opaque;
+
+ /* ProgressMeter API is thread-safe */
+ ProgressMeter progress;
+
+
+ /** Protected by job_mutex */
+
+ /**
+ * AioContext to run the job coroutine in.
+ * The job Aiocontext can be read when holding *either*
+ * the BQL (so we are in the main loop) or the job_mutex.
+ * Instead, it can only be written when we hold *both* BQL
+ * and the job_mutex.
+ */
+ AioContext *aio_context;
+
+ /** Reference count of the block job */
+ int refcnt;
+
+ /** Current state; See @JobStatus for details. */
+ JobStatus status;
+
+ /**
+ * Timer that is used by @job_sleep_ns. Accessed under job_mutex (in
+ * job.c).
+ */
+ QEMUTimer sleep_timer;
+
+ /**
+ * Counter for pause request. If non-zero, the block job is either paused,
+ * or if busy == true will pause itself as soon as possible.
+ */
+ int pause_count;
+
+ /**
+ * Set to false by the job while the coroutine has yielded and may be
+ * re-entered by job_enter(). There may still be I/O or event loop activity
+ * pending. Accessed under job_mutex.
+ *
+ * When the job is deferred to the main loop, busy is true as long as the
+ * bottom half is still pending.
+ */
+ bool busy;
+
+ /**
+ * Set to true by the job while it is in a quiescent state, where
+ * no I/O or event loop activity is pending.
+ */
+ bool paused;
+
+ /**
+ * Set to true if the job is paused by user. Can be unpaused with the
+ * block-job-resume QMP command.
+ */
+ bool user_paused;
+
+ /**
+ * Set to true if the job should cancel itself. The flag must
+ * always be tested just before toggling the busy flag from false
+ * to true. After a job has been cancelled, it should only yield
+ * if #aio_poll will ("sooner or later") reenter the coroutine.
+ */
+ bool cancelled;
+
+ /**
+ * Set to true if the job should abort immediately without waiting
+ * for data to be in sync.
+ */
+ bool force_cancel;
+
+ /** Set to true when the job has deferred work to the main loop. */
+ bool deferred_to_main_loop;
+
+ /**
+ * Return code from @run and/or @prepare callback(s).
+ * Not final until the job has reached the CONCLUDED status.
+ * 0 on success, -errno on failure.
+ */
+ int ret;
+
+ /**
+ * Error object for a failed job.
+ * If job->ret is nonzero and an error object was not set, it will be set
+ * to strerror(-job->ret) during job_completed.
+ */
+ Error *err;
+
+ /** Notifiers called when a cancelled job is finalised */
+ NotifierList on_finalize_cancelled;
+
+ /** Notifiers called when a successfully completed job is finalised */
+ NotifierList on_finalize_completed;
+
+ /** Notifiers called when the job transitions to PENDING */
+ NotifierList on_pending;
+
+ /** Notifiers called when the job transitions to READY */
+ NotifierList on_ready;
+
+ /** Notifiers called when the job coroutine yields or terminates */
+ NotifierList on_idle;
+
+ /** Element of the list of jobs */
+ QLIST_ENTRY(Job) job_list;
+
+ /** Transaction this job is part of */
+ JobTxn *txn;
+
+ /** Element of the list of jobs in a job transaction */
+ QLIST_ENTRY(Job) txn_list;
+} Job;
+
+/**
+ * Callbacks and other information about a Job driver.
+ * All callbacks are invoked with job_mutex *not* held.
+ */
+struct JobDriver {
+
+ /*
+ * These fields are initialized when this object is created,
+ * and are never changed afterwards
+ */
+
+ /** Derived Job struct size */
+ size_t instance_size;
+
+ /** Enum describing the operation */
+ JobType job_type;
+
+ /**
+ * Mandatory: Entrypoint for the Coroutine.
+ *
+ * This callback will be invoked when moving from CREATED to RUNNING.
+ *
+ * If this callback returns nonzero, the job transaction it is part of is
+ * aborted. If it returns zero, the job moves into the WAITING state. If it
+ * is the last job to complete in its transaction, all jobs in the
+ * transaction move from WAITING to PENDING.
+ *
+ * This callback must be run in the job's context.
+ */
+ int coroutine_fn (*run)(Job *job, Error **errp);
+
+ /*
+ * Functions run without regard to the BQL that may run in any
+ * arbitrary thread. These functions do not need to be thread-safe
+ * because the caller ensures that they are invoked from one
+ * thread at time.
+ */
+
+ /**
+ * If the callback is not NULL, it will be invoked when the job transitions
+ * into the paused state. Paused jobs must not perform any asynchronous
+ * I/O or event loop activity. This callback is used to quiesce jobs.
+ */
+ void coroutine_fn (*pause)(Job *job);
+
+ /**
+ * If the callback is not NULL, it will be invoked when the job transitions
+ * out of the paused state. Any asynchronous I/O or event loop activity
+ * should be restarted from this callback.
+ */
+ void coroutine_fn (*resume)(Job *job);
+
+ /*
+ * Global state (GS) API. These functions run under the BQL.
+ *
+ * See include/block/block-global-state.h for more information about
+ * the GS API.
+ */
+
+ /**
+ * Called when the job is resumed by the user (i.e. user_paused becomes
+ * false). .user_resume is called before .resume.
+ */
+ void (*user_resume)(Job *job);
+
+ /**
+ * Optional callback for job types whose completion must be triggered
+ * manually.
+ */
+ void (*complete)(Job *job, Error **errp);
+
+ /**
+ * If the callback is not NULL, prepare will be invoked when all the jobs
+ * belonging to the same transaction complete; or upon this job's completion
+ * if it is not in a transaction.
+ *
+ * This callback will not be invoked if the job has already failed.
+ * If it fails, abort and then clean will be called.
+ */
+ int (*prepare)(Job *job);
+
+ /**
+ * If the callback is not NULL, it will be invoked when all the jobs
+ * belonging to the same transaction complete; or upon this job's
+ * completion if it is not in a transaction. Skipped if NULL.
+ *
+ * All jobs will complete with a call to either .commit() or .abort() but
+ * never both.
+ */
+ void (*commit)(Job *job);
+
+ /**
+ * If the callback is not NULL, it will be invoked when any job in the
+ * same transaction fails; or upon this job's failure (due to error or
+ * cancellation) if it is not in a transaction. Skipped if NULL.
+ *
+ * All jobs will complete with a call to either .commit() or .abort() but
+ * never both.
+ */
+ void (*abort)(Job *job);
+
+ /**
+ * If the callback is not NULL, it will be invoked after a call to either
+ * .commit() or .abort(). Regardless of which callback is invoked after
+ * completion, .clean() will always be called, even if the job does not
+ * belong to a transaction group.
+ */
+ void (*clean)(Job *job);
+
+ /**
+ * If the callback is not NULL, it will be invoked in job_cancel_async
+ *
+ * This function must return true if the job will be cancelled
+ * immediately without any further I/O (mandatory if @force is
+ * true), and false otherwise. This lets the generic job layer
+ * know whether a job has been truly (force-)cancelled, or whether
+ * it is just in a special completion mode (like mirror after
+ * READY).
+ * (If the callback is NULL, the job is assumed to terminate
+ * without I/O.)
+ */
+ bool (*cancel)(Job *job, bool force);
+
+
+ /** Called when the job is freed */
+ void (*free)(Job *job);
+};
+
+typedef enum JobCreateFlags {
+ /* Default behavior */
+ JOB_DEFAULT = 0x00,
+ /* Job is not QMP-created and should not send QMP events */
+ JOB_INTERNAL = 0x01,
+ /* Job requires manual finalize step */
+ JOB_MANUAL_FINALIZE = 0x02,
+ /* Job requires manual dismiss step */
+ JOB_MANUAL_DISMISS = 0x04,
+} JobCreateFlags;
+
+extern QemuMutex job_mutex;
+
+#define JOB_LOCK_GUARD() QEMU_LOCK_GUARD(&job_mutex)
+
+#define WITH_JOB_LOCK_GUARD() WITH_QEMU_LOCK_GUARD(&job_mutex)
+
+/**
+ * job_lock:
+ *
+ * Take the mutex protecting the list of jobs and their status.
+ * Most functions called by the monitor need to call job_lock
+ * and job_unlock manually. On the other hand, function called
+ * by the block jobs themselves and by the block layer will take the
+ * lock for you.
+ */
+void job_lock(void);
+
+/**
+ * job_unlock:
+ *
+ * Release the mutex protecting the list of jobs and their status.
+ */
+void job_unlock(void);
+
+/** Returns the JobType of a given Job. */
+JobType job_type(const Job *job);
+
+/** Returns the enum string for the JobType of a given Job. */
+const char *job_type_str(const Job *job);
+
+/** Returns true if the job should not be visible to the management layer. */
+bool job_is_internal(Job *job);
+
+#endif
diff --git a/include/qemu/job.h b/include/qemu/job.h
index 574110a1f2..cdfc603706 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -26,324 +26,7 @@
#ifndef JOB_H
#define JOB_H
-#include "qapi/qapi-types-job.h"
-#include "qemu/queue.h"
-#include "qemu/progress_meter.h"
-#include "qemu/coroutine.h"
-#include "block/aio.h"
-
-typedef struct JobDriver JobDriver;
-typedef struct JobTxn JobTxn;
-
-
-/**
- * Long-running operation.
- */
-typedef struct Job {
-
- /* Fields set at initialization (job_create), and never modified */
-
- /** The ID of the job. May be NULL for internal jobs. */
- char *id;
-
- /**
- * The type of this job.
- * All callbacks are called with job_mutex *not* held.
- */
- const JobDriver *driver;
-
- /**
- * The coroutine that executes the job. If not NULL, it is reentered when
- * busy is false and the job is cancelled.
- * Initialized in job_start()
- */
- Coroutine *co;
-
- /** True if this job should automatically finalize itself */
- bool auto_finalize;
-
- /** True if this job should automatically dismiss itself */
- bool auto_dismiss;
-
- /** The completion function that will be called when the job completes. */
- BlockCompletionFunc *cb;
-
- /** The opaque value that is passed to the completion function. */
- void *opaque;
-
- /* ProgressMeter API is thread-safe */
- ProgressMeter progress;
-
-
- /** Protected by job_mutex */
-
- /**
- * AioContext to run the job coroutine in.
- * The job Aiocontext can be read when holding *either*
- * the BQL (so we are in the main loop) or the job_mutex.
- * Instead, it can only be written when we hold *both* BQL
- * and the job_mutex.
- */
- AioContext *aio_context;
-
- /** Reference count of the block job */
- int refcnt;
-
- /** Current state; See @JobStatus for details. */
- JobStatus status;
-
- /**
- * Timer that is used by @job_sleep_ns. Accessed under job_mutex (in
- * job.c).
- */
- QEMUTimer sleep_timer;
-
- /**
- * Counter for pause request. If non-zero, the block job is either paused,
- * or if busy == true will pause itself as soon as possible.
- */
- int pause_count;
-
- /**
- * Set to false by the job while the coroutine has yielded and may be
- * re-entered by job_enter(). There may still be I/O or event loop activity
- * pending. Accessed under job_mutex.
- *
- * When the job is deferred to the main loop, busy is true as long as the
- * bottom half is still pending.
- */
- bool busy;
-
- /**
- * Set to true by the job while it is in a quiescent state, where
- * no I/O or event loop activity is pending.
- */
- bool paused;
-
- /**
- * Set to true if the job is paused by user. Can be unpaused with the
- * block-job-resume QMP command.
- */
- bool user_paused;
-
- /**
- * Set to true if the job should cancel itself. The flag must
- * always be tested just before toggling the busy flag from false
- * to true. After a job has been cancelled, it should only yield
- * if #aio_poll will ("sooner or later") reenter the coroutine.
- */
- bool cancelled;
-
- /**
- * Set to true if the job should abort immediately without waiting
- * for data to be in sync.
- */
- bool force_cancel;
-
- /** Set to true when the job has deferred work to the main loop. */
- bool deferred_to_main_loop;
-
- /**
- * Return code from @run and/or @prepare callback(s).
- * Not final until the job has reached the CONCLUDED status.
- * 0 on success, -errno on failure.
- */
- int ret;
-
- /**
- * Error object for a failed job.
- * If job->ret is nonzero and an error object was not set, it will be set
- * to strerror(-job->ret) during job_completed.
- */
- Error *err;
-
- /** Notifiers called when a cancelled job is finalised */
- NotifierList on_finalize_cancelled;
-
- /** Notifiers called when a successfully completed job is finalised */
- NotifierList on_finalize_completed;
-
- /** Notifiers called when the job transitions to PENDING */
- NotifierList on_pending;
-
- /** Notifiers called when the job transitions to READY */
- NotifierList on_ready;
-
- /** Notifiers called when the job coroutine yields or terminates */
- NotifierList on_idle;
-
- /** Element of the list of jobs */
- QLIST_ENTRY(Job) job_list;
-
- /** Transaction this job is part of */
- JobTxn *txn;
-
- /** Element of the list of jobs in a job transaction */
- QLIST_ENTRY(Job) txn_list;
-} Job;
-
-/**
- * Callbacks and other information about a Job driver.
- * All callbacks are invoked with job_mutex *not* held.
- */
-struct JobDriver {
-
- /*
- * These fields are initialized when this object is created,
- * and are never changed afterwards
- */
-
- /** Derived Job struct size */
- size_t instance_size;
-
- /** Enum describing the operation */
- JobType job_type;
-
- /**
- * Mandatory: Entrypoint for the Coroutine.
- *
- * This callback will be invoked when moving from CREATED to RUNNING.
- *
- * If this callback returns nonzero, the job transaction it is part of is
- * aborted. If it returns zero, the job moves into the WAITING state. If it
- * is the last job to complete in its transaction, all jobs in the
- * transaction move from WAITING to PENDING.
- *
- * This callback must be run in the job's context.
- */
- int coroutine_fn (*run)(Job *job, Error **errp);
-
- /*
- * Functions run without regard to the BQL that may run in any
- * arbitrary thread. These functions do not need to be thread-safe
- * because the caller ensures that they are invoked from one
- * thread at time.
- */
-
- /**
- * If the callback is not NULL, it will be invoked when the job transitions
- * into the paused state. Paused jobs must not perform any asynchronous
- * I/O or event loop activity. This callback is used to quiesce jobs.
- */
- void coroutine_fn (*pause)(Job *job);
-
- /**
- * If the callback is not NULL, it will be invoked when the job transitions
- * out of the paused state. Any asynchronous I/O or event loop activity
- * should be restarted from this callback.
- */
- void coroutine_fn (*resume)(Job *job);
-
- /*
- * Global state (GS) API. These functions run under the BQL.
- *
- * See include/block/block-global-state.h for more information about
- * the GS API.
- */
-
- /**
- * Called when the job is resumed by the user (i.e. user_paused becomes
- * false). .user_resume is called before .resume.
- */
- void (*user_resume)(Job *job);
-
- /**
- * Optional callback for job types whose completion must be triggered
- * manually.
- */
- void (*complete)(Job *job, Error **errp);
-
- /**
- * If the callback is not NULL, prepare will be invoked when all the jobs
- * belonging to the same transaction complete; or upon this job's completion
- * if it is not in a transaction.
- *
- * This callback will not be invoked if the job has already failed.
- * If it fails, abort and then clean will be called.
- */
- int (*prepare)(Job *job);
-
- /**
- * If the callback is not NULL, it will be invoked when all the jobs
- * belonging to the same transaction complete; or upon this job's
- * completion if it is not in a transaction. Skipped if NULL.
- *
- * All jobs will complete with a call to either .commit() or .abort() but
- * never both.
- */
- void (*commit)(Job *job);
-
- /**
- * If the callback is not NULL, it will be invoked when any job in the
- * same transaction fails; or upon this job's failure (due to error or
- * cancellation) if it is not in a transaction. Skipped if NULL.
- *
- * All jobs will complete with a call to either .commit() or .abort() but
- * never both.
- */
- void (*abort)(Job *job);
-
- /**
- * If the callback is not NULL, it will be invoked after a call to either
- * .commit() or .abort(). Regardless of which callback is invoked after
- * completion, .clean() will always be called, even if the job does not
- * belong to a transaction group.
- */
- void (*clean)(Job *job);
-
- /**
- * If the callback is not NULL, it will be invoked in job_cancel_async
- *
- * This function must return true if the job will be cancelled
- * immediately without any further I/O (mandatory if @force is
- * true), and false otherwise. This lets the generic job layer
- * know whether a job has been truly (force-)cancelled, or whether
- * it is just in a special completion mode (like mirror after
- * READY).
- * (If the callback is NULL, the job is assumed to terminate
- * without I/O.)
- */
- bool (*cancel)(Job *job, bool force);
-
-
- /** Called when the job is freed */
- void (*free)(Job *job);
-};
-
-typedef enum JobCreateFlags {
- /* Default behavior */
- JOB_DEFAULT = 0x00,
- /* Job is not QMP-created and should not send QMP events */
- JOB_INTERNAL = 0x01,
- /* Job requires manual finalize step */
- JOB_MANUAL_FINALIZE = 0x02,
- /* Job requires manual dismiss step */
- JOB_MANUAL_DISMISS = 0x04,
-} JobCreateFlags;
-
-extern QemuMutex job_mutex;
-
-#define JOB_LOCK_GUARD() QEMU_LOCK_GUARD(&job_mutex)
-
-#define WITH_JOB_LOCK_GUARD() WITH_QEMU_LOCK_GUARD(&job_mutex)
-
-/**
- * job_lock:
- *
- * Take the mutex protecting the list of jobs and their status.
- * Most functions called by the monitor need to call job_lock
- * and job_unlock manually. On the other hand, function called
- * by the block jobs themselves and by the block layer will take the
- * lock for you.
- */
-void job_lock(void);
-
-/**
- * job_unlock:
- *
- * Release the mutex protecting the list of jobs and their status.
- */
-void job_unlock(void);
+#include "job-common.h"
/**
* Allocate and return a new job transaction. Jobs can be added to the
@@ -499,15 +182,6 @@ void job_yield(Job *job);
*/
void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
-/** Returns the JobType of a given Job. */
-JobType job_type(const Job *job);
-
-/** Returns the enum string for the JobType of a given Job. */
-const char *job_type_str(const Job *job);
-
-/** Returns true if the job should not be visible to the management layer. */
-bool job_is_internal(Job *job);
-
/**
* Returns whether the job is being cancelled.
* Called with job_mutex *not* held.
--
2.31.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] jobs: add job-monitor.h
2022-02-08 14:39 [PATCH v2 0/3] job: split job API in driver and monitor Emanuele Giuseppe Esposito
2022-02-08 14:39 ` [PATCH v2 1/3] jobs: add job-common.h Emanuele Giuseppe Esposito
@ 2022-02-08 14:39 ` Emanuele Giuseppe Esposito
2022-02-08 14:39 ` [PATCH v2 3/3] jobs: add job-driver.h Emanuele Giuseppe Esposito
2 siblings, 0 replies; 4+ messages in thread
From: Emanuele Giuseppe Esposito @ 2022-02-08 14:39 UTC (permalink / raw)
To: qemu-block
Cc: Emanuele Giuseppe Esposito, Vladimir Sementsov-Ogievskiy,
qemu-devel, Stefan Hajnoczi, Paolo Bonzini, John Snow
job-monitor.h contains all functions of job.h that are used by the
monitor and essentially all functions that do not define a
JobDriver/Blockdriver.
No functional change intended.
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
---
include/qemu/job-monitor.h | 249 +++++++++++++++++++++++++++++++++++++
include/qemu/job.h | 204 +-----------------------------
job.c | 1 +
3 files changed, 251 insertions(+), 203 deletions(-)
create mode 100644 include/qemu/job-monitor.h
diff --git a/include/qemu/job-monitor.h b/include/qemu/job-monitor.h
new file mode 100644
index 0000000000..58e99a9a47
--- /dev/null
+++ b/include/qemu/job-monitor.h
@@ -0,0 +1,249 @@
+/*
+ * Declarations for background jobs
+ *
+ * Copyright (c) 2011 IBM Corp.
+ * Copyright (c) 2012, 2018 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef JOB_MONITOR_H
+#define JOB_MONITOR_H
+
+#include "job-common.h"
+
+/*
+ * Job monitor API.
+ *
+ * These functions use are used by the QEMU monitor, for example
+ * to execute QMP commands. The monitor is aware of the job_mutex
+ * presence, so these functions assume it is held by the caller
+ * to protect job fields (see job-common.h).
+ * This prevents TOC/TOU bugs, allowing the caller to hold the
+ * lock between a check in the job state and the actual action.
+ *
+ * Therefore, each function in this API that needs protection
+ * must have the suffix "_locked" and the comment
+ * "Called between job_lock and job_unlock."
+ */
+
+
+/**
+ * Allocate and return a new job transaction. Jobs can be added to the
+ * transaction using job_txn_add_job_locked().
+ *
+ * The transaction is automatically freed when the last job completes or is
+ * cancelled.
+ *
+ * All jobs in the transaction either complete successfully or fail/cancel as a
+ * group. Jobs wait for each other before completing. Cancelling one job
+ * cancels all jobs in the transaction.
+ */
+JobTxn *job_txn_new(void);
+
+/**
+ * Release a reference that was previously acquired with job_txn_add_job_locked
+ * or job_txn_new. If it's the last reference to the object, it will be freed.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_txn_unref_locked(JobTxn *txn);
+
+/**
+ * Add a reference to Job refcnt, it will be decreased with job_unref_locked,
+ * and then be freed if it comes to be the last reference.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_ref_locked(Job *job);
+
+/**
+ * Release a reference that was previously acquired with job_ref_locked() or
+ * job_create(). If it's the last reference to the object, it will be freed.
+ *
+ * Called between job_lock and job_unlock, but might release it temporarly.
+ */
+void job_unref_locked(Job *job);
+
+/**
+ * Conditionally enter the job coroutine if the job is ready to run, not
+ * already busy and fn() returns true. fn() is called while under the job_lock
+ * critical section.
+ *
+ * Called between job_lock and job_unlock, but might release it temporarly.
+ */
+void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
+
+/** Just like job_is_cancelled, but called between job_lock and job_unlock */
+bool job_is_cancelled_locked(Job *job);
+
+/** Same as job_is_completed(), but assumes job_lock is held. */
+bool job_is_completed_locked(Job *job);
+
+/** Same as job_is_ready(), but assumes job_lock is held. */
+bool job_is_ready_locked(Job *job);
+
+/**
+ * Request @job to pause at the next pause point. Must be paired with
+ * job_resume_locked(). If the job is supposed to be resumed by user action,
+ * call job_user_pause_locked() instead.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_pause_locked(Job *job);
+
+/**
+ * Resumes a @job paused with job_pause_locked.
+ * Called between job_lock and job_unlock.
+ */
+void job_resume_locked(Job *job);
+
+/**
+ * Asynchronously pause the specified @job.
+ * Do not allow a resume until a matching call to job_user_resume_locked.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_user_pause_locked(Job *job, Error **errp);
+
+/**
+ * Returns true if the job is user-paused.
+ * Called between job_lock and job_unlock.
+ */
+bool job_user_paused_locked(Job *job);
+
+/**
+ * Resume the specified @job.
+ * Must be paired with a preceding job_user_pause_locked.
+ *
+ * Called between job_lock and job_unlock, but might release it temporarly.
+ */
+void job_user_resume_locked(Job *job, Error **errp);
+
+/**
+ * Get the next element from the list of block jobs after @job, or the
+ * first one if @job is %NULL.
+ *
+ * Returns the requested job, or %NULL if there are no more jobs left.
+ *
+ * Called between job_lock and job_unlock.
+ */
+Job *job_next_locked(Job *job);
+
+/**
+ * Get the job identified by @id (which must not be %NULL).
+ *
+ * Returns the requested job, or %NULL if it doesn't exist.
+ *
+ * Called between job_lock and job_unlock.
+ */
+Job *job_get_locked(const char *id);
+
+/**
+ * Check whether the verb @verb can be applied to @job in its current state.
+ * Returns 0 if the verb can be applied; otherwise errp is set and -EPERM
+ * returned.
+ *
+ * Called between job_lock and job_unlock.
+ */
+int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp);
+
+/**
+ * Asynchronously complete the specified @job.
+ * Called between job_lock and job_unlock, but it releases the lock temporarly.
+ */
+void job_complete_locked(Job *job, Error **errp);
+
+/**
+ * Asynchronously cancel the specified @job. If @force is true, the job should
+ * be cancelled immediately without waiting for a consistent state.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_cancel_locked(Job *job, bool force);
+
+/**
+ * Cancels the specified job like job_cancel_locked(), but may refuse to do so
+ * if the operation isn't meaningful in the current state of the job.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_user_cancel_locked(Job *job, bool force, Error **errp);
+
+/**
+ * Synchronously cancel the @job. The completion callback is called
+ * before the function returns. If @force is false, the job may
+ * actually complete instead of canceling itself; the circumstances
+ * under which this happens depend on the kind of job that is active.
+ *
+ * Returns the return value from the job if the job actually completed
+ * during the call, or -ECANCELED if it was canceled.
+ *
+ * Called between job_lock and job_unlock.
+ */
+int job_cancel_sync_locked(Job *job, bool force);
+
+/**
+ * @job: The job to be completed.
+ * @errp: Error object which may be set by job_complete_locked(); this is not
+ * necessarily set on every error, the job return value has to be
+ * checked as well.
+ *
+ * Synchronously complete the job. The completion callback is called before the
+ * function returns, unless it is NULL (which is permissible when using this
+ * function).
+ *
+ * Returns the return value from the job.
+ * Called between job_lock and job_unlock.
+ */
+int job_complete_sync_locked(Job *job, Error **errp);
+
+/**
+ * For a @job that has finished its work and is pending awaiting explicit
+ * acknowledgement to commit its work, this will commit that work.
+ *
+ * FIXME: Make the below statement universally true:
+ * For jobs that support the manual workflow mode, all graph changes that occur
+ * as a result will occur after this command and before a successful reply.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_finalize_locked(Job *job, Error **errp);
+
+/**
+ * Remove the concluded @job from the query list and resets the passed pointer
+ * to %NULL. Returns an error if the job is not actually concluded.
+ *
+ * Called between job_lock and job_unlock.
+ */
+void job_dismiss_locked(Job **job, Error **errp);
+
+/**
+ * Synchronously finishes the given @job. If @finish is given, it is called to
+ * trigger completion or cancellation of the job.
+ *
+ * Returns 0 if the job is successfully completed, -ECANCELED if the job was
+ * cancelled before completing, and -errno in other error cases.
+ *
+ * Called between job_lock and job_unlock.
+ */
+int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
+ Error **errp);
+
+#endif
diff --git a/include/qemu/job.h b/include/qemu/job.h
index cdfc603706..c2bbdef8e8 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -26,28 +26,7 @@
#ifndef JOB_H
#define JOB_H
-#include "job-common.h"
-
-/**
- * Allocate and return a new job transaction. Jobs can be added to the
- * transaction using job_txn_add_job_locked().
- *
- * The transaction is automatically freed when the last job completes or is
- * cancelled.
- *
- * All jobs in the transaction either complete successfully or fail/cancel as a
- * group. Jobs wait for each other before completing. Cancelling one job
- * cancels all jobs in the transaction.
- */
-JobTxn *job_txn_new(void);
-
-/**
- * Release a reference that was previously acquired with job_txn_add_job_locked
- * or job_txn_new. If it's the last reference to the object, it will be freed.
- *
- * Called between job_lock and job_unlock.
- */
-void job_txn_unref_locked(JobTxn *txn);
+#include "job-monitor.h"
/**
* Create a new long-running job and return it.
@@ -66,22 +45,6 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
AioContext *ctx, int flags, BlockCompletionFunc *cb,
void *opaque, Error **errp);
-/**
- * Add a reference to Job refcnt, it will be decreased with job_unref_locked,
- * and then be freed if it comes to be the last reference.
- *
- * Called between job_lock and job_unlock.
- */
-void job_ref_locked(Job *job);
-
-/**
- * Release a reference that was previously acquired with job_ref_locked() or
- * job_create(). If it's the last reference to the object, it will be freed.
- *
- * Called between job_lock and job_unlock, but might release it temporarly.
- */
-void job_unref_locked(Job *job);
-
/**
* @job: The job that has made progress
* @done: How much progress the job made since the last call
@@ -121,15 +84,6 @@ void job_progress_set_remaining(Job *job, uint64_t remaining);
*/
void job_progress_increase_remaining(Job *job, uint64_t delta);
-/**
- * Conditionally enter the job coroutine if the job is ready to run, not
- * already busy and fn() returns true. fn() is called while under the job_lock
- * critical section.
- *
- * Called between job_lock and job_unlock, but might release it temporarly.
- */
-void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
-
/**
* @job: A job that has not yet been started.
*
@@ -188,9 +142,6 @@ void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
*/
bool job_is_cancelled(Job *job);
-/** Just like job_is_cancelled, but called between job_lock and job_unlock */
-bool job_is_cancelled_locked(Job *job);
-
/**
* Returns whether the job is scheduled for cancellation (at an
* indefinite point).
@@ -204,83 +155,12 @@ bool job_cancel_requested(Job *job);
*/
bool job_is_completed(Job *job);
-/** Same as job_is_completed(), but assumes job_lock is held. */
-bool job_is_completed_locked(Job *job);
-
/**
* Returns whether the job is ready to be completed.
* Called with job_mutex *not* held.
*/
bool job_is_ready(Job *job);
-/** Same as job_is_ready(), but assumes job_lock is held. */
-bool job_is_ready_locked(Job *job);
-
-/**
- * Request @job to pause at the next pause point. Must be paired with
- * job_resume_locked(). If the job is supposed to be resumed by user action,
- * call job_user_pause_locked() instead.
- *
- * Called between job_lock and job_unlock.
- */
-void job_pause_locked(Job *job);
-
-/**
- * Resumes a @job paused with job_pause_locked.
- * Called between job_lock and job_unlock.
- */
-void job_resume_locked(Job *job);
-
-/**
- * Asynchronously pause the specified @job.
- * Do not allow a resume until a matching call to job_user_resume_locked.
- *
- * Called between job_lock and job_unlock.
- */
-void job_user_pause_locked(Job *job, Error **errp);
-
-/**
- * Returns true if the job is user-paused.
- * Called between job_lock and job_unlock.
- */
-bool job_user_paused_locked(Job *job);
-
-/**
- * Resume the specified @job.
- * Must be paired with a preceding job_user_pause_locked.
- *
- * Called between job_lock and job_unlock, but might release it temporarly.
- */
-void job_user_resume_locked(Job *job, Error **errp);
-
-/**
- * Get the next element from the list of block jobs after @job, or the
- * first one if @job is %NULL.
- *
- * Returns the requested job, or %NULL if there are no more jobs left.
- *
- * Called between job_lock and job_unlock.
- */
-Job *job_next_locked(Job *job);
-
-/**
- * Get the job identified by @id (which must not be %NULL).
- *
- * Returns the requested job, or %NULL if it doesn't exist.
- *
- * Called between job_lock and job_unlock.
- */
-Job *job_get_locked(const char *id);
-
-/**
- * Check whether the verb @verb can be applied to @job in its current state.
- * Returns 0 if the verb can be applied; otherwise errp is set and -EPERM
- * returned.
- *
- * Called between job_lock and job_unlock.
- */
-int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp);
-
/**
* The @job could not be started, free it.
* Called with job_mutex *not* held.
@@ -293,41 +173,6 @@ void job_early_fail(Job *job);
*/
void job_transition_to_ready(Job *job);
-/**
- * Asynchronously complete the specified @job.
- * Called between job_lock and job_unlock, but it releases the lock temporarly.
- */
-void job_complete_locked(Job *job, Error **errp);
-
-/**
- * Asynchronously cancel the specified @job. If @force is true, the job should
- * be cancelled immediately without waiting for a consistent state.
- *
- * Called between job_lock and job_unlock.
- */
-void job_cancel_locked(Job *job, bool force);
-
-/**
- * Cancels the specified job like job_cancel_locked(), but may refuse to do so
- * if the operation isn't meaningful in the current state of the job.
- *
- * Called between job_lock and job_unlock.
- */
-void job_user_cancel_locked(Job *job, bool force, Error **errp);
-
-/**
- * Synchronously cancel the @job. The completion callback is called
- * before the function returns. If @force is false, the job may
- * actually complete instead of canceling itself; the circumstances
- * under which this happens depend on the kind of job that is active.
- *
- * Returns the return value from the job if the job actually completed
- * during the call, or -ECANCELED if it was canceled.
- *
- * Called between job_lock and job_unlock.
- */
-int job_cancel_sync_locked(Job *job, bool force);
-
/**
* Synchronously force-cancels all jobs using job_cancel_sync_locked().
*
@@ -337,53 +182,6 @@ int job_cancel_sync_locked(Job *job, bool force);
*/
void job_cancel_sync_all(void);
-/**
- * @job: The job to be completed.
- * @errp: Error object which may be set by job_complete_locked(); this is not
- * necessarily set on every error, the job return value has to be
- * checked as well.
- *
- * Synchronously complete the job. The completion callback is called before the
- * function returns, unless it is NULL (which is permissible when using this
- * function).
- *
- * Returns the return value from the job.
- * Called between job_lock and job_unlock.
- */
-int job_complete_sync_locked(Job *job, Error **errp);
-
-/**
- * For a @job that has finished its work and is pending awaiting explicit
- * acknowledgement to commit its work, this will commit that work.
- *
- * FIXME: Make the below statement universally true:
- * For jobs that support the manual workflow mode, all graph changes that occur
- * as a result will occur after this command and before a successful reply.
- *
- * Called between job_lock and job_unlock.
- */
-void job_finalize_locked(Job *job, Error **errp);
-
-/**
- * Remove the concluded @job from the query list and resets the passed pointer
- * to %NULL. Returns an error if the job is not actually concluded.
- *
- * Called between job_lock and job_unlock.
- */
-void job_dismiss_locked(Job **job, Error **errp);
-
-/**
- * Synchronously finishes the given @job. If @finish is given, it is called to
- * trigger completion or cancellation of the job.
- *
- * Returns 0 if the job is successfully completed, -ECANCELED if the job was
- * cancelled before completing, and -errno in other error cases.
- *
- * Called between job_lock and job_unlock.
- */
-int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
- Error **errp);
-
/**
* Sets the @job->aio_context.
* Called with job_mutex *not* held.
diff --git a/job.c b/job.c
index c7a41d88d6..844102befb 100644
--- a/job.c
+++ b/job.c
@@ -40,6 +40,7 @@
* therefore needs consistency across job_get and the actual operation
* (e.g. job_user_cancel). To achieve this consistency, the caller
* calls job_lock/job_unlock itself around the whole operation.
+ * These functions are declared in job-monitor.h.
*
*
* The second includes functions used by the block job drivers and sometimes
--
2.31.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] jobs: add job-driver.h
2022-02-08 14:39 [PATCH v2 0/3] job: split job API in driver and monitor Emanuele Giuseppe Esposito
2022-02-08 14:39 ` [PATCH v2 1/3] jobs: add job-common.h Emanuele Giuseppe Esposito
2022-02-08 14:39 ` [PATCH v2 2/3] jobs: add job-monitor.h Emanuele Giuseppe Esposito
@ 2022-02-08 14:39 ` Emanuele Giuseppe Esposito
2 siblings, 0 replies; 4+ messages in thread
From: Emanuele Giuseppe Esposito @ 2022-02-08 14:39 UTC (permalink / raw)
To: qemu-block
Cc: Emanuele Giuseppe Esposito, Vladimir Sementsov-Ogievskiy,
qemu-devel, Stefan Hajnoczi, Paolo Bonzini, John Snow
job-driver.h contains all functions of job.h that are used by
the drivers (JobDriver, BlockJobDriver).
These functions are unaware of the job_mutex,
so they all take and release the lock internally.
No functional change intended.
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
---
include/qemu/job-driver.h | 211 ++++++++++++++++++++++++++++++++++++++
include/qemu/job.h | 167 +-----------------------------
job.c | 3 +-
3 files changed, 215 insertions(+), 166 deletions(-)
create mode 100644 include/qemu/job-driver.h
diff --git a/include/qemu/job-driver.h b/include/qemu/job-driver.h
new file mode 100644
index 0000000000..a78c8fa305
--- /dev/null
+++ b/include/qemu/job-driver.h
@@ -0,0 +1,211 @@
+/*
+ * Declarations for background jobs
+ *
+ * Copyright (c) 2011 IBM Corp.
+ * Copyright (c) 2012, 2018 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef JOB_DRIVER_H
+#define JOB_DRIVER_H
+
+#include "job-common.h"
+
+/*
+ * Job driver API.
+ *
+ * These functions use are used by job drivers like mirror,
+ * stream, commit etc. The driver is not aware of the job_mutex
+ * presence, so these functions use it internally to protect
+ * job fields (see job-common.h).
+ *
+ * Therefore, each function in this API that requires protection
+ * must have the comment
+ * "Called with job_mutext *not* held"
+ */
+
+
+/**
+ * Create a new long-running job and return it.
+ * Called with job_mutex *not* held.
+ *
+ * @job_id: The id of the newly-created job, or %NULL for internal jobs
+ * @driver: The class object for the newly-created job.
+ * @txn: The transaction this job belongs to, if any. %NULL otherwise.
+ * @ctx: The AioContext to run the job coroutine in.
+ * @flags: Creation flags for the job. See @JobCreateFlags.
+ * @cb: Completion function for the job.
+ * @opaque: Opaque pointer value passed to @cb.
+ * @errp: Error object.
+ */
+void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
+ AioContext *ctx, int flags, BlockCompletionFunc *cb,
+ void *opaque, Error **errp);
+
+/**
+ * @job: The job that has made progress
+ * @done: How much progress the job made since the last call
+ *
+ * Updates the progress counter of the job.
+ *
+ * Progress API is thread safe.
+ */
+void job_progress_update(Job *job, uint64_t done);
+
+/**
+ * @job: The job whose expected progress end value is set
+ * @remaining: Missing progress (on top of the current progress counter value)
+ * until the new expected end value is reached
+ *
+ * Sets the expected end value of the progress counter of a job so that a
+ * completion percentage can be calculated when the progress is updated.
+ *
+ * Progress API is thread safe.
+ */
+void job_progress_set_remaining(Job *job, uint64_t remaining);
+
+/**
+ * @job: The job whose expected progress end value is updated
+ * @delta: Value which is to be added to the current expected end
+ * value
+ *
+ * Increases the expected end value of the progress counter of a job.
+ * This is useful for parenthesis operations: If a job has to
+ * conditionally perform a high-priority operation as part of its
+ * progress, it calls this function with the expected operation's
+ * length before, and job_progress_update() afterwards.
+ * (So the operation acts as a parenthesis in regards to the main job
+ * operation running in background.)
+ *
+ * Progress API is thread safe.
+ */
+void job_progress_increase_remaining(Job *job, uint64_t delta);
+
+/**
+ * @job: A job that has not yet been started.
+ *
+ * Begins execution of a job.
+ * Takes ownership of one reference to the job object.
+ *
+ * Called with job_mutex *not* held.
+ */
+void job_start(Job *job);
+
+/**
+ * @job: The job to enter.
+ * Called with job_mutex *not* held.
+ *
+ * Continue the specified job by entering the coroutine.
+ * Called with job_mutex lock *not* held.
+ */
+void job_enter(Job *job);
+
+/**
+ * @job: The job that is ready to pause.
+ *
+ * Pause now if job_pause_locked() has been called. Jobs that perform lots of
+ * I/O must call this between requests so that the job can be paused.
+ *
+ * Called with job_mutex *not* held (we don't want the coroutine
+ * to yield with the lock held!).
+ */
+void coroutine_fn job_pause_point(Job *job);
+
+/**
+ * @job: The job that calls the function.
+ *
+ * Yield the job coroutine.
+ * Called with job_mutex *not* held (we don't want the coroutine
+ * to yield with the lock held!).
+ */
+void job_yield(Job *job);
+
+/**
+ * @job: The job that calls the function.
+ * @ns: How many nanoseconds to stop for.
+ *
+ * Put the job to sleep (assuming that it wasn't canceled) for @ns
+ * %QEMU_CLOCK_REALTIME nanoseconds. Canceling the job will immediately
+ * interrupt the wait.
+ *
+ * Called with job_mutex *not* held (we don't want the coroutine
+ * to yield with the lock held!).
+ */
+void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
+
+/**
+ * Returns whether the job is being cancelled.
+ * Called with job_mutex *not* held.
+ */
+bool job_is_cancelled(Job *job);
+
+/**
+ * Returns whether the job is scheduled for cancellation (at an
+ * indefinite point).
+ * Called with job_mutex *not* held.
+ */
+bool job_cancel_requested(Job *job);
+
+/**
+ * Returns whether the job is in a completed state.
+ * Called with job_mutex *not* held.
+ */
+bool job_is_completed(Job *job);
+
+/**
+ * Returns whether the job is ready to be completed.
+ * Called with job_mutex *not* held.
+ */
+bool job_is_ready(Job *job);
+
+/**
+ * The @job could not be started, free it.
+ * Called with job_mutex *not* held.
+ */
+void job_early_fail(Job *job);
+
+/**
+ * Moves the @job from RUNNING to READY.
+ * Called with job_mutex *not* held.
+ */
+void job_transition_to_ready(Job *job);
+
+/**
+ * Synchronously force-cancels all jobs using job_cancel_sync_locked().
+ *
+ * Called with job_lock *not* held, unlike most other APIs consumed
+ * by the monitor! This is primarly to avoid adding unnecessary lock-unlock
+ * patterns in the caller.
+ */
+void job_cancel_sync_all(void);
+
+/**
+ * Sets the @job->aio_context.
+ * Called with job_mutex *not* held.
+ *
+ * This function must run in the main thread to protect against
+ * concurrent read in job_finish_sync_locked(),
+ * takes the job_mutex lock to protect against the read in
+ * job_do_yield_locked(), and must be called when the coroutine
+ * is quiescent.
+ */
+void job_set_aio_context(Job *job, AioContext *ctx);
+
+#endif
diff --git a/include/qemu/job.h b/include/qemu/job.h
index c2bbdef8e8..4a0b01dd1d 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -27,171 +27,8 @@
#define JOB_H
#include "job-monitor.h"
+#include "job-driver.h"
-/**
- * Create a new long-running job and return it.
- * Called with job_mutex *not* held.
- *
- * @job_id: The id of the newly-created job, or %NULL for internal jobs
- * @driver: The class object for the newly-created job.
- * @txn: The transaction this job belongs to, if any. %NULL otherwise.
- * @ctx: The AioContext to run the job coroutine in.
- * @flags: Creation flags for the job. See @JobCreateFlags.
- * @cb: Completion function for the job.
- * @opaque: Opaque pointer value passed to @cb.
- * @errp: Error object.
- */
-void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
- AioContext *ctx, int flags, BlockCompletionFunc *cb,
- void *opaque, Error **errp);
-
-/**
- * @job: The job that has made progress
- * @done: How much progress the job made since the last call
- *
- * Updates the progress counter of the job.
- *
- * Progress API is thread safe.
- */
-void job_progress_update(Job *job, uint64_t done);
-
-/**
- * @job: The job whose expected progress end value is set
- * @remaining: Missing progress (on top of the current progress counter value)
- * until the new expected end value is reached
- *
- * Sets the expected end value of the progress counter of a job so that a
- * completion percentage can be calculated when the progress is updated.
- *
- * Progress API is thread safe.
- */
-void job_progress_set_remaining(Job *job, uint64_t remaining);
-
-/**
- * @job: The job whose expected progress end value is updated
- * @delta: Value which is to be added to the current expected end
- * value
- *
- * Increases the expected end value of the progress counter of a job.
- * This is useful for parenthesis operations: If a job has to
- * conditionally perform a high-priority operation as part of its
- * progress, it calls this function with the expected operation's
- * length before, and job_progress_update() afterwards.
- * (So the operation acts as a parenthesis in regards to the main job
- * operation running in background.)
- *
- * Progress API is thread safe.
- */
-void job_progress_increase_remaining(Job *job, uint64_t delta);
-
-/**
- * @job: A job that has not yet been started.
- *
- * Begins execution of a job.
- * Takes ownership of one reference to the job object.
- *
- * Called with job_mutex *not* held.
- */
-void job_start(Job *job);
-
-/**
- * @job: The job to enter.
- * Called with job_mutex *not* held.
- *
- * Continue the specified job by entering the coroutine.
- * Called with job_mutex lock *not* held.
- */
-void job_enter(Job *job);
-
-/**
- * @job: The job that is ready to pause.
- *
- * Pause now if job_pause_locked() has been called. Jobs that perform lots of
- * I/O must call this between requests so that the job can be paused.
- *
- * Called with job_mutex *not* held (we don't want the coroutine
- * to yield with the lock held!).
- */
-void coroutine_fn job_pause_point(Job *job);
-
-/**
- * @job: The job that calls the function.
- *
- * Yield the job coroutine.
- * Called with job_mutex *not* held (we don't want the coroutine
- * to yield with the lock held!).
- */
-void job_yield(Job *job);
-
-/**
- * @job: The job that calls the function.
- * @ns: How many nanoseconds to stop for.
- *
- * Put the job to sleep (assuming that it wasn't canceled) for @ns
- * %QEMU_CLOCK_REALTIME nanoseconds. Canceling the job will immediately
- * interrupt the wait.
- *
- * Called with job_mutex *not* held (we don't want the coroutine
- * to yield with the lock held!).
- */
-void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
-
-/**
- * Returns whether the job is being cancelled.
- * Called with job_mutex *not* held.
- */
-bool job_is_cancelled(Job *job);
-
-/**
- * Returns whether the job is scheduled for cancellation (at an
- * indefinite point).
- * Called with job_mutex *not* held.
- */
-bool job_cancel_requested(Job *job);
-
-/**
- * Returns whether the job is in a completed state.
- * Called with job_mutex *not* held.
- */
-bool job_is_completed(Job *job);
-
-/**
- * Returns whether the job is ready to be completed.
- * Called with job_mutex *not* held.
- */
-bool job_is_ready(Job *job);
-
-/**
- * The @job could not be started, free it.
- * Called with job_mutex *not* held.
- */
-void job_early_fail(Job *job);
-
-/**
- * Moves the @job from RUNNING to READY.
- * Called with job_mutex *not* held.
- */
-void job_transition_to_ready(Job *job);
-
-/**
- * Synchronously force-cancels all jobs using job_cancel_sync_locked().
- *
- * Called with job_lock *not* held, unlike most other APIs consumed
- * by the monitor! This is primarly to avoid adding unnecessary lock-unlock
- * patterns in the caller.
- */
-void job_cancel_sync_all(void);
-
-/**
- * Sets the @job->aio_context.
- * Called with job_mutex *not* held.
- *
- * This function must run in the main thread to protect against
- * concurrent read in job_finish_sync_locked(),
- * takes the job_mutex lock to protect against the read in
- * job_do_yield_locked(), and must be called when the coroutine
- * is quiescent.
- */
-void job_set_aio_context(Job *job, AioContext *ctx);
+/* DO NOT ADD ANYTHING IN HERE. USE ONE OF THE HEADERS INCLUDED ABOVE */
#endif
diff --git a/job.c b/job.c
index 844102befb..b72f7ea724 100644
--- a/job.c
+++ b/job.c
@@ -44,7 +44,8 @@
*
*
* The second includes functions used by the block job drivers and sometimes
- * by the core block layer. These delegate the locking to the callee instead.
+ * by the core block layer. These delegate the locking to the callee instead,
+ * and are declared in job-driver.h.
*/
/*
--
2.31.1
^ permalink raw reply related [flat|nested] 4+ messages in thread