bdrv_dirty_iter_free(dbi);
}
-static void coroutine_fn backup_run(void *opaque)
+static int coroutine_fn backup_run(Job *opaque_job, Error **errp)
{
- BackupBlockJob *job = opaque;
+ BackupBlockJob *job = container_of(opaque_job, BackupBlockJob, common.job);
BackupCompleteData *data;
BlockDriverState *bs = blk_bs(job->common.blk);
int64_t offset, nb_clusters;
data = g_malloc(sizeof(*data));
data->ret = ret;
job_defer_to_main_loop(&job->common.job, backup_complete, data);
+ return ret;
}
static const BlockJobDriver backup_job_driver = {
.free = block_job_free,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
- .start = backup_run,
+ .run = backup_run,
.commit = backup_commit,
.abort = backup_abort,
.clean = backup_clean,
bdrv_unref(top);
}
-static void coroutine_fn commit_run(void *opaque)
+static int coroutine_fn commit_run(Job *job, Error **errp)
{
- CommitBlockJob *s = opaque;
+ CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
CommitCompleteData *data;
int64_t offset;
uint64_t delay_ns = 0;
data = g_malloc(sizeof(*data));
data->ret = ret;
job_defer_to_main_loop(&s->common.job, commit_complete, data);
+ return ret;
}
static const BlockJobDriver commit_job_driver = {
.free = block_job_free,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
- .start = commit_run,
+ .run = commit_run,
},
};
job_completed(job, s->ret, s->err);
}
-static void coroutine_fn blockdev_create_run(void *opaque)
+static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
{
- BlockdevCreateJob *s = opaque;
+ BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common);
job_progress_set_remaining(&s->common, 1);
s->ret = s->drv->bdrv_co_create(s->opts, &s->err);
qapi_free_BlockdevCreateOptions(s->opts);
job_defer_to_main_loop(&s->common, blockdev_create_complete, NULL);
+
+ return s->ret;
}
static const JobDriver blockdev_create_job_driver = {
.instance_size = sizeof(BlockdevCreateJob),
.job_type = JOB_TYPE_CREATE,
- .start = blockdev_create_run,
+ .run = blockdev_create_run,
};
void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
return ret;
}
-static void coroutine_fn mirror_run(void *opaque)
+static int coroutine_fn mirror_run(Job *job, Error **errp)
{
- MirrorBlockJob *s = opaque;
+ MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
MirrorExitData *data;
BlockDriverState *bs = s->mirror_top_bs->backing->bs;
BlockDriverState *target_bs = blk_bs(s->target);
if (need_drain) {
bdrv_drained_begin(bs);
}
+
job_defer_to_main_loop(&s->common.job, mirror_exit, data);
+ return ret;
}
static void mirror_complete(Job *job, Error **errp)
.free = block_job_free,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
- .start = mirror_run,
+ .run = mirror_run,
.pause = mirror_pause,
.complete = mirror_complete,
},
.free = block_job_free,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
- .start = mirror_run,
+ .run = mirror_run,
.pause = mirror_pause,
.complete = mirror_complete,
},
g_free(data);
}
-static void coroutine_fn stream_run(void *opaque)
+static int coroutine_fn stream_run(Job *job, Error **errp)
{
- StreamBlockJob *s = opaque;
+ StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
StreamCompleteData *data;
BlockBackend *blk = s->common.blk;
BlockDriverState *bs = blk_bs(blk);
data = g_malloc(sizeof(*data));
data->ret = ret;
job_defer_to_main_loop(&s->common.job, stream_complete, data);
+ return ret;
}
static const BlockJobDriver stream_job_driver = {
.instance_size = sizeof(StreamBlockJob),
.job_type = JOB_TYPE_STREAM,
.free = block_job_free,
- .start = stream_run,
+ .run = stream_run,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
},
JobType job_type;
/** Mandatory: Entrypoint for the Coroutine. */
- CoroutineEntry *start;
+ int coroutine_fn (*run)(Job *job, Error **errp);
/**
* If the callback is not NULL, it will be invoked when the job transitions
{
Job *job = opaque;
- assert(job && job->driver && job->driver->start);
+ assert(job && job->driver && job->driver->run);
job_pause_point(job);
- job->driver->start(job);
+ job->ret = job->driver->run(job, NULL);
}
void job_start(Job *job)
{
assert(job && !job_started(job) && job->paused &&
- job->driver && job->driver->start);
+ job->driver && job->driver->run);
job->co = qemu_coroutine_create(job_co_entry, job);
job->pause_count--;
job->busy = true;
job_completed(job, 0, NULL);
}
-static void coroutine_fn test_job_start(void *opaque)
+static int coroutine_fn test_job_run(Job *job, Error **errp)
{
- TestBlockJob *s = opaque;
+ TestBlockJob *s = container_of(job, TestBlockJob, common.job);
job_transition_to_ready(&s->common.job);
while (!s->should_complete) {
}
job_defer_to_main_loop(&s->common.job, test_job_completed, NULL);
+ return 0;
}
static void test_job_complete(Job *job, Error **errp)
.free = block_job_free,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
- .start = test_job_start,
+ .run = test_job_run,
.complete = test_job_complete,
},
};
bdrv_unref(bs);
}
-static void coroutine_fn test_block_job_run(void *opaque)
+static int coroutine_fn test_block_job_run(Job *job, Error **errp)
{
- TestBlockJob *s = opaque;
- BlockJob *job = &s->common;
+ TestBlockJob *s = container_of(job, TestBlockJob, common.job);
while (s->iterations--) {
if (s->use_timer) {
- job_sleep_ns(&job->job, 0);
+ job_sleep_ns(job, 0);
} else {
- job_yield(&job->job);
+ job_yield(job);
}
- if (job_is_cancelled(&job->job)) {
+ if (job_is_cancelled(job)) {
break;
}
}
- job_defer_to_main_loop(&job->job, test_block_job_complete,
+ job_defer_to_main_loop(job, test_block_job_complete,
(void *)(intptr_t)s->rc);
+ return s->rc;
}
typedef struct {
.free = block_job_free,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
- .start = test_block_job_run,
+ .run = test_block_job_run,
},
};
s->should_complete = true;
}
-static void coroutine_fn cancel_job_start(void *opaque)
+static int coroutine_fn cancel_job_run(Job *job, Error **errp)
{
- CancelJob *s = opaque;
+ CancelJob *s = container_of(job, CancelJob, common.job);
while (!s->should_complete) {
if (job_is_cancelled(&s->common.job)) {
defer:
job_defer_to_main_loop(&s->common.job, cancel_job_completed, s);
+ return 0;
}
static const BlockJobDriver test_cancel_driver = {
.free = block_job_free,
.user_resume = block_job_user_resume,
.drain = block_job_drain,
- .start = cancel_job_start,
+ .run = cancel_job_run,
.complete = cancel_job_complete,
},
};