diff --git a/block.c b/block.c index 1dc14908ac..9922943793 100644 --- a/block.c +++ b/block.c @@ -49,7 +49,6 @@ #include "qemu/timer.h" #include "qemu/cutils.h" #include "qemu/id.h" -#include "qemu/transactions.h" #include "block/coroutines.h" #ifdef CONFIG_BSD @@ -1577,7 +1576,7 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, return ret; } - bdrv_refresh_limits(bs, &local_err); + bdrv_refresh_limits(bs, NULL, &local_err); if (local_err) { error_propagate(errp, local_err); return -EINVAL; @@ -3363,7 +3362,7 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, } out: - bdrv_refresh_limits(bs, NULL); + bdrv_refresh_limits(bs, NULL, NULL); return ret; } @@ -4847,7 +4846,7 @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state) bdrv_set_backing_hd(bs, reopen_state->new_backing_bs, &error_abort); } - bdrv_refresh_limits(bs, NULL); + bdrv_refresh_limits(bs, NULL, NULL); } /* @@ -5244,7 +5243,7 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, out: tran_finalize(tran, ret); - bdrv_refresh_limits(bs_top, NULL); + bdrv_refresh_limits(bs_top, NULL, NULL); return ret; } diff --git a/block/io.c b/block/io.c index ca2dca3007..35b6c56efc 100644 --- a/block/io.c +++ b/block/io.c @@ -133,13 +133,40 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src) dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov); } -void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) +typedef struct BdrvRefreshLimitsState { + BlockDriverState *bs; + BlockLimits old_bl; +} BdrvRefreshLimitsState; + +static void bdrv_refresh_limits_abort(void *opaque) +{ + BdrvRefreshLimitsState *s = opaque; + + s->bs->bl = s->old_bl; +} + +static TransactionActionDrv bdrv_refresh_limits_drv = { + .abort = bdrv_refresh_limits_abort, + .clean = g_free, +}; + +/* @tran is allowed to be NULL, in this case no rollback is possible. */ +void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp) { ERRP_GUARD(); BlockDriver *drv = bs->drv; BdrvChild *c; bool have_limits; + if (tran) { + BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1); + *s = (BdrvRefreshLimitsState) { + .bs = bs, + .old_bl = bs->bl, + }; + tran_add(tran, &bdrv_refresh_limits_drv, s); + } + memset(&bs->bl, 0, sizeof(bs->bl)); if (!drv) { @@ -156,7 +183,7 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) QLIST_FOREACH(c, &bs->children, next) { if (c->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED | BDRV_CHILD_COW)) { - bdrv_refresh_limits(c->bs, errp); + bdrv_refresh_limits(c->bs, tran, errp); if (*errp) { return; } diff --git a/include/block/block.h b/include/block/block.h index 85481a05c6..ad38259c91 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -9,6 +9,7 @@ #include "block/dirty-bitmap.h" #include "block/blockjob.h" #include "qemu/hbitmap.h" +#include "qemu/transactions.h" /* * generated_co_wrapper @@ -421,7 +422,7 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, BlockDriverState *in_bs, Error **errp); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); -void bdrv_refresh_limits(BlockDriverState *bs, Error **errp); +void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp); int bdrv_commit(BlockDriverState *bs); int bdrv_make_empty(BdrvChild *c, Error **errp); int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,