@ -1250,20 +1250,6 @@ static bool bdrv_child_cb_change_aio_ctx(BdrvChild *child, AioContext *ctx,
return bdrv_change_aio_context ( bs , ctx , visited , tran , errp ) ;
}
static bool bdrv_child_cb_can_set_aio_ctx ( BdrvChild * child , AioContext * ctx ,
GSList * * ignore , Error * * errp )
{
BlockDriverState * bs = child - > opaque ;
return bdrv_can_set_aio_context ( bs , ctx , ignore , errp ) ;
}
static void bdrv_child_cb_set_aio_ctx ( BdrvChild * child , AioContext * ctx ,
GSList * * ignore )
{
BlockDriverState * bs = child - > opaque ;
return bdrv_set_aio_context_ignore ( bs , ctx , ignore ) ;
}
/*
* Returns the options and flags that a temporary snapshot should get , based on
* the originally requested flags ( the originally requested image will have
@ -1540,8 +1526,6 @@ const BdrvChildClass child_of_bds = {
. attach = bdrv_child_cb_attach ,
. detach = bdrv_child_cb_detach ,
. inactivate = bdrv_child_cb_inactivate ,
. can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx ,
. set_aio_ctx = bdrv_child_cb_set_aio_ctx ,
. change_aio_ctx = bdrv_child_cb_change_aio_ctx ,
. update_filename = bdrv_child_cb_update_filename ,
. get_parent_aio_context = child_of_bds_get_parent_aio_context ,
@ -7205,125 +7189,6 @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
bs - > walking_aio_notifiers = false ;
}
/*
* Changes the AioContext used for fd handlers , timers , and BHs by this
* BlockDriverState and all its children and parents .
*
* Must be called from the main AioContext .
*
* The caller must own the AioContext lock for the old AioContext of bs , but it
* must not own the AioContext lock for new_context ( unless new_context is the
* same as the current context of bs ) .
*
* @ ignore will accumulate all visited BdrvChild objects . The caller is
* responsible for freeing the list afterwards .
*/
void bdrv_set_aio_context_ignore ( BlockDriverState * bs ,
AioContext * new_context , GSList * * ignore )
{
AioContext * old_context = bdrv_get_aio_context ( bs ) ;
GSList * children_to_process = NULL ;
GSList * parents_to_process = NULL ;
GSList * entry ;
BdrvChild * child , * parent ;
g_assert ( qemu_get_current_aio_context ( ) = = qemu_get_aio_context ( ) ) ;
GLOBAL_STATE_CODE ( ) ;
if ( old_context = = new_context ) {
return ;
}
bdrv_drained_begin ( bs ) ;
QLIST_FOREACH ( child , & bs - > children , next ) {
if ( g_slist_find ( * ignore , child ) ) {
continue ;
}
* ignore = g_slist_prepend ( * ignore , child ) ;
children_to_process = g_slist_prepend ( children_to_process , child ) ;
}
QLIST_FOREACH ( parent , & bs - > parents , next_parent ) {
if ( g_slist_find ( * ignore , parent ) ) {
continue ;
}
* ignore = g_slist_prepend ( * ignore , parent ) ;
parents_to_process = g_slist_prepend ( parents_to_process , parent ) ;
}
for ( entry = children_to_process ;
entry ! = NULL ;
entry = g_slist_next ( entry ) ) {
child = entry - > data ;
bdrv_set_aio_context_ignore ( child - > bs , new_context , ignore ) ;
}
g_slist_free ( children_to_process ) ;
for ( entry = parents_to_process ;
entry ! = NULL ;
entry = g_slist_next ( entry ) ) {
parent = entry - > data ;
assert ( parent - > klass - > set_aio_ctx ) ;
parent - > klass - > set_aio_ctx ( parent , new_context , ignore ) ;
}
g_slist_free ( parents_to_process ) ;
bdrv_detach_aio_context ( bs ) ;
/* Acquire the new context, if necessary */
if ( qemu_get_aio_context ( ) ! = new_context ) {
aio_context_acquire ( new_context ) ;
}
bdrv_attach_aio_context ( bs , new_context ) ;
/*
* If this function was recursively called from
* bdrv_set_aio_context_ignore ( ) , there may be nodes in the
* subtree that have not yet been moved to the new AioContext .
* Release the old one so bdrv_drained_end ( ) can poll them .
*/
if ( qemu_get_aio_context ( ) ! = old_context ) {
aio_context_release ( old_context ) ;
}
bdrv_drained_end ( bs ) ;
if ( qemu_get_aio_context ( ) ! = old_context ) {
aio_context_acquire ( old_context ) ;
}
if ( qemu_get_aio_context ( ) ! = new_context ) {
aio_context_release ( new_context ) ;
}
}
static bool bdrv_parent_can_set_aio_context ( BdrvChild * c , AioContext * ctx ,
GSList * * ignore , Error * * errp )
{
GLOBAL_STATE_CODE ( ) ;
if ( g_slist_find ( * ignore , c ) ) {
return true ;
}
* ignore = g_slist_prepend ( * ignore , c ) ;
/*
* A BdrvChildClass that doesn ' t handle AioContext changes cannot
* tolerate any AioContext changes
*/
if ( ! c - > klass - > can_set_aio_ctx ) {
char * user = bdrv_child_user_desc ( c ) ;
error_setg ( errp , " Changing iothreads is not supported by %s " , user ) ;
g_free ( user ) ;
return false ;
}
if ( ! c - > klass - > can_set_aio_ctx ( c , ctx , ignore , errp ) ) {
assert ( ! errp | | * errp ) ;
return false ;
}
return true ;
}
typedef struct BdrvStateSetAioContext {
AioContext * new_ctx ;
BlockDriverState * bs ;
@ -7357,17 +7222,6 @@ static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
return true ;
}
bool bdrv_child_can_set_aio_context ( BdrvChild * c , AioContext * ctx ,
GSList * * ignore , Error * * errp )
{
GLOBAL_STATE_CODE ( ) ;
if ( g_slist_find ( * ignore , c ) ) {
return true ;
}
* ignore = g_slist_prepend ( * ignore , c ) ;
return bdrv_can_set_aio_context ( c - > bs , ctx , ignore , errp ) ;
}
bool bdrv_child_change_aio_context ( BdrvChild * c , AioContext * ctx ,
GHashTable * visited , Transaction * tran ,
Error * * errp )
@ -7380,33 +7234,6 @@ bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
return bdrv_change_aio_context ( c - > bs , ctx , visited , tran , errp ) ;
}
/* @ignore will accumulate all visited BdrvChild object. The caller is
* responsible for freeing the list afterwards . */
bool bdrv_can_set_aio_context ( BlockDriverState * bs , AioContext * ctx ,
GSList * * ignore , Error * * errp )
{
BdrvChild * c ;
if ( bdrv_get_aio_context ( bs ) = = ctx ) {
return true ;
}
GLOBAL_STATE_CODE ( ) ;
QLIST_FOREACH ( c , & bs - > parents , next_parent ) {
if ( ! bdrv_parent_can_set_aio_context ( c , ctx , ignore , errp ) ) {
return false ;
}
}
QLIST_FOREACH ( c , & bs - > children , next ) {
if ( ! bdrv_child_can_set_aio_context ( c , ctx , ignore , errp ) ) {
return false ;
}
}
return true ;
}
static void bdrv_set_aio_context_clean ( void * opaque )
{
BdrvStateSetAioContext * state = ( BdrvStateSetAioContext * ) opaque ;
@ -7499,29 +7326,6 @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
return true ;
}
int bdrv_child_try_set_aio_context ( BlockDriverState * bs , AioContext * ctx ,
BdrvChild * ignore_child , Error * * errp )
{
GSList * ignore ;
bool ret ;
GLOBAL_STATE_CODE ( ) ;
ignore = ignore_child ? g_slist_prepend ( NULL , ignore_child ) : NULL ;
ret = bdrv_can_set_aio_context ( bs , ctx , & ignore , errp ) ;
g_slist_free ( ignore ) ;
if ( ! ret ) {
return - EPERM ;
}
ignore = ignore_child ? g_slist_prepend ( NULL , ignore_child ) : NULL ;
bdrv_set_aio_context_ignore ( bs , ctx , & ignore ) ;
g_slist_free ( ignore ) ;
return 0 ;
}
/*
* Change bs ' s and recursively all of its parents ' and children ' s AioContext
* to the given new context , returning an error if that isn ' t possible .