[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 09/11] blockjob: add block_job_start
From: |
John Snow |
Subject: |
[Qemu-devel] [PATCH v2 09/11] blockjob: add block_job_start |
Date: |
Fri, 30 Sep 2016 18:00:47 -0400 |
Instead of automatically starting jobs at creation time via backup_start
et al, we'd like to return a job object pointer that can be started
manually at later point in time.
For now, add the block_job_start mechanism and start the jobs
automatically as we have been doing, with conversions job-by-job coming
in later patches.
Of note: cancellation of unstarted jobs will perform all the normal
cleanup as if the job had started, particularly abort and clean. The
only difference is that we will not emit any events, because the job
never actually started.
Signed-off-by: John Snow <address@hidden>
---
block/backup.c | 3 +--
block/commit.c | 3 +--
block/mirror.c | 3 +--
block/stream.c | 3 +--
blockjob.c | 48 +++++++++++++++++++++++++++++++++++------------
include/block/block_int.h | 8 ++++++++
tests/test-blockjob-txn.c | 12 ++++++------
7 files changed, 54 insertions(+), 26 deletions(-)
diff --git a/block/backup.c b/block/backup.c
index 58dfc58..7294169 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -637,9 +637,8 @@ void backup_start(const char *job_id, BlockDriverState *bs,
bdrv_op_block_all(target, job->common.blocker);
job->common.len = len;
- job->common.co = qemu_coroutine_create(job->common.driver->start, job);
block_job_txn_add_job(txn, &job->common);
- qemu_coroutine_enter(job->common.co);
+ block_job_start(&job->common);
return;
error:
diff --git a/block/commit.c b/block/commit.c
index dbaf39e..e64fdf3 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -275,10 +275,9 @@ void commit_start(const char *job_id, BlockDriverState *bs,
s->backing_file_str = g_strdup(backing_file_str);
s->on_error = on_error;
- s->common.co = qemu_coroutine_create(s->common.driver->start, s);
trace_commit_start(bs, base, top, s, s->common.co, opaque);
- qemu_coroutine_enter(s->common.co);
+ block_job_start(&s->common);
}
diff --git a/block/mirror.c b/block/mirror.c
index ef54e5b..2a6a662 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -969,9 +969,8 @@ static void mirror_start_job(const char *job_id,
BlockDriverState *bs,
bdrv_op_block_all(target, s->common.blocker);
- s->common.co = qemu_coroutine_create(s->common.driver->start, s);
trace_mirror_start(bs, s, s->common.co, opaque);
- qemu_coroutine_enter(s->common.co);
+ block_job_start(&s->common);
}
void mirror_start(const char *job_id, BlockDriverState *bs,
diff --git a/block/stream.c b/block/stream.c
index 2a1c814..55cbbe7 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -232,7 +232,6 @@ void stream_start(const char *job_id, BlockDriverState *bs,
s->backing_file_str = g_strdup(backing_file_str);
s->on_error = on_error;
- s->common.co = qemu_coroutine_create(s->common.driver->start, s);
trace_stream_start(bs, base, s, s->common.co, opaque);
- qemu_coroutine_enter(s->common.co);
+ block_job_start(&s->common);
}
diff --git a/blockjob.c b/blockjob.c
index 44cbf6c..ac9a68d 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -161,7 +161,8 @@ void *block_job_create(const char *job_id, const
BlockJobDriver *driver,
job->blk = blk;
job->cb = cb;
job->opaque = opaque;
- job->busy = true;
+ job->busy = false;
+ job->paused = true;
job->refcnt = 1;
bs->job = job;
@@ -184,6 +185,15 @@ void *block_job_create(const char *job_id, const
BlockJobDriver *driver,
return job;
}
+void block_job_start(BlockJob *job)
+{
+ assert(job && !job->co && job->paused && !job->busy && job->driver->start);
+ job->paused = false;
+ job->busy = true;
+ job->co = qemu_coroutine_create(job->driver->start, job);
+ qemu_coroutine_enter(job->co);
+}
+
void block_job_ref(BlockJob *job)
{
++job->refcnt;
@@ -220,18 +230,24 @@ static void block_job_completed_single(BlockJob *job)
if (job->driver->clean) {
job->driver->clean(job);
}
+
if (job->cb) {
job->cb(job->opaque, job->ret);
}
- if (block_job_is_cancelled(job)) {
- block_job_event_cancelled(job);
- } else {
- const char *msg = NULL;
- if (job->ret < 0) {
- msg = strerror(-job->ret);
+
+ /* Emit events only if we actually started */
+ if (job->co) {
+ if (block_job_is_cancelled(job)) {
+ block_job_event_cancelled(job);
+ } else {
+ const char *msg = NULL;
+ if (job->ret < 0) {
+ msg = strerror(-job->ret);
+ }
+ block_job_event_completed(job, msg);
}
- block_job_event_completed(job, msg);
}
+
if (job->txn) {
QLIST_REMOVE(job, txn_list);
block_job_txn_unref(job->txn);
@@ -335,7 +351,8 @@ void block_job_set_speed(BlockJob *job, int64_t speed,
Error **errp)
void block_job_complete(BlockJob *job, Error **errp)
{
- if (job->pause_count || job->cancelled || !job->driver->complete) {
+ if (job->pause_count || job->cancelled ||
+ !job->co || !job->driver->complete) {
error_setg(errp, "The active block job '%s' cannot be completed",
job->id);
return;
@@ -364,6 +381,8 @@ bool block_job_paused(BlockJob *job)
void coroutine_fn block_job_pause_point(BlockJob *job)
{
+ assert(job && job->co);
+
if (!block_job_should_pause(job)) {
return;
}
@@ -408,9 +427,14 @@ void block_job_enter(BlockJob *job)
void block_job_cancel(BlockJob *job)
{
- job->cancelled = true;
- block_job_iostatus_reset(job);
- block_job_enter(job);
+ if (job->co) {
+ job->cancelled = true;
+ block_job_iostatus_reset(job);
+ block_job_enter(job);
+ } else {
+ /* Job was queued but unstarted. Perform cleanup. */
+ block_job_completed(job, -ECANCELED);
+ }
}
bool block_job_is_cancelled(BlockJob *job)
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 3e79228..686f6a8 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -763,6 +763,14 @@ void backup_start(const char *job_id, BlockDriverState *bs,
BlockCompletionFunc *cb, void *opaque,
BlockJobTxn *txn, Error **errp);
+/**
+ * block_job_start:
+ * @job: The job object as returned by @block_job_create.
+ *
+ * Begins execution of a block job.
+ */
+void block_job_start(BlockJob *job);
+
void hmp_drive_add_node(Monitor *mon, const char *optstr);
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
index 736e18f..d694b52 100644
--- a/tests/test-blockjob-txn.c
+++ b/tests/test-blockjob-txn.c
@@ -24,10 +24,6 @@ typedef struct {
int *result;
} TestBlockJob;
-static const BlockJobDriver test_block_job_driver = {
- .instance_size = sizeof(TestBlockJob),
-};
-
static void test_block_job_complete(BlockJob *job, void *opaque)
{
BlockDriverState *bs = blk_bs(job->blk);
@@ -77,6 +73,11 @@ static void test_block_job_cb(void *opaque, int ret)
g_free(data);
}
+static const BlockJobDriver test_block_job_driver = {
+ .instance_size = sizeof(TestBlockJob),
+ .start = test_block_job_run,
+};
+
/* Create a block job that completes with a given return code after a given
* number of event loop iterations. The return code is stored in the given
* result pointer.
@@ -103,10 +104,9 @@ static BlockJob *test_block_job_start(unsigned int
iterations,
s->use_timer = use_timer;
s->rc = rc;
s->result = result;
- s->common.co = qemu_coroutine_create(test_block_job_run, s);
data->job = s;
data->result = result;
- qemu_coroutine_enter(s->common.co);
+ block_job_start(&s->common);
return &s->common;
}
--
2.7.4
- [Qemu-devel] [PATCH v2 00/11] blockjobs: Fix transactional race condition, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 01/11] blockjob: fix dead pointer in txn list, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 03/11] Blockjobs: Internalize user_pause logic, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 02/11] blockjob: centralize QMP event emissions, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 04/11] blockjobs: Always use block_job_get_aio_context, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 06/11] blockjobs: fix documentation, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 07/11] blockjob: add .clean property, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 05/11] blockjobs: split interface into public/private, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 08/11] blockjob: add .start field, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 09/11] blockjob: add block_job_start,
John Snow <=
- [Qemu-devel] [PATCH v2 10/11] blockjob: refactor backup_start as backup_job_create, John Snow, 2016/09/30
- [Qemu-devel] [PATCH v2 11/11] iotests: add transactional failure race test, John Snow, 2016/09/30
- Re: [Qemu-devel] [PATCH v2 00/11] blockjobs: Fix transactional race condition, no-reply, 2016/09/30