Commit 3718d8ab authored by Fam Zheng's avatar Fam Zheng Committed by Stefan Hajnoczi
Browse files

block: Replace in_use with operation blocker



This drops BlockDriverState.in_use with op_blockers:

  - Call bdrv_op_block_all in place of bdrv_set_in_use(bs, 1).

  - Call bdrv_op_unblock_all in place of bdrv_set_in_use(bs, 0).

  - Check bdrv_op_is_blocked() in place of bdrv_in_use(bs).

    The specific types are used, e.g. in place of starting block backup,
    bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP, ...).

    There is one exception in block_job_create, where
    bdrv_op_blocker_is_empty() is used, because we don't know the operation
    type here. This doesn't matter because in a few commits away we will drop
    the check and move it to callers that _do_ know the type.

  - Check bdrv_op_blocker_is_empty() in place of assert(!bs->in_use).

Note: there is only bdrv_op_block_all and bdrv_op_unblock_all callers at
this moment. So although the checks are specific to op types, this
changes can still be seen as identical logic with previously with
in_use. The difference is error message are improved because of blocker
error info.

Signed-off-by: default avatarFam Zheng <famz@redhat.com>
Reviewed-by: default avatarJeff Cody <jcody@redhat.com>
Reviewed-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent fbe40ff7
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ typedef struct BlkMigDevState {
    unsigned long *aio_bitmap;
    int64_t completed_sectors;
    BdrvDirtyBitmap *dirty_bitmap;
    Error *blocker;
} BlkMigDevState;

typedef struct BlkMigBlock {
@@ -361,7 +362,8 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
        bmds->completed_sectors = 0;
        bmds->shared_base = block_mig_state.shared_base;
        alloc_aio_bitmap(bmds);
        bdrv_set_in_use(bs, 1);
        error_setg(&bmds->blocker, "block device is in use by migration");
        bdrv_op_block_all(bs, bmds->blocker);
        bdrv_ref(bs);

        block_mig_state.total_sector_sum += sectors;
@@ -599,7 +601,8 @@ static void blk_mig_cleanup(void)
    blk_mig_lock();
    while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
        bdrv_set_in_use(bmds->bs, 0);
        bdrv_op_unblock_all(bmds->bs, bmds->blocker);
        error_free(bmds->blocker);
        bdrv_unref(bmds->bs);
        g_free(bmds->aio_bitmap);
        g_free(bmds);
+7 −17
Original line number Diff line number Diff line
@@ -1949,7 +1949,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
    bs_dest->refcnt             = bs_src->refcnt;

    /* job */
    bs_dest->in_use             = bs_src->in_use;
    bs_dest->job                = bs_src->job;

    /* keep the same entry in bdrv_states */
@@ -1992,7 +1991,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
    assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
    assert(bs_new->job == NULL);
    assert(bs_new->dev == NULL);
    assert(bs_new->in_use == 0);
    assert(bdrv_op_blocker_is_empty(bs_new));
    assert(bs_new->io_limits_enabled == false);
    assert(!throttle_have_timer(&bs_new->throttle_state));

@@ -2011,7 +2010,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
    /* Check a few fields that should remain attached to the device */
    assert(bs_new->dev == NULL);
    assert(bs_new->job == NULL);
    assert(bs_new->in_use == 0);
    assert(bdrv_op_blocker_is_empty(bs_new));
    assert(bs_new->io_limits_enabled == false);
    assert(!throttle_have_timer(&bs_new->throttle_state));

@@ -2056,7 +2055,7 @@ static void bdrv_delete(BlockDriverState *bs)
{
    assert(!bs->dev);
    assert(!bs->job);
    assert(!bs->in_use);
    assert(bdrv_op_blocker_is_empty(bs));
    assert(!bs->refcnt);
    assert(QLIST_EMPTY(&bs->dirty_bitmaps));

@@ -2238,7 +2237,8 @@ int bdrv_commit(BlockDriverState *bs)
        return -ENOTSUP;
    }

    if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) {
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT, NULL) ||
        bdrv_op_is_blocked(bs->backing_hd, BLOCK_OP_TYPE_COMMIT, NULL)) {
        return -EBUSY;
    }

@@ -3500,8 +3500,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
        return -ENOTSUP;
    if (bs->read_only)
        return -EACCES;
    if (bdrv_in_use(bs))
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
        return -EBUSY;
    }
    ret = drv->bdrv_truncate(bs, offset);
    if (ret == 0) {
        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
@@ -5401,17 +5402,6 @@ bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
    return true;
}

void bdrv_set_in_use(BlockDriverState *bs, int in_use)
{
    assert(bs->in_use != in_use);
    bs->in_use = in_use;
}

int bdrv_in_use(BlockDriverState *bs)
{
    return bs->in_use;
}

void bdrv_iostatus_enable(BlockDriverState *bs)
{
    bs->iostatus_enabled = true;
+9 −10
Original line number Diff line number Diff line
@@ -1334,8 +1334,8 @@ static void external_snapshot_prepare(BlkTransactionState *common,
        return;
    }

    if (bdrv_in_use(state->old_bs)) {
        error_set(errp, QERR_DEVICE_IN_USE, device);
    if (bdrv_op_is_blocked(state->old_bs,
                           BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
        return;
    }

@@ -1557,8 +1557,7 @@ exit:

static void eject_device(BlockDriverState *bs, int force, Error **errp)
{
    if (bdrv_in_use(bs)) {
        error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
        return;
    }
    if (!bdrv_dev_has_removable_media(bs)) {
@@ -1760,14 +1759,16 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
    const char *id = qdict_get_str(qdict, "id");
    BlockDriverState *bs;
    Error *local_err = NULL;

    bs = bdrv_find(id);
    if (!bs) {
        qerror_report(QERR_DEVICE_NOT_FOUND, id);
        return -1;
    }
    if (bdrv_in_use(bs)) {
        qerror_report(QERR_DEVICE_IN_USE, id);
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
        error_report("%s", error_get_pretty(local_err));
        error_free(local_err);
        return -1;
    }

@@ -2023,8 +2024,7 @@ void qmp_drive_backup(const char *device, const char *target,
        }
    }

    if (bdrv_in_use(bs)) {
        error_set(errp, QERR_DEVICE_IN_USE, device);
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
        return;
    }

@@ -2157,8 +2157,7 @@ void qmp_drive_mirror(const char *device, const char *target,
        }
    }

    if (bdrv_in_use(bs)) {
        error_set(errp, QERR_DEVICE_IN_USE, device);
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR, errp)) {
        return;
    }

+9 −5
Original line number Diff line number Diff line
@@ -41,14 +41,16 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
{
    BlockJob *job;

    if (bs->job || bdrv_in_use(bs)) {
    if (bs->job || !bdrv_op_blocker_is_empty(bs)) {
        error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
        return NULL;
    }
    bdrv_ref(bs);
    bdrv_set_in_use(bs, 1);

    job = g_malloc0(driver->instance_size);
    error_setg(&job->blocker, "block device is in use by block job: %s",
               BlockJobType_lookup[driver->job_type]);
    bdrv_op_block_all(bs, job->blocker);

    job->driver        = driver;
    job->bs            = bs;
    job->cb            = cb;
@@ -63,8 +65,9 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
        block_job_set_speed(job, speed, &local_err);
        if (local_err) {
            bs->job = NULL;
            bdrv_op_unblock_all(bs, job->blocker);
            error_free(job->blocker);
            g_free(job);
            bdrv_set_in_use(bs, 0);
            error_propagate(errp, local_err);
            return NULL;
        }
@@ -79,8 +82,9 @@ void block_job_completed(BlockJob *job, int ret)
    assert(bs->job == job);
    job->cb(job->opaque, ret);
    bs->job = NULL;
    bdrv_op_unblock_all(bs, job->blocker);
    error_free(job->blocker);
    g_free(job);
    bdrv_set_in_use(bs, 0);
}

void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
+12 −6
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ struct VirtIOBlockDataPlane {
                                             queue */

    unsigned int num_reqs;

    /* Operation blocker on BDS */
    Error *blocker;
};

/* Raise an interrupt to signal guest, if necessary */
@@ -350,6 +353,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
{
    VirtIOBlockDataPlane *s;
    int fd;
    Error *local_err = NULL;

    *dataplane = NULL;

@@ -372,9 +376,10 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
    /* If dataplane is (re-)enabled while the guest is running there could be
     * block jobs that can conflict.
     */
    if (bdrv_in_use(blk->conf.bs)) {
        error_setg(errp,
                   "cannot start dataplane thread while device is in use");
    if (bdrv_op_is_blocked(blk->conf.bs, BLOCK_OP_TYPE_DATAPLANE, &local_err)) {
        error_report("cannot start dataplane thread: %s",
                      error_get_pretty(local_err));
        error_free(local_err);
        return;
    }

@@ -406,8 +411,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
    }
    s->ctx = iothread_get_aio_context(s->iothread);

    /* Prevent block operations that conflict with data plane thread */
    bdrv_set_in_use(blk->conf.bs, 1);
    error_setg(&s->blocker, "block device is in use by data plane");
    bdrv_op_block_all(blk->conf.bs, s->blocker);

    *dataplane = s;
}
@@ -420,7 +425,8 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
    }

    virtio_blk_data_plane_stop(s);
    bdrv_set_in_use(s->blk->conf.bs, 0);
    bdrv_op_unblock_all(s->blk->conf.bs, s->blocker);
    error_free(s->blocker);
    object_unref(OBJECT(s->iothread));
    g_free(s);
}
Loading