@@ -542,7 +542,8 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
goto error;
}
- job = block_job_create(&backup_job_driver, bs, speed, cb, opaque, errp);
+ job = block_job_create(NULL, &backup_job_driver, bs, speed,
+ cb, opaque, errp);
if (!job) {
goto error;
}
@@ -236,7 +236,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
return;
}
- s = block_job_create(&commit_job_driver, bs, speed, cb, opaque, errp);
+ s = block_job_create(NULL, &commit_job_driver, bs, speed, cb, opaque, errp);
if (!s) {
return;
}
@@ -867,7 +867,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
buf_size = DEFAULT_MIRROR_BUF_SIZE;
}
- s = block_job_create(driver, bs, speed, cb, opaque, errp);
+ s = block_job_create(NULL, driver, bs, speed, cb, opaque, errp);
if (!s) {
return;
}
@@ -226,7 +226,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
{
StreamBlockJob *s;
- s = block_job_create(&stream_job_driver, bs, speed, cb, opaque, errp);
+ s = block_job_create(NULL, &stream_job_driver, bs, speed, cb, opaque, errp);
if (!s) {
return;
}
@@ -117,9 +117,9 @@ static void block_job_detach_aio_context(void *opaque)
block_job_unref(job);
}
-void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
- int64_t speed, BlockCompletionFunc *cb,
- void *opaque, Error **errp)
+void *block_job_create(const char *job_id, const BlockJobDriver *driver,
+ BlockDriverState *bs, int64_t speed,
+ BlockCompletionFunc *cb, void *opaque, Error **errp)
{
BlockBackend *blk;
BlockJob *job;
@@ -129,6 +129,17 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
return NULL;
}
+ if (job_id) {
+ if (!id_wellformed(job_id)) {
+ error_setg(errp, "Invalid job ID '%s'", job_id);
+ return NULL;
+ }
+ if (block_job_get(job_id)) {
+ error_setg(errp, "Job ID '%s' already in use", job_id);
+ return NULL;
+ }
+ }
+
blk = blk_new();
blk_insert_bs(blk, bs);
@@ -140,7 +151,7 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
job->driver = driver;
job->device = g_strdup(bdrv_get_device_name(bs));
- job->id = id_generate(ID_JOB);
+ job->id = job_id ? g_strdup(job_id) : id_generate(ID_JOB);
job->blk = blk;
job->cb = cb;
job->opaque = opaque;
@@ -229,6 +229,8 @@ BlockJob *block_job_get(const char *id);
/**
* block_job_create:
+ * @job_id: The id of the newly-created job, or %NULL to have one
+ * generated automatically.
* @job_type: The class object for the newly-created job.
* @bs: The block
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
@@ -245,9 +247,9 @@ BlockJob *block_job_get(const char *id);
* This function is not part of the public job interface; it should be
* called from a wrapper that is specific to the job type.
*/
-void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
- int64_t speed, BlockCompletionFunc *cb,
- void *opaque, Error **errp);
+void *block_job_create(const char *job_id, const BlockJobDriver *driver,
+ BlockDriverState *bs, int64_t speed,
+ BlockCompletionFunc *cb, void *opaque, Error **errp);
/**
* block_job_sleep_ns:
@@ -94,7 +94,7 @@ static BlockJob *test_block_job_start(unsigned int iterations,
data = g_new0(TestBlockJobCBData, 1);
bs = bdrv_new();
- s = block_job_create(&test_block_job_driver, bs, 0, test_block_job_cb,
+ s = block_job_create(NULL, &test_block_job_driver, bs, 0, test_block_job_cb,
data, &error_abort);
s->iterations = iterations;
s->use_timer = use_timer;