/*
 * Background jobs (long-running operations)
 *
 * Copyright (c) 2011 IBM Corp.
 * Copyright (c) 2012, 2018 Red Hat, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/job.h"
#include "qemu/id.h"
#include "qemu/main-loop.h"
#include "qemu/aio-wait.h"
#include "trace/trace-root.h"
#include "qapi/qapi-events-job.h"

/*
 * The job API is composed of two categories of functions.
 *
 * The first includes functions used by the monitor.  The monitor is
 * peculiar in that it accesses the job list with job_get, and
 * therefore needs consistency across job_get and the actual operation
 * (e.g. job_user_cancel). To achieve this consistency, the caller
 * calls job_lock/job_unlock itself around the whole operation.
 *
 *
 * The second includes functions used by the job drivers and sometimes
 * by the core block layer. These delegate the locking to the callee instead.
 */

/*
 * job_mutex protects the jobs list, but also makes the
 * struct job fields thread-safe.
 */
QemuMutex job_mutex;

/* Protected by job_mutex */
static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);

/* Job State Transition Table */
bool JobSTT[JOB_STATUS__MAX][JOB_STATUS__MAX] = {
                                    /* U, C, R, P, Y, S, W, D, X, E, N */
    /* U: */ [JOB_STATUS_UNDEFINED] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    /* C: */ [JOB_STATUS_CREATED]   = {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1},
    /* R: */ [JOB_STATUS_RUNNING]   = {0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0},
    /* P: */ [JOB_STATUS_PAUSED]    = {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    /* Y: */ [JOB_STATUS_READY]     = {0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0},
    /* S: */ [JOB_STATUS_STANDBY]   = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
    /* W: */ [JOB_STATUS_WAITING]   = {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0},
    /* D: */ [JOB_STATUS_PENDING]   = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0},
    /* X: */ [JOB_STATUS_ABORTING]  = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0},
    /* E: */ [JOB_STATUS_CONCLUDED] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    /* N: */ [JOB_STATUS_NULL]      = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};

bool JobVerbTable[JOB_VERB__MAX][JOB_STATUS__MAX] = {
                                    /* U, C, R, P, Y, S, W, D, X, E, N */
    [JOB_VERB_CANCEL]               = {0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
    [JOB_VERB_PAUSE]                = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
    [JOB_VERB_RESUME]               = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
    [JOB_VERB_SET_SPEED]            = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
    [JOB_VERB_COMPLETE]             = {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0},
    [JOB_VERB_FINALIZE]             = {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
    [JOB_VERB_DISMISS]              = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
    [JOB_VERB_CHANGE]               = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
};

/* Transactional group of jobs */
struct JobTxn {

    /* Is this txn being cancelled? */
    bool aborting;

    /* List of jobs */
    QLIST_HEAD(, Job) jobs;

    /* Reference count */
    int refcnt;
};

void job_lock(void)
{
    qemu_mutex_lock(&job_mutex);
}

void job_unlock(void)
{
    qemu_mutex_unlock(&job_mutex);
}

static void __attribute__((__constructor__)) job_init(void)
{
    qemu_mutex_init(&job_mutex);
}

JobTxn *job_txn_new(void)
{
    JobTxn *txn = g_new0(JobTxn, 1);
    QLIST_INIT(&txn->jobs);
    txn->refcnt = 1;
    return txn;
}

/* Called with job_mutex held. */
static void job_txn_ref_locked(JobTxn *txn)
{
    txn->refcnt++;
}

void job_txn_unref_locked(JobTxn *txn)
{
    if (txn && --txn->refcnt == 0) {
        g_free(txn);
    }
}

void job_txn_unref(JobTxn *txn)
{
    JOB_LOCK_GUARD();
    job_txn_unref_locked(txn);
}

/**
 * @txn: The transaction (may be NULL)
 * @job: Job to add to the transaction
 *
 * Add @job to the transaction.  The @job must not already be in a transaction.
 * The caller must call either job_txn_unref() or job_completed() to release
 * the reference that is automatically grabbed here.
 *
 * If @txn is NULL, the function does nothing.
 *
 * Called with job_mutex held.
 */
static void job_txn_add_job_locked(JobTxn *txn, Job *job)
{
    if (!txn) {
        return;
    }

    assert(!job->txn);
    job->txn = txn;

    QLIST_INSERT_HEAD(&txn->jobs, job, txn_list);
    job_txn_ref_locked(txn);
}

/* Called with job_mutex held. */
static void job_txn_del_job_locked(Job *job)
{
    if (job->txn) {
        QLIST_REMOVE(job, txn_list);
        job_txn_unref_locked(job->txn);
        job->txn = NULL;
    }
}

/* Called with job_mutex held, but releases it temporarily. */
static int job_txn_apply_locked(Job *job, int fn(Job *))
{
    Job *other_job, *next;
    JobTxn *txn = job->txn;
    int rc = 0;

    /*
     * Similar to job_completed_txn_abort, we take each job's lock before
     * applying fn, but since we assume that outer_ctx is held by the caller,
     * we need to release it here to avoid holding the lock twice - which would
     * break AIO_WAIT_WHILE from within fn.
     */
    job_ref_locked(job);

    QLIST_FOREACH_SAFE(other_job, &txn->jobs, txn_list, next) {
        rc = fn(other_job);
        if (rc) {
            break;
        }
    }

    job_unref_locked(job);
    return rc;
}

bool job_is_internal(Job *job)
{
    return (job->id == NULL);
}

/* Called with job_mutex held. */
static void job_state_transition_locked(Job *job, JobStatus s1)
{
    JobStatus s0 = job->status;
    assert(s1 >= 0 && s1 < JOB_STATUS__MAX);
    trace_job_state_transition(job, job->ret,
                               JobSTT[s0][s1] ? "allowed" : "disallowed",
                               JobStatus_str(s0), JobStatus_str(s1));
    assert(JobSTT[s0][s1]);
    job->status = s1;

    if (!job_is_internal(job) && s1 != s0) {
        qapi_event_send_job_status_change(job->id, job->status);
    }
}

int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp)
{
    JobStatus s0 = job->status;
    assert(verb >= 0 && verb < JOB_VERB__MAX);
    trace_job_apply_verb(job, JobStatus_str(s0), JobVerb_str(verb),
                         JobVerbTable[verb][s0] ? "allowed" : "prohibited");
    if (JobVerbTable[verb][s0]) {
        return 0;
    }
    error_setg(errp, "Job '%s' in state '%s' cannot accept command verb '%s'",
               job->id, JobStatus_str(s0), JobVerb_str(verb));
    return -EPERM;
}

JobType job_type(const Job *job)
{
    return job->driver->job_type;
}

const char *job_type_str(const Job *job)
{
    return JobType_str(job_type(job));
}

bool job_is_cancelled_locked(Job *job)
{
    /* force_cancel may be true only if cancelled is true, too */
    assert(job->cancelled || !job->force_cancel);
    return job->force_cancel;
}

bool job_is_paused(Job *job)
{
    JOB_LOCK_GUARD();
    return job->paused;
}

bool job_is_cancelled(Job *job)
{
    JOB_LOCK_GUARD();
    return job_is_cancelled_locked(job);
}

/* Called with job_mutex held. */
static bool job_cancel_requested_locked(Job *job)
{
    return job->cancelled;
}

bool job_cancel_requested(Job *job)
{
    JOB_LOCK_GUARD();
    return job_cancel_requested_locked(job);
}

bool job_is_ready_locked(Job *job)
{
    switch (job->status) {
    case JOB_STATUS_UNDEFINED:
    case JOB_STATUS_CREATED:
    case JOB_STATUS_RUNNING:
    case JOB_STATUS_PAUSED:
    case JOB_STATUS_WAITING:
    case JOB_STATUS_PENDING:
    case JOB_STATUS_ABORTING:
    case JOB_STATUS_CONCLUDED:
    case JOB_STATUS_NULL:
        return false;
    case JOB_STATUS_READY:
    case JOB_STATUS_STANDBY:
        return true;
    default:
        g_assert_not_reached();
    }
    return false;
}

bool job_is_ready(Job *job)
{
    JOB_LOCK_GUARD();
    return job_is_ready_locked(job);
}

bool job_is_completed_locked(Job *job)
{
    switch (job->status) {
    case JOB_STATUS_UNDEFINED:
    case JOB_STATUS_CREATED:
    case JOB_STATUS_RUNNING:
    case JOB_STATUS_PAUSED:
    case JOB_STATUS_READY:
    case JOB_STATUS_STANDBY:
        return false;
    case JOB_STATUS_WAITING:
    case JOB_STATUS_PENDING:
    case JOB_STATUS_ABORTING:
    case JOB_STATUS_CONCLUDED:
    case JOB_STATUS_NULL:
        return true;
    default:
        g_assert_not_reached();
    }
    return false;
}

static bool job_is_completed(Job *job)
{
    JOB_LOCK_GUARD();
    return job_is_completed_locked(job);
}

static bool job_started_locked(Job *job)
{
    return job->co;
}

/* Called with job_mutex held. */
static bool job_should_pause_locked(Job *job)
{
    return job->pause_count > 0;
}

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

Job *job_next(Job *job)
{
    JOB_LOCK_GUARD();
    return job_next_locked(job);
}

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

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

    return NULL;
}

void job_set_aio_context(Job *job, AioContext *ctx)
{
    /* protect against read in job_finish_sync_locked and job_start */
    GLOBAL_STATE_CODE();
    /* protect against read in job_do_yield_locked */
    JOB_LOCK_GUARD();
    /* ensure the job is quiescent while the AioContext is changed */
    assert(job->paused || job_is_completed_locked(job));
    job->aio_context = ctx;
}

/* Called with job_mutex *not* held. */
static void job_sleep_timer_cb(void *opaque)
{
    Job *job = opaque;

    job_enter(job);
}

void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
                 AioContext *ctx, int flags, BlockCompletionFunc *cb,
                 void *opaque, Error **errp)
{
    Job *job;

    JOB_LOCK_GUARD();

    if (job_id) {
        if (flags & JOB_INTERNAL) {
            error_setg(errp, "Cannot specify job ID for internal job");
            return NULL;
        }
        if (!id_wellformed(job_id)) {
            error_setg(errp, "Invalid job ID '%s'", job_id);
            return NULL;
        }
        if (job_get_locked(job_id)) {
            error_setg(errp, "Job ID '%s' already in use", job_id);
            return NULL;
        }
    } else if (!(flags & JOB_INTERNAL)) {
        error_setg(errp, "An explicit job ID is required");
        return NULL;
    }

    job = g_malloc0(driver->instance_size);
    job->driver        = driver;
    job->id            = g_strdup(job_id);
    job->refcnt        = 1;
    job->aio_context   = ctx;
    job->busy          = false;
    job->paused        = true;
    job->pause_count   = 1;
    job->auto_finalize = !(flags & JOB_MANUAL_FINALIZE);
    job->auto_dismiss  = !(flags & JOB_MANUAL_DISMISS);
    job->cb            = cb;
    job->opaque        = opaque;

    progress_init(&job->progress);

    notifier_list_init(&job->on_finalize_cancelled);
    notifier_list_init(&job->on_finalize_completed);
    notifier_list_init(&job->on_pending);
    notifier_list_init(&job->on_ready);
    notifier_list_init(&job->on_idle);

    job_state_transition_locked(job, JOB_STATUS_CREATED);
    aio_timer_init(qemu_get_aio_context(), &job->sleep_timer,
                   QEMU_CLOCK_REALTIME, SCALE_NS,
                   job_sleep_timer_cb, job);

    QLIST_INSERT_HEAD(&jobs, job, job_list);

    /* Single jobs are modeled as single-job transactions for sake of
     * consolidating the job management logic */
    if (!txn) {
        txn = job_txn_new();
        job_txn_add_job_locked(txn, job);
        job_txn_unref_locked(txn);
    } else {
        job_txn_add_job_locked(txn, job);
    }

    return job;
}

void job_ref_locked(Job *job)
{
    ++job->refcnt;
}

void job_unref_locked(Job *job)
{
    GLOBAL_STATE_CODE();

    if (--job->refcnt == 0) {
        assert(job->status == JOB_STATUS_NULL);
        assert(!timer_pending(&job->sleep_timer));
        assert(!job->txn);

        if (job->driver->free) {
            job_unlock();
            job->driver->free(job);
            job_lock();
        }

        QLIST_REMOVE(job, job_list);

        progress_destroy(&job->progress);
        error_free(job->err);
        g_free(job->id);
        g_free(job);
    }
}

void job_progress_update(Job *job, uint64_t done)
{
    progress_work_done(&job->progress, done);
}

void job_progress_set_remaining(Job *job, uint64_t remaining)
{
    progress_set_remaining(&job->progress, remaining);
}

void job_progress_increase_remaining(Job *job, uint64_t delta)
{
    progress_increase_remaining(&job->progress, delta);
}

/**
 * To be called when a cancelled job is finalised.
 * Called with job_mutex held.
 */
static void job_event_cancelled_locked(Job *job)
{
    notifier_list_notify(&job->on_finalize_cancelled, job);
}

/**
 * To be called when a successfully completed job is finalised.
 * Called with job_mutex held.
 */
static void job_event_completed_locked(Job *job)
{
    notifier_list_notify(&job->on_finalize_completed, job);
}

/* Called with job_mutex held. */
static void job_event_pending_locked(Job *job)
{
    notifier_list_notify(&job->on_pending, job);
}

/* Called with job_mutex held. */
static void job_event_ready_locked(Job *job)
{
    notifier_list_notify(&job->on_ready, job);
}

/* Called with job_mutex held. */
static void job_event_idle_locked(Job *job)
{
    notifier_list_notify(&job->on_idle, job);
}

void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
{
    if (!job_started_locked(job)) {
        return;
    }
    if (job->deferred_to_main_loop) {
        return;
    }

    if (job->busy) {
        return;
    }

    if (fn && !fn(job)) {
        return;
    }

    assert(!job->deferred_to_main_loop);
    timer_del(&job->sleep_timer);
    job->busy = true;
    job_unlock();
    aio_co_wake(job->co);
    job_lock();
}

void job_enter(Job *job)
{
    JOB_LOCK_GUARD();
    job_enter_cond_locked(job, NULL);
}

/* Yield, and schedule a timer to reenter the coroutine after @ns nanoseconds.
 * Reentering the job coroutine with job_enter() before the timer has expired
 * is allowed and cancels the timer.
 *
 * If @ns is (uint64_t) -1, no timer is scheduled and job_enter() must be
 * called explicitly.
 *
 * Called with job_mutex held, but releases it temporarily.
 */
static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
{
    AioContext *next_aio_context;

    if (ns != -1) {
        timer_mod(&job->sleep_timer, ns);
    }
    job->busy = false;
    job_event_idle_locked(job);
    job_unlock();
    qemu_coroutine_yield();
    job_lock();

    next_aio_context = job->aio_context;
    /*
     * Coroutine has resumed, but in the meanwhile the job AioContext
     * might have changed via bdrv_try_change_aio_context(), so we need to move
     * the coroutine too in the new aiocontext.
     */
    while (qemu_get_current_aio_context() != next_aio_context) {
        job_unlock();
        aio_co_reschedule_self(next_aio_context);
        job_lock();
        next_aio_context = job->aio_context;
    }

    /* Set by job_enter_cond_locked() before re-entering the coroutine.  */
    assert(job->busy);
}

/* Called with job_mutex held, but releases it temporarily. */
static void coroutine_fn job_pause_point_locked(Job *job)
{
    assert(job && job_started_locked(job));

    if (!job_should_pause_locked(job)) {
        return;
    }
    if (job_is_cancelled_locked(job)) {
        return;
    }

    if (job->driver->pause) {
        job_unlock();
        job->driver->pause(job);
        job_lock();
    }

    if (job_should_pause_locked(job) && !job_is_cancelled_locked(job)) {
        JobStatus status = job->status;
        job_state_transition_locked(job, status == JOB_STATUS_READY
                                    ? JOB_STATUS_STANDBY
                                    : JOB_STATUS_PAUSED);
        job->paused = true;
        /*
         * Stay paused across back-to-back pause requests: a transient
         * paused == false while pause_count > 0 would be observed as
         * "not paused" by job_set_aio_context() and other drain consumers.
         */
        do {
            job_do_yield_locked(job, -1);
        } while (job_should_pause_locked(job) && !job_is_cancelled_locked(job));
        job->paused = false;
        job_state_transition_locked(job, status);
    }

    if (job->driver->resume) {
        job_unlock();
        job->driver->resume(job);
        job_lock();
    }
}

void coroutine_fn job_pause_point(Job *job)
{
    JOB_LOCK_GUARD();
    job_pause_point_locked(job);
}

void coroutine_fn job_yield(Job *job)
{
    JOB_LOCK_GUARD();
    assert(job->busy);

    /* Check cancellation *before* setting busy = false, too!  */
    if (job_is_cancelled_locked(job)) {
        return;
    }

    if (!job_should_pause_locked(job)) {
        job_do_yield_locked(job, -1);
    }

    job_pause_point_locked(job);
}

void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
{
    JOB_LOCK_GUARD();
    assert(job->busy);

    /* Check cancellation *before* setting busy = false, too!  */
    if (job_is_cancelled_locked(job)) {
        return;
    }

    if (!job_should_pause_locked(job)) {
        job_do_yield_locked(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns);
    }

    job_pause_point_locked(job);
}

/* Assumes the job_mutex is held */
static bool job_timer_not_pending_locked(Job *job)
{
    return !timer_pending(&job->sleep_timer);
}

void job_pause_locked(Job *job)
{
    job->pause_count++;
    if (!job->paused) {
        job_enter_cond_locked(job, NULL);
    }
}

void job_pause(Job *job)
{
    JOB_LOCK_GUARD();
    job_pause_locked(job);
}

void job_resume_locked(Job *job)
{
    assert(job->pause_count > 0);
    job->pause_count--;
    if (job->pause_count) {
        return;
    }

    /* kick only if no timer is pending */
    job_enter_cond_locked(job, job_timer_not_pending_locked);
}

void job_resume(Job *job)
{
    JOB_LOCK_GUARD();
    job_resume_locked(job);
}

void job_user_pause_locked(Job *job, Error **errp)
{
    if (job_apply_verb_locked(job, JOB_VERB_PAUSE, errp)) {
        return;
    }
    if (job->user_paused) {
        error_setg(errp, "Job is already paused");
        return;
    }
    job->user_paused = true;
    job_pause_locked(job);
}

bool job_user_paused_locked(Job *job)
{
    return job->user_paused;
}

void job_user_resume_locked(Job *job, Error **errp)
{
    assert(job);
    GLOBAL_STATE_CODE();
    if (!job->user_paused || job->pause_count <= 0) {
        error_setg(errp, "Can't resume a job that was not paused");
        return;
    }
    if (job_apply_verb_locked(job, JOB_VERB_RESUME, errp)) {
        return;
    }
    if (job->driver->user_resume) {
        job_unlock();
        job->driver->user_resume(job);
        job_lock();
    }
    job->user_paused = false;
    job_resume_locked(job);
}

/* Called with job_mutex held, but releases it temporarily. */
static void job_do_dismiss_locked(Job *job)
{
    assert(job);
    job->busy = false;
    job->paused = false;
    job->deferred_to_main_loop = true;

    job_txn_del_job_locked(job);

    job_state_transition_locked(job, JOB_STATUS_NULL);
    job_unref_locked(job);
}

void job_dismiss_locked(Job **jobptr, Error **errp)
{
    Job *job = *jobptr;
    /* similarly to _complete, this is QMP-interface only. */
    assert(job->id);
    if (job_apply_verb_locked(job, JOB_VERB_DISMISS, errp)) {
        return;
    }

    job_do_dismiss_locked(job);
    *jobptr = NULL;
}

void job_early_fail(Job *job)
{
    JOB_LOCK_GUARD();
    assert(job->status == JOB_STATUS_CREATED);
    job_do_dismiss_locked(job);
}

/* Called with job_mutex held. */
static void job_conclude_locked(Job *job)
{
    job_state_transition_locked(job, JOB_STATUS_CONCLUDED);
    if (job->auto_dismiss || !job_started_locked(job)) {
        job_do_dismiss_locked(job);
    }
}

/* Called with job_mutex held. */
static void job_update_rc_locked(Job *job)
{
    if (!job->ret && job_is_cancelled_locked(job)) {
        job->ret = -ECANCELED;
    }
    if (job->ret) {
        if (!job->err) {
            error_setg(&job->err, "%s", strerror(-job->ret));
        }
        job_state_transition_locked(job, JOB_STATUS_ABORTING);
    }
}

static void job_commit(Job *job)
{
    assert(!job->ret);
    GLOBAL_STATE_CODE();
    if (job->driver->commit) {
        job->driver->commit(job);
    }
}

static void job_abort(Job *job)
{
    assert(job->ret);
    GLOBAL_STATE_CODE();
    if (job->driver->abort) {
        job->driver->abort(job);
    }
}

static void job_clean(Job *job)
{
    GLOBAL_STATE_CODE();
    if (job->driver->clean) {
        job->driver->clean(job);
    }
}

/*
 * Called with job_mutex held, but releases it temporarily.
 */
static int job_finalize_single_locked(Job *job)
{
    int job_ret;

    assert(job_is_completed_locked(job));

    /* Ensure abort is called for late-transactional failures */
    job_update_rc_locked(job);

    job_ret = job->ret;
    job_unlock();

    if (!job_ret) {
        job_commit(job);
    } else {
        job_abort(job);
    }
    job_clean(job);

    if (job->cb) {
        job->cb(job->opaque, job_ret);
    }

    job_lock();

    /* Emit events only if we actually started */
    if (job_started_locked(job)) {
        if (job_is_cancelled_locked(job)) {
            job_event_cancelled_locked(job);
        } else {
            job_event_completed_locked(job);
        }
    }

    job_txn_del_job_locked(job);
    job_conclude_locked(job);
    return 0;
}

/*
 * Called with job_mutex held, but releases it temporarily.
 */
static void job_cancel_async_locked(Job *job, bool force)
{
    GLOBAL_STATE_CODE();
    if (job->driver->cancel) {
        job_unlock();
        force = job->driver->cancel(job, force);
        job_lock();
    } else {
        /* No .cancel() means the job will behave as if force-cancelled */
        force = true;
    }

    if (job->user_paused) {
        /* Do not call job_enter here, the caller will handle it.  */
        if (job->driver->user_resume) {
            job_unlock();
            job->driver->user_resume(job);
            job_lock();
        }
        job->user_paused = false;
        assert(job->pause_count > 0);
        job->pause_count--;
    }

    /*
     * Ignore soft cancel requests after the job is already done
     * (We will still invoke job->driver->cancel() above, but if the
     * job driver supports soft cancelling and the job is done, that
     * should be a no-op, too.  We still call it so it can override
     * @force.)
     */
    if (force || !job->deferred_to_main_loop) {
        job->cancelled = true;
        /* To prevent 'force == false' overriding a previous 'force == true' */
        job->force_cancel |= force;
    }
}

/*
 * Called with job_mutex held, but releases it temporarily.
 */
static void job_completed_txn_abort_locked(Job *job)
{
    JobTxn *txn = job->txn;
    Job *other_job;

    if (txn->aborting) {
        /*
         * We are cancelled by another job, which will handle everything.
         */
        return;
    }
    txn->aborting = true;
    job_txn_ref_locked(txn);

    job_ref_locked(job);

    /* Other jobs are effectively cancelled by us, set the status for
     * them; this job, however, may or may not be cancelled, depending
     * on the caller, so leave it. */
    QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
        if (other_job != job) {
            /*
             * This is a transaction: If one job failed, no result will matter.
             * Therefore, pass force=true to terminate all other jobs as quickly
             * as possible.
             */
            job_cancel_async_locked(other_job, true);
        }
    }
    while (!QLIST_EMPTY(&txn->jobs)) {
        other_job = QLIST_FIRST(&txn->jobs);
        if (!job_is_completed_locked(other_job)) {
            assert(job_cancel_requested_locked(other_job));
            job_finish_sync_locked(other_job, NULL, NULL);
        }
        job_finalize_single_locked(other_job);
    }

    job_unref_locked(job);
    job_txn_unref_locked(txn);
}

/* Called with job_mutex held, but releases it temporarily */
static int job_prepare_locked(Job *job)
{
    int ret;

    GLOBAL_STATE_CODE();

    if (job->ret == 0 && job->driver->prepare) {
        job_unlock();
        ret = job->driver->prepare(job);
        job_lock();
        job->ret = ret;
        job_update_rc_locked(job);
    }

    return job->ret;
}

/* Called with job_mutex held */
static int job_needs_finalize_locked(Job *job)
{
    return !job->auto_finalize;
}

/* Called with job_mutex held */
static void job_do_finalize_locked(Job *job)
{
    int rc;
    assert(job && job->txn);

    /* prepare the transaction to complete */
    rc = job_txn_apply_locked(job, job_prepare_locked);
    if (rc) {
        job_completed_txn_abort_locked(job);
    } else {
        job_txn_apply_locked(job, job_finalize_single_locked);
    }
}

void job_finalize_locked(Job *job, Error **errp)
{
    assert(job && job->id);
    if (job_apply_verb_locked(job, JOB_VERB_FINALIZE, errp)) {
        return;
    }
    job_do_finalize_locked(job);
}

/* Called with job_mutex held. */
static int job_transition_to_pending_locked(Job *job)
{
    job_state_transition_locked(job, JOB_STATUS_PENDING);
    if (!job->auto_finalize) {
        job_event_pending_locked(job);
    }
    return 0;
}

void job_transition_to_ready(Job *job)
{
    JOB_LOCK_GUARD();
    job_state_transition_locked(job, JOB_STATUS_READY);
    job_event_ready_locked(job);
}

/* Called with job_mutex held. */
static void job_completed_txn_success_locked(Job *job)
{
    JobTxn *txn = job->txn;
    Job *other_job;

    job_state_transition_locked(job, JOB_STATUS_WAITING);

    /*
     * Successful completion, see if there are other running jobs in this
     * txn.
     */
    QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
        if (!job_is_completed_locked(other_job)) {
            return;
        }
        assert(other_job->ret == 0);
    }

    job_txn_apply_locked(job, job_transition_to_pending_locked);

    /* If no jobs need manual finalization, automatically do so */
    if (job_txn_apply_locked(job, job_needs_finalize_locked) == 0) {
        job_do_finalize_locked(job);
    }
}

/* Called with job_mutex held. */
static void job_completed_locked(Job *job)
{
    assert(job && job->txn && !job_is_completed_locked(job));

    job_update_rc_locked(job);
    trace_job_completed(job, job->ret);
    if (job->ret) {
        job_completed_txn_abort_locked(job);
    } else {
        job_completed_txn_success_locked(job);
    }
}

/**
 * Useful only as a type shim for aio_bh_schedule_oneshot.
 * Called with job_mutex *not* held.
 */
static void job_exit(void *opaque)
{
    Job *job = (Job *)opaque;
    JOB_LOCK_GUARD();
    job_ref_locked(job);

    /* This is a lie, we're not quiescent, but still doing the completion
     * callbacks. However, completion callbacks tend to involve operations that
     * drain block nodes, and if .drained_poll still returned true, we would
     * deadlock. */
    job->busy = false;
    job_event_idle_locked(job);

    job_completed_locked(job);
    job_unref_locked(job);
}

/**
 * All jobs must allow a pause point before entering their job proper. This
 * ensures that jobs can be paused prior to being started, then resumed later.
 */
static void coroutine_fn job_co_entry(void *opaque)
{
    Job *job = opaque;
    int ret;

    assert(job && job->driver && job->driver->run);
    WITH_JOB_LOCK_GUARD() {
        assert(job->aio_context == qemu_get_current_aio_context());
        job_pause_point_locked(job);
    }
    ret = job->driver->run(job, &job->err);
    WITH_JOB_LOCK_GUARD() {
        job->ret = ret;
        job->deferred_to_main_loop = true;
        job->busy = true;
    }
    aio_bh_schedule_oneshot(qemu_get_aio_context(), job_exit, job);
}

void job_start(Job *job)
{
    assert(qemu_in_main_thread());

    WITH_JOB_LOCK_GUARD() {
        assert(job && !job_started_locked(job) && job->paused &&
            job->driver && job->driver->run);
        job->co = qemu_coroutine_create(job_co_entry, job);
        job->pause_count--;
        job->busy = true;
        job->paused = false;
        job_state_transition_locked(job, JOB_STATUS_RUNNING);
    }
    aio_co_enter(job->aio_context, job->co);
}

void job_cancel_locked(Job *job, bool force)
{
    if (job->status == JOB_STATUS_CONCLUDED) {
        job_do_dismiss_locked(job);
        return;
    }
    job_cancel_async_locked(job, force);
    if (!job_started_locked(job)) {
        job_completed_locked(job);
    } else if (job->deferred_to_main_loop) {
        /*
         * job_cancel_async() ignores soft-cancel requests for jobs
         * that are already done (i.e. deferred to the main loop).  We
         * have to check again whether the job is really cancelled.
         * (job_cancel_requested() and job_is_cancelled() are equivalent
         * here, because job_cancel_async() will make soft-cancel
         * requests no-ops when deferred_to_main_loop is true.  We
         * choose to call job_is_cancelled() to show that we invoke
         * job_completed_txn_abort() only for force-cancelled jobs.)
         */
        if (job_is_cancelled_locked(job)) {
            job_completed_txn_abort_locked(job);
        }
    } else {
        job_enter_cond_locked(job, NULL);
    }
}

void job_user_cancel_locked(Job *job, bool force, Error **errp)
{
    if (job_apply_verb_locked(job, JOB_VERB_CANCEL, errp)) {
        return;
    }
    job_cancel_locked(job, force);
}

/* A wrapper around job_cancel_locked() taking an Error ** parameter so it may
 * be used with job_finish_sync_locked() without the need for (rather nasty)
 * function pointer casts there.
 *
 * Called with job_mutex held.
 */
static void job_cancel_err_locked(Job *job, Error **errp)
{
    job_cancel_locked(job, false);
}

/**
 * Same as job_cancel_err(), but force-cancel.
 * Called with job_mutex held.
 */
static void job_force_cancel_err_locked(Job *job, Error **errp)
{
    job_cancel_locked(job, true);
}

int job_cancel_sync_locked(Job *job, bool force)
{
    if (force) {
        return job_finish_sync_locked(job, &job_force_cancel_err_locked, NULL);
    } else {
        return job_finish_sync_locked(job, &job_cancel_err_locked, NULL);
    }
}

int job_cancel_sync(Job *job, bool force)
{
    JOB_LOCK_GUARD();
    return job_cancel_sync_locked(job, force);
}

void job_cancel_sync_all(void)
{
    Job *job;
    JOB_LOCK_GUARD();

    while ((job = job_next_locked(NULL))) {
        job_cancel_sync_locked(job, true);
    }
}

int job_complete_sync_locked(Job *job, Error **errp)
{
    return job_finish_sync_locked(job, job_complete_locked, errp);
}

void job_complete_locked(Job *job, Error **errp)
{
    /* Should not be reachable via external interface for internal jobs */
    assert(job->id);
    GLOBAL_STATE_CODE();
    if (job_apply_verb_locked(job, JOB_VERB_COMPLETE, errp)) {
        return;
    }
    if (job_cancel_requested_locked(job) || !job->driver->complete) {
        error_setg(errp, "The active block job '%s' cannot be completed",
                   job->id);
        return;
    }

    job_unlock();
    job->driver->complete(job, errp);
    job_lock();
}

int job_finish_sync_locked(Job *job,
                           void (*finish)(Job *, Error **errp),
                           Error **errp)
{
    Error *local_err = NULL;
    int ret;
    GLOBAL_STATE_CODE();

    job_ref_locked(job);

    if (finish) {
        finish(job, &local_err);
    }
    if (local_err) {
        error_propagate(errp, local_err);
        job_unref_locked(job);
        return -EBUSY;
    }

    job_unlock();
    AIO_WAIT_WHILE_UNLOCKED(job->aio_context,
                            (job_enter(job), !job_is_completed(job)));
    job_lock();

    ret = (job_is_cancelled_locked(job) && job->ret == 0)
          ? -ECANCELED : job->ret;
    job_unref_locked(job);
    return ret;
}
