@ -151,34 +151,29 @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
}
/**
* Return a pointer to the child BDS pointer to which we can fall
* Return a pointer to child of given BDS to which we can fall
* back if the given BDS does not support snapshots .
* Return NULL if there is no BDS to ( safely ) fall back to .
*
* We need to return an indirect pointer because bdrv_snapshot_goto ( )
* has to modify the BdrvChild pointer .
*/
static BdrvChild * * bdrv_snapshot_fallback_ptr ( BlockDriverState * bs )
static BdrvChild * bdrv_snapshot_fallback_child ( BlockDriverState * bs )
{
BdrvChild * * fallback ;
BdrvChild * child = bdrv_primary_child ( bs ) ;
BdrvChild * fallback = bdrv_primary_child ( bs ) ;
BdrvChild * child ;
/* We allow fallback only to primary child */
if ( ! child ) {
if ( ! fallback ) {
return NULL ;
}
fallback = ( child = = bs - > file ? & bs - > file : & bs - > backing ) ;
assert ( * fallback = = child ) ;
/*
* Check that there are no other children that would need to be
* snapshotted . If there are , it is not safe to fall back to
* * fallback .
* fallback .
*/
QLIST_FOREACH ( child , & bs - > children , next ) {
if ( child - > role & ( BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
BDRV_CHILD_FILTERED ) & &
child ! = * fallback )
child ! = fallback )
{
return NULL ;
}
@ -189,8 +184,7 @@ static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
static BlockDriverState * bdrv_snapshot_fallback ( BlockDriverState * bs )
{
BdrvChild * * child_ptr = bdrv_snapshot_fallback_ptr ( bs ) ;
return child_ptr ? ( * child_ptr ) - > bs : NULL ;
return child_bs ( bdrv_snapshot_fallback_child ( bs ) ) ;
}
int bdrv_can_snapshot ( BlockDriverState * bs )
@ -237,7 +231,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
Error * * errp )
{
BlockDriver * drv = bs - > drv ;
BdrvChild * * fallback_ptr ;
BdrvChild * fallback ;
int ret , open_ret ;
GLOBAL_STATE_CODE ( ) ;
@ -260,13 +254,13 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
return ret ;
}
fallback_ptr = bdrv_snapshot_fallback_ptr ( bs ) ;
if ( fallback_ptr ) {
fallback = bdrv_snapshot_fallback_child ( bs ) ;
if ( fallback ) {
QDict * options ;
QDict * file_options ;
Error * local_err = NULL ;
BlockDriverState * fallback_bs = ( * fallback_ptr ) - > bs ;
char * subqdict_prefix = g_strdup_printf ( " %s. " , ( * fallback_ptr ) - > name ) ;
BlockDriverState * fallback_bs = fallback - > bs ;
char * subqdict_prefix = g_strdup_printf ( " %s. " , fallback - > name ) ;
options = qdict_clone_shallow ( bs - > options ) ;
@ -277,8 +271,8 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
qobject_unref ( file_options ) ;
g_free ( subqdict_prefix ) ;
/* Force .bdrv_open() below to re-attach fallback_bs on * fallback_ptr */
qdict_put_str ( options , ( * fallback_ptr ) - > name ,
/* Force .bdrv_open() below to re-attach fallback_bs on fallback */
qdict_put_str ( options , fallback - > name ,
bdrv_get_node_name ( fallback_bs ) ) ;
/* Now close bs, apply the snapshot on fallback_bs, and re-open bs */
@ -287,7 +281,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
}
/* .bdrv_open() will re-attach it */
bdrv_unref_child ( bs , * fallback_ptr ) ;
bdrv_unref_child ( bs , fallback ) ;
ret = bdrv_snapshot_goto ( fallback_bs , snapshot_id , errp ) ;
open_ret = drv - > bdrv_open ( bs , options , bs - > open_flags , & local_err ) ;