Commit 7ca7f0f6 authored by Kevin Wolf's avatar Kevin Wolf
Browse files

block: Decouple throttling from BlockDriverState



This moves the throttling related part of the BDS life cycle management
to BlockBackend. The throttling group reference is now kept even when no
medium is inserted.

With this commit, throttling isn't disabled and then re-enabled any more
during graph reconfiguration. This fixes the temporary breakage of I/O
throttling when used with live snapshots or block jobs that manipulate
the graph.

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Reviewed-by: default avatarAlberto Garcia <berto@igalia.com>
Acked-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent bb9aaeca
Loading
Loading
Loading
Loading
+0 −34
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@
#include "qmp-commands.h"
#include "qemu/timer.h"
#include "qapi-event.h"
#include "block/throttle-groups.h"
#include "qemu/cutils.h"
#include "qemu/id.h"

@@ -2121,11 +2120,6 @@ static void bdrv_close(BlockDriverState *bs)

    assert(!bs->job);

    /* Disable I/O limits and drain all pending throttled requests */
    if (bs->blk && blk_get_public(bs->blk)->throttle_state) {
        blk_io_limits_disable(bs->blk);
    }

    bdrv_drained_begin(bs); /* complete I/O */
    bdrv_flush(bs);
    bdrv_drain(bs); /* in case flush left pending I/O */
@@ -2254,26 +2248,6 @@ static void swap_feature_fields(BlockDriverState *bs_top,
    bdrv_move_feature_fields(&tmp, bs_top);
    bdrv_move_feature_fields(bs_top, bs_new);
    bdrv_move_feature_fields(bs_new, &tmp);

    assert(!bs_new->blk);
    if (bs_top->blk && blk_get_public(bs_top->blk)->throttle_state) {
        /*
         * FIXME Need to break I/O throttling with graph manipulations
         * temporarily because of conflicting invariants (3. will go away when
         * throttling is fully converted to work on BlockBackends):
         *
         * 1. Every BlockBackend has a single root BDS
         * 2. I/O throttling functions require an attached BlockBackend
         * 3. We need to first enable throttling on the new BDS and then
         *    disable it on the old one (because of throttle group refcounts)
         */
#if 0
        bdrv_io_limits_enable(bs_new, throttle_group_get_name(bs_top));
        bdrv_io_limits_disable(bs_top);
#else
        abort();
#endif
    }
}

/*
@@ -3674,10 +3648,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
        baf->detach_aio_context(baf->opaque);
    }

    if (bs->blk && blk_get_public(bs->blk)->throttle_state) {
        throttle_timers_detach_aio_context(
            &blk_get_public(bs->blk)->throttle_timers);
    }
    if (bs->drv->bdrv_detach_aio_context) {
        bs->drv->bdrv_detach_aio_context(bs);
    }
@@ -3711,10 +3681,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
    if (bs->drv->bdrv_attach_aio_context) {
        bs->drv->bdrv_attach_aio_context(bs, new_context);
    }
    if (bs->blk && blk_get_public(bs->blk)->throttle_state) {
        throttle_timers_attach_aio_context(
            &blk_get_public(bs->blk)->throttle_timers, new_context);
    }

    QLIST_FOREACH(ban, &bs->aio_notifiers, list) {
        ban->attached_aio_context(new_context, ban->opaque);
+14 −23
Original line number Diff line number Diff line
@@ -188,10 +188,6 @@ static void blk_delete(BlockBackend *blk)
    }
    assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
    assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
    if (blk->root_state.throttle_state) {
        g_free(blk->root_state.throttle_group);
        throttle_group_unref(blk->root_state.throttle_state);
    }
    QTAILQ_REMOVE(&block_backends, blk, link);
    drive_info_del(blk->legacy_dinfo);
    block_acct_cleanup(&blk->stats);
@@ -445,12 +441,12 @@ void blk_remove_bs(BlockBackend *blk)
    assert(blk->root->bs->blk == blk);

    notifier_list_notify(&blk->remove_bs_notifiers, blk);

    blk_update_root_state(blk);
    if (blk->public.throttle_state) {
        blk_io_limits_disable(blk);
        throttle_timers_detach_aio_context(&blk->public.throttle_timers);
    }

    blk_update_root_state(blk);

    blk->root->bs->blk = NULL;
    bdrv_root_unref_child(blk->root);
    blk->root = NULL;
@@ -468,6 +464,10 @@ void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
    bs->blk = blk;

    notifier_list_notify(&blk->insert_bs_notifiers, blk);
    if (blk->public.throttle_state) {
        throttle_timers_attach_aio_context(
            &blk->public.throttle_timers, bdrv_get_aio_context(bs));
    }
}

/*
@@ -1374,7 +1374,14 @@ void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
    BlockDriverState *bs = blk_bs(blk);

    if (bs) {
        if (blk->public.throttle_state) {
            throttle_timers_detach_aio_context(&blk->public.throttle_timers);
        }
        bdrv_set_aio_context(bs, new_context);
        if (blk->public.throttle_state) {
            throttle_timers_attach_aio_context(&blk->public.throttle_timers,
                                               new_context);
        }
    }
}

@@ -1539,19 +1546,6 @@ void blk_update_root_state(BlockBackend *blk)
    blk->root_state.open_flags    = blk->root->bs->open_flags;
    blk->root_state.read_only     = blk->root->bs->read_only;
    blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;

    if (blk->root_state.throttle_group) {
        g_free(blk->root_state.throttle_group);
        throttle_group_unref(blk->root_state.throttle_state);
    }
    if (blk->public.throttle_state) {
        const char *name = throttle_group_get_name(blk);
        blk->root_state.throttle_group = g_strdup(name);
        blk->root_state.throttle_state = throttle_group_incref(name);
    } else {
        blk->root_state.throttle_group = NULL;
        blk->root_state.throttle_state = NULL;
    }
}

/*
@@ -1562,9 +1556,6 @@ void blk_update_root_state(BlockBackend *blk)
void blk_apply_root_state(BlockBackend *blk, BlockDriverState *bs)
{
    bs->detect_zeroes = blk->root_state.detect_zeroes;
    if (blk->root_state.throttle_group) {
        blk_io_limits_enable(blk, blk->root_state.throttle_group);
    }
}

/*
+9 −18
Original line number Diff line number Diff line
@@ -577,15 +577,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
        blk_rs->read_only     = !(bdrv_flags & BDRV_O_RDWR);
        blk_rs->detect_zeroes = detect_zeroes;

        if (throttle_enabled(&cfg)) {
            if (!throttling_group) {
                throttling_group = blk_name(blk);
            }
            blk_rs->throttle_group = g_strdup(throttling_group);
            blk_rs->throttle_state = throttle_group_incref(throttling_group);
            blk_rs->throttle_state->cfg = cfg;
        }

        QDECREF(bs_opts);
    } else {
        if (file && !*file) {
@@ -611,15 +602,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,

        bs->detect_zeroes = detect_zeroes;

        /* disk I/O throttling */
        if (throttle_enabled(&cfg)) {
            if (!throttling_group) {
                throttling_group = blk_name(blk);
            }
            blk_io_limits_enable(blk, throttling_group);
            blk_set_io_limits(blk, &cfg);
        }

        if (bdrv_key_required(bs)) {
            autostart = 0;
        }
@@ -633,6 +615,15 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
        }
    }

    /* disk I/O throttling */
    if (throttle_enabled(&cfg)) {
        if (!throttling_group) {
            throttling_group = blk_name(blk);
        }
        blk_io_limits_enable(blk, throttling_group);
        blk_set_io_limits(blk, &cfg);
    }

    blk_set_enable_write_cache(blk, !writethrough);
    blk_set_on_error(blk, on_read_error, on_write_error);

+0 −3
Original line number Diff line number Diff line
@@ -500,9 +500,6 @@ struct BlockBackendRootState {
    int open_flags;
    bool read_only;
    BlockdevDetectZeroesOptions detect_zeroes;

    char *throttle_group;
    ThrottleState *throttle_state;
};

static inline BlockDriverState *backing_bs(BlockDriverState *bs)