@ -1981,15 +1981,7 @@ void bdrv_make_anon(BlockDriverState *bs)
bs - > node_name [ 0 ] = ' \0 ' ;
}
static void bdrv_rebind ( BlockDriverState * bs )
{
if ( bs - > drv & & bs - > drv - > bdrv_rebind ) {
bs - > drv - > bdrv_rebind ( bs ) ;
}
}
/* Fields that need to stay with the top-level BDS, no matter whether the
* address of the top - level BDS stays the same or not . */
/* Fields that need to stay with the top-level BDS */
static void bdrv_move_feature_fields ( BlockDriverState * bs_dest ,
BlockDriverState * bs_src )
{
@ -2013,151 +2005,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
bs_dest - > dirty_bitmaps = bs_src - > dirty_bitmaps ;
}
/* Fields that only need to be swapped if the contents of BDSes is swapped
* rather than pointers being changed in the parents , and throttling fields
* because only bdrv_swap ( ) messes with internals of throttling . */
static void bdrv_move_reference_fields ( BlockDriverState * bs_dest ,
BlockDriverState * bs_src )
{
/* i/o throttled req */
bs_dest - > throttle_state = bs_src - > throttle_state ,
bs_dest - > io_limits_enabled = bs_src - > io_limits_enabled ;
bs_dest - > pending_reqs [ 0 ] = bs_src - > pending_reqs [ 0 ] ;
bs_dest - > pending_reqs [ 1 ] = bs_src - > pending_reqs [ 1 ] ;
bs_dest - > throttled_reqs [ 0 ] = bs_src - > throttled_reqs [ 0 ] ;
bs_dest - > throttled_reqs [ 1 ] = bs_src - > throttled_reqs [ 1 ] ;
memcpy ( & bs_dest - > round_robin ,
& bs_src - > round_robin ,
sizeof ( bs_dest - > round_robin ) ) ;
memcpy ( & bs_dest - > throttle_timers ,
& bs_src - > throttle_timers ,
sizeof ( ThrottleTimers ) ) ;
/* reference count */
bs_dest - > refcnt = bs_src - > refcnt ;
/* job */
bs_dest - > job = bs_src - > job ;
/* keep the same entry in bdrv_states */
bs_dest - > device_list = bs_src - > device_list ;
bs_dest - > blk = bs_src - > blk ;
bs_dest - > parents = bs_src - > parents ;
memcpy ( bs_dest - > op_blockers , bs_src - > op_blockers ,
sizeof ( bs_dest - > op_blockers ) ) ;
}
/*
* Swap bs contents for two image chains while they are live ,
* while keeping required fields on the BlockDriverState that is
* actually attached to a device .
*
* This will modify the BlockDriverState fields , and swap contents
* between bs_new and bs_old . Both bs_new and bs_old are modified .
*
* bs_new must not be attached to a BlockBackend .
*
* This function does not create any image files .
*/
void bdrv_swap ( BlockDriverState * bs_new , BlockDriverState * bs_old )
{
BlockDriverState tmp ;
BdrvChild * child ;
bdrv_drain ( bs_new ) ;
bdrv_drain ( bs_old ) ;
/* The code needs to swap the node_name but simply swapping node_list won't
* work so first remove the nodes from the graph list , do the swap then
* insert them back if needed .
*/
if ( bs_new - > node_name [ 0 ] ! = ' \0 ' ) {
QTAILQ_REMOVE ( & graph_bdrv_states , bs_new , node_list ) ;
}
if ( bs_old - > node_name [ 0 ] ! = ' \0 ' ) {
QTAILQ_REMOVE ( & graph_bdrv_states , bs_old , node_list ) ;
}
/* If the BlockDriverState is part of a throttling group acquire
* its lock since we ' re going to mess with the protected fields .
* Otherwise there ' s no need to worry since no one else can touch
* them . */
if ( bs_old - > throttle_state ) {
throttle_group_lock ( bs_old ) ;
}
/* bs_new must be unattached and shouldn't have anything fancy enabled */
assert ( ! bs_new - > blk ) ;
assert ( QLIST_EMPTY ( & bs_new - > dirty_bitmaps ) ) ;
assert ( bs_new - > job = = NULL ) ;
assert ( bs_new - > io_limits_enabled = = false ) ;
assert ( bs_new - > throttle_state = = NULL ) ;
assert ( ! throttle_timers_are_initialized ( & bs_new - > throttle_timers ) ) ;
tmp = * bs_new ;
* bs_new = * bs_old ;
* bs_old = tmp ;
/* there are some fields that should not be swapped, move them back */
bdrv_move_feature_fields ( & tmp , bs_old ) ;
bdrv_move_feature_fields ( bs_old , bs_new ) ;
bdrv_move_feature_fields ( bs_new , & tmp ) ;
bdrv_move_reference_fields ( & tmp , bs_old ) ;
bdrv_move_reference_fields ( bs_old , bs_new ) ;
bdrv_move_reference_fields ( bs_new , & tmp ) ;
/* bs_new must remain unattached */
assert ( ! bs_new - > blk ) ;
/* Check a few fields that should remain attached to the device */
assert ( bs_new - > job = = NULL ) ;
assert ( bs_new - > io_limits_enabled = = false ) ;
assert ( bs_new - > throttle_state = = NULL ) ;
assert ( ! throttle_timers_are_initialized ( & bs_new - > throttle_timers ) ) ;
/* Release the ThrottleGroup lock */
if ( bs_old - > throttle_state ) {
throttle_group_unlock ( bs_old ) ;
}
/* insert the nodes back into the graph node list if needed */
if ( bs_new - > node_name [ 0 ] ! = ' \0 ' ) {
QTAILQ_INSERT_TAIL ( & graph_bdrv_states , bs_new , node_list ) ;
}
if ( bs_old - > node_name [ 0 ] ! = ' \0 ' ) {
QTAILQ_INSERT_TAIL ( & graph_bdrv_states , bs_old , node_list ) ;
}
/*
* Update lh_first . le_prev for non - empty lists .
*
* The head of the op blocker list doesn ' t change because it is moved back
* in bdrv_move_feature_fields ( ) .
*/
assert ( QLIST_EMPTY ( & bs_old - > tracked_requests ) ) ;
assert ( QLIST_EMPTY ( & bs_new - > tracked_requests ) ) ;
QLIST_FIX_HEAD_PTR ( & bs_new - > children , next ) ;
QLIST_FIX_HEAD_PTR ( & bs_old - > children , next ) ;
/* Update references in bs->opaque and children */
QLIST_FOREACH ( child , & bs_old - > children , next ) {
if ( child - > bs - > inherits_from = = bs_new ) {
child - > bs - > inherits_from = bs_old ;
}
}
QLIST_FOREACH ( child , & bs_new - > children , next ) {
if ( child - > bs - > inherits_from = = bs_old ) {
child - > bs - > inherits_from = bs_new ;
}
}
bdrv_rebind ( bs_new ) ;
bdrv_rebind ( bs_old ) ;
}
static void change_parent_backing_link ( BlockDriverState * from ,
BlockDriverState * to )
{