Skip to content

Commit

Permalink
job: Maintain a list of all jobs
Browse files Browse the repository at this point in the history
This moves the job list from BlockJob to Job. Now we can check for
duplicate IDs in job_create().

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
  • Loading branch information
kevmw committed May 23, 2018
1 parent fd61a70 commit e7c1d78
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 25 deletions.
46 changes: 24 additions & 22 deletions blockjob.c
Expand Up @@ -129,8 +129,6 @@ struct BlockJobTxn {
int refcnt;
};

static QLIST_HEAD(, BlockJob) block_jobs = QLIST_HEAD_INITIALIZER(block_jobs);

/*
* The block job API is composed of two categories of functions.
*
Expand All @@ -146,25 +144,34 @@ static QLIST_HEAD(, BlockJob) block_jobs = QLIST_HEAD_INITIALIZER(block_jobs);
* blockjob_int.h.
*/

BlockJob *block_job_next(BlockJob *job)
static bool is_block_job(Job *job)
{
if (!job) {
return QLIST_FIRST(&block_jobs);
}
return QLIST_NEXT(job, job_list);
return job_type(job) == JOB_TYPE_BACKUP ||
job_type(job) == JOB_TYPE_COMMIT ||
job_type(job) == JOB_TYPE_MIRROR ||
job_type(job) == JOB_TYPE_STREAM;
}

BlockJob *block_job_next(BlockJob *bjob)
{
Job *job = bjob ? &bjob->job : NULL;

do {
job = job_next(job);
} while (job && !is_block_job(job));

return job ? container_of(job, BlockJob, job) : NULL;
}

BlockJob *block_job_get(const char *id)
{
BlockJob *job;
Job *job = job_get(id);

QLIST_FOREACH(job, &block_jobs, job_list) {
if (job->job.id && !strcmp(id, job->job.id)) {
return job;
}
if (job && is_block_job(job)) {
return container_of(job, BlockJob, job);
} else {
return NULL;
}

return NULL;
}

BlockJobTxn *block_job_txn_new(void)
Expand Down Expand Up @@ -253,7 +260,6 @@ void block_job_unref(BlockJob *job)
assert(job->status == BLOCK_JOB_STATUS_NULL);
assert(!job->txn);
BlockDriverState *bs = blk_bs(job->blk);
QLIST_REMOVE(job, job_list);
bs->job = NULL;
block_job_remove_all_bdrv(job);
blk_remove_aio_context_notifier(job->blk,
Expand Down Expand Up @@ -812,7 +818,7 @@ void block_job_cancel_sync_all(void)
BlockJob *job;
AioContext *aio_context;

while ((job = QLIST_FIRST(&block_jobs))) {
while ((job = block_job_next(NULL))) {
aio_context = blk_get_aio_context(job->blk);
aio_context_acquire(aio_context);
block_job_cancel_sync(job);
Expand Down Expand Up @@ -942,10 +948,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
error_setg(errp, "Cannot specify job ID for internal block job");
return NULL;
}
if (block_job_get(job_id)) {
error_setg(errp, "Job ID '%s' already in use", job_id);
return NULL;
}
}

blk = blk_new(perm, shared_perm);
Expand All @@ -961,6 +963,8 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
return NULL;
}

assert(is_block_job(&job->job));

job->driver = driver;
job->blk = blk;
job->cb = cb;
Expand All @@ -983,8 +987,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,

bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);

QLIST_INSERT_HEAD(&block_jobs, job, job_list);

blk_add_aio_context_notifier(blk, block_job_attached_aio_context,
block_job_detach_aio_context, job);

Expand Down
3 changes: 0 additions & 3 deletions include/block/blockjob.h
Expand Up @@ -105,9 +105,6 @@ typedef struct BlockJob {
*/
bool deferred_to_main_loop;

/** Element of the list of block jobs */
QLIST_ENTRY(BlockJob) job_list;

/** Status that is published by the query-block-jobs QMP API */
BlockDeviceIoStatus iostatus;

Expand Down
19 changes: 19 additions & 0 deletions include/qemu/job.h
Expand Up @@ -27,6 +27,7 @@
#define JOB_H

#include "qapi/qapi-types-block-core.h"
#include "qemu/queue.h"

typedef struct JobDriver JobDriver;

Expand All @@ -39,6 +40,9 @@ typedef struct Job {

/** The type of this job. */
const JobDriver *driver;

/** Element of the list of jobs */
QLIST_ENTRY(Job) job_list;
} Job;

/**
Expand Down Expand Up @@ -71,4 +75,19 @@ 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);

/**
* 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.
*/
Job *job_next(Job *job);

/**
* Get the job identified by @id (which must not be %NULL).
*
* Returns the requested job, or %NULL if it doesn't exist.
*/
Job *job_get(const char *id);

#endif
31 changes: 31 additions & 0 deletions job.c
Expand Up @@ -29,6 +29,8 @@
#include "qemu/job.h"
#include "qemu/id.h"

static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);

JobType job_type(const Job *job)
{
return job->driver->job_type;
Expand All @@ -39,6 +41,27 @@ const char *job_type_str(const Job *job)
return JobType_str(job_type(job));
}

Job *job_next(Job *job)
{
if (!job) {
return QLIST_FIRST(&jobs);
}
return QLIST_NEXT(job, job_list);
}

Job *job_get(const char *id)
{
Job *job;

QLIST_FOREACH(job, &jobs, job_list) {
if (job->id && !strcmp(id, job->id)) {
return job;
}
}

return NULL;
}

void *job_create(const char *job_id, const JobDriver *driver, Error **errp)
{
Job *job;
Expand All @@ -48,17 +71,25 @@ void *job_create(const char *job_id, const JobDriver *driver, Error **errp)
error_setg(errp, "Invalid job ID '%s'", job_id);
return NULL;
}
if (job_get(job_id)) {
error_setg(errp, "Job ID '%s' already in use", job_id);
return NULL;
}
}

job = g_malloc0(driver->instance_size);
job->driver = driver;
job->id = g_strdup(job_id);

QLIST_INSERT_HEAD(&jobs, job, job_list);

return job;
}

void job_delete(Job *job)
{
QLIST_REMOVE(job, job_list);

g_free(job->id);
g_free(job);
}

0 comments on commit e7c1d78

Please sign in to comment.