@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
BlockDriverState * parent ,
BlockDriverState * parent ,
const BdrvChildClass * child_class ,
const BdrvChildClass * child_class ,
BdrvChildRole child_role ,
BdrvChildRole child_role ,
bool parse_filename ,
Error * * errp ) ;
Error * * errp ) ;
static bool bdrv_recurse_has_child ( BlockDriverState * bs ,
static bool bdrv_recurse_has_child ( BlockDriverState * bs ,
@ -2055,7 +2056,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
* block driver has been specified explicitly .
* block driver has been specified explicitly .
*/
*/
static int bdrv_fill_options ( QDict * * options , const char * filename ,
static int bdrv_fill_options ( QDict * * options , const char * filename ,
int * flags , Error * * errp )
int * flags , bool allow_parse_filename ,
Error * * errp )
{
{
const char * drvname ;
const char * drvname ;
bool protocol = * flags & BDRV_O_PROTOCOL ;
bool protocol = * flags & BDRV_O_PROTOCOL ;
@ -2097,7 +2099,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
if ( protocol & & filename ) {
if ( protocol & & filename ) {
if ( ! qdict_haskey ( * options , " filename " ) ) {
if ( ! qdict_haskey ( * options , " filename " ) ) {
qdict_put_str ( * options , " filename " , filename ) ;
qdict_put_str ( * options , " filename " , filename ) ;
parse_filename = tru e;
parse_filename = allow_parse_filenam e;
} else {
} else {
error_setg ( errp , " Can't specify 'file' and 'filename' options at "
error_setg ( errp , " Can't specify 'file' and 'filename' options at "
" the same time " ) ;
" the same time " ) ;
@ -3660,7 +3662,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
}
}
backing_hd = bdrv_open_inherit ( backing_filename , reference , options , 0 , bs ,
backing_hd = bdrv_open_inherit ( backing_filename , reference , options , 0 , bs ,
& child_of_bds , bdrv_backing_role ( bs ) , errp ) ;
& child_of_bds , bdrv_backing_role ( bs ) , true ,
errp ) ;
if ( ! backing_hd ) {
if ( ! backing_hd ) {
bs - > open_flags | = BDRV_O_NO_BACKING ;
bs - > open_flags | = BDRV_O_NO_BACKING ;
error_prepend ( errp , " Could not open backing file: " ) ;
error_prepend ( errp , " Could not open backing file: " ) ;
@ -3694,7 +3697,8 @@ free_exit:
static BlockDriverState *
static BlockDriverState *
bdrv_open_child_bs ( const char * filename , QDict * options , const char * bdref_key ,
bdrv_open_child_bs ( const char * filename , QDict * options , const char * bdref_key ,
BlockDriverState * parent , const BdrvChildClass * child_class ,
BlockDriverState * parent , const BdrvChildClass * child_class ,
BdrvChildRole child_role , bool allow_none , Error * * errp )
BdrvChildRole child_role , bool allow_none ,
bool parse_filename , Error * * errp )
{
{
BlockDriverState * bs = NULL ;
BlockDriverState * bs = NULL ;
QDict * image_options ;
QDict * image_options ;
@ -3725,7 +3729,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
}
}
bs = bdrv_open_inherit ( filename , reference , image_options , 0 ,
bs = bdrv_open_inherit ( filename , reference , image_options , 0 ,
parent , child_class , child_role , errp ) ;
parent , child_class , child_role , parse_filename ,
errp ) ;
if ( ! bs ) {
if ( ! bs ) {
goto done ;
goto done ;
}
}
@ -3735,6 +3740,33 @@ done:
return bs ;
return bs ;
}
}
static BdrvChild * bdrv_open_child_common ( const char * filename ,
QDict * options , const char * bdref_key ,
BlockDriverState * parent ,
const BdrvChildClass * child_class ,
BdrvChildRole child_role ,
bool allow_none , bool parse_filename ,
Error * * errp )
{
BlockDriverState * bs ;
BdrvChild * child ;
GLOBAL_STATE_CODE ( ) ;
bs = bdrv_open_child_bs ( filename , options , bdref_key , parent , child_class ,
child_role , allow_none , parse_filename , errp ) ;
if ( bs = = NULL ) {
return NULL ;
}
bdrv_graph_wrlock ( ) ;
child = bdrv_attach_child ( parent , bs , bdref_key , child_class , child_role ,
errp ) ;
bdrv_graph_wrunlock ( ) ;
return child ;
}
/*
/*
* Opens a disk image whose options are given as BlockdevRef in another block
* Opens a disk image whose options are given as BlockdevRef in another block
* device ' s options .
* device ' s options .
@ -3758,27 +3790,15 @@ BdrvChild *bdrv_open_child(const char *filename,
BdrvChildRole child_role ,
BdrvChildRole child_role ,
bool allow_none , Error * * errp )
bool allow_none , Error * * errp )
{
{
BlockDriverState * bs ;
return bdrv_open_child_common ( filename , options , bdref_key , parent ,
BdrvChild * child ;
child_class , child_role , allow_none , false ,
errp ) ;
GLOBAL_STATE_CODE ( ) ;
bs = bdrv_open_child_bs ( filename , options , bdref_key , parent , child_class ,
child_role , allow_none , errp ) ;
if ( bs = = NULL ) {
return NULL ;
}
bdrv_graph_wrlock ( ) ;
child = bdrv_attach_child ( parent , bs , bdref_key , child_class , child_role ,
errp ) ;
bdrv_graph_wrunlock ( ) ;
return child ;
}
}
/*
/*
* Wrapper on bdrv_open_child ( ) for most popular case : open primary child of bs .
* This does mostly the same as bdrv_open_child ( ) , but for opening the primary
* child of a node . A notable difference from bdrv_open_child ( ) is that it
* enables filename parsing for protocol names ( including json : ) .
*
*
* @ parent can move to a different AioContext in this function .
* @ parent can move to a different AioContext in this function .
*/
*/
@ -3793,8 +3813,8 @@ int bdrv_open_file_child(const char *filename,
role = parent - > drv - > is_filter ?
role = parent - > drv - > is_filter ?
( BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY ) : BDRV_CHILD_IMAGE ;
( BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY ) : BDRV_CHILD_IMAGE ;
if ( ! bdrv_open_child ( filename , options , bdref_key , parent ,
if ( ! bdrv_open_child_common ( filename , options , bdref_key , parent ,
& child_of_bds , role , false , errp ) )
& child_of_bds , role , false , tru e , errp ) )
{
{
return - EINVAL ;
return - EINVAL ;
}
}
@ -3839,7 +3859,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
}
}
bs = bdrv_open_inherit ( NULL , reference , qdict , 0 , NULL , NULL , 0 , errp ) ;
bs = bdrv_open_inherit ( NULL , reference , qdict , 0 , NULL , NULL , 0 , false ,
errp ) ;
obj = NULL ;
obj = NULL ;
qobject_unref ( obj ) ;
qobject_unref ( obj ) ;
visit_free ( v ) ;
visit_free ( v ) ;
@ -3929,7 +3950,7 @@ static BlockDriverState * no_coroutine_fn
bdrv_open_inherit ( const char * filename , const char * reference , QDict * options ,
bdrv_open_inherit ( const char * filename , const char * reference , QDict * options ,
int flags , BlockDriverState * parent ,
int flags , BlockDriverState * parent ,
const BdrvChildClass * child_class , BdrvChildRole child_role ,
const BdrvChildClass * child_class , BdrvChildRole child_role ,
Error * * errp )
bool parse_filename , Error * * errp )
{
{
int ret ;
int ret ;
BlockBackend * file = NULL ;
BlockBackend * file = NULL ;
@ -3977,9 +3998,11 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
}
}
/* json: syntax counts as explicit options, as if in the QDict */
/* json: syntax counts as explicit options, as if in the QDict */
parse_json_protocol ( options , & filename , & local_err ) ;
if ( parse_filename ) {
if ( local_err ) {
parse_json_protocol ( options , & filename , & local_err ) ;
goto fail ;
if ( local_err ) {
goto fail ;
}
}
}
bs - > explicit_options = qdict_clone_shallow ( options ) ;
bs - > explicit_options = qdict_clone_shallow ( options ) ;
@ -4004,7 +4027,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
parent - > open_flags , parent - > options ) ;
parent - > open_flags , parent - > options ) ;
}
}
ret = bdrv_fill_options ( & options , filename , & flags , & local_err ) ;
ret = bdrv_fill_options ( & options , filename , & flags , parse_filename ,
& local_err ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
goto fail ;
goto fail ;
}
}
@ -4073,7 +4097,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
file_bs = bdrv_open_child_bs ( filename , options , " file " , bs ,
file_bs = bdrv_open_child_bs ( filename , options , " file " , bs ,
& child_of_bds , BDRV_CHILD_IMAGE ,
& child_of_bds , BDRV_CHILD_IMAGE ,
true , & local_err ) ;
true , true , & local_err ) ;
if ( local_err ) {
if ( local_err ) {
goto fail ;
goto fail ;
}
}
@ -4222,7 +4246,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
GLOBAL_STATE_CODE ( ) ;
GLOBAL_STATE_CODE ( ) ;
return bdrv_open_inherit ( filename , reference , options , flags , NULL ,
return bdrv_open_inherit ( filename , reference , options , flags , NULL ,
NULL , 0 , errp ) ;
NULL , 0 , true , errp ) ;
}
}
/* Return true if the NULL-terminated @list contains @str */
/* Return true if the NULL-terminated @list contains @str */