Commit e7c1d78b authored by Kevin Wolf's avatar Kevin Wolf
Browse files

job: Maintain a list of all jobs



This moves the job list from BlockJob to Job. Now we can check for
duplicate IDs in job_create().

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Reviewed-by: default avatarMax Reitz <mreitz@redhat.com>
Reviewed-by: default avatarJohn Snow <jsnow@redhat.com>
parent fd61a701
Loading
Loading
Loading
Loading
+24 −22
Original line number Diff line number Diff line
@@ -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.
 *
@@ -146,26 +144,35 @@ 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_get(const char *id)
BlockJob *block_job_next(BlockJob *bjob)
{
    BlockJob *job;
    Job *job = bjob ? &bjob->job : NULL;

    QLIST_FOREACH(job, &block_jobs, job_list) {
        if (job->job.id && !strcmp(id, job->job.id)) {
            return job;
        }
    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)
{
    Job *job = job_get(id);

    if (job && is_block_job(job)) {
        return container_of(job, BlockJob, job);
    } else {
        return NULL;
    }
}

BlockJobTxn *block_job_txn_new(void)
{
@@ -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,
@@ -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);
@@ -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);
@@ -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;
@@ -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);

+0 −3
Original line number Diff line number Diff line
@@ -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;

+19 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#define JOB_H

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

typedef struct JobDriver JobDriver;

@@ -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;

/**
@@ -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 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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);
}