@ -118,8 +118,9 @@ static int qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
}
}
static int qcow2_crypto_hdr_init_func ( QCryptoBlock * block , size_t headerlen ,
static int coroutine_fn GRAPH_RDLOCK
void * opaque , Error * * errp )
qcow2_crypto_hdr_init_func ( QCryptoBlock * block , size_t headerlen , void * opaque ,
Error * * errp )
{
{
BlockDriverState * bs = opaque ;
BlockDriverState * bs = opaque ;
BDRVQcow2State * s = bs - > opaque ;
BDRVQcow2State * s = bs - > opaque ;
@ -144,9 +145,7 @@ static int qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
*/
*/
clusterlen = size_to_clusters ( s , headerlen ) * s - > cluster_size ;
clusterlen = size_to_clusters ( s , headerlen ) * s - > cluster_size ;
assert ( qcow2_pre_write_overlap_check ( bs , 0 , ret , clusterlen , false ) = = 0 ) ;
assert ( qcow2_pre_write_overlap_check ( bs , 0 , ret , clusterlen , false ) = = 0 ) ;
ret = bdrv_pwrite_zeroes ( bs - > file ,
ret = bdrv_co_pwrite_zeroes ( bs - > file , ret , clusterlen , 0 ) ;
ret ,
clusterlen , 0 ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
error_setg_errno ( errp , - ret , " Could not zero fill encryption header " ) ;
error_setg_errno ( errp , - ret , " Could not zero fill encryption header " ) ;
return - 1 ;
return - 1 ;
@ -156,7 +155,9 @@ static int qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
}
}
static int qcow2_crypto_hdr_write_func ( QCryptoBlock * block , size_t offset ,
/* The graph lock must be held when called in coroutine context */
static int coroutine_mixed_fn
qcow2_crypto_hdr_write_func ( QCryptoBlock * block , size_t offset ,
const uint8_t * buf , size_t buflen ,
const uint8_t * buf , size_t buflen ,
void * opaque , Error * * errp )
void * opaque , Error * * errp )
{
{
@ -3137,7 +3138,8 @@ static int qcow2_change_backing_file(BlockDriverState *bs,
return qcow2_update_header ( bs ) ;
return qcow2_update_header ( bs ) ;
}
}
static int qcow2_set_up_encryption ( BlockDriverState * bs ,
static int coroutine_fn GRAPH_RDLOCK
qcow2_set_up_encryption ( BlockDriverState * bs ,
QCryptoBlockCreateOptions * cryptoopts ,
QCryptoBlockCreateOptions * cryptoopts ,
Error * * errp )
Error * * errp )
{
{
@ -3426,7 +3428,7 @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
return refcount_bits ;
return refcount_bits ;
}
}
static int coroutine_fn
static int coroutine_fn GRAPH_UNLOCKED
qcow2_co_create ( BlockdevCreateOptions * create_options , Error * * errp )
qcow2_co_create ( BlockdevCreateOptions * create_options , Error * * errp )
{
{
BlockdevCreateOptionsQcow2 * qcow2_opts ;
BlockdevCreateOptionsQcow2 * qcow2_opts ;
@ -3724,8 +3726,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
goto out ;
goto out ;
}
}
bdrv_graph_co_rdlock ( ) ;
ret = qcow2_alloc_clusters ( blk_bs ( blk ) , 3 * cluster_size ) ;
ret = qcow2_alloc_clusters ( blk_bs ( blk ) , 3 * cluster_size ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
bdrv_graph_co_rdunlock ( ) ;
error_setg_errno ( errp , - ret , " Could not allocate clusters for qcow2 "
error_setg_errno ( errp , - ret , " Could not allocate clusters for qcow2 "
" header and refcount table " ) ;
" header and refcount table " ) ;
goto out ;
goto out ;
@ -3743,6 +3747,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
/* Create a full header (including things like feature table) */
/* Create a full header (including things like feature table) */
ret = qcow2_update_header ( blk_bs ( blk ) ) ;
ret = qcow2_update_header ( blk_bs ( blk ) ) ;
bdrv_graph_co_rdunlock ( ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
error_setg_errno ( errp , - ret , " Could not update qcow2 header " ) ;
error_setg_errno ( errp , - ret , " Could not update qcow2 header " ) ;
goto out ;
goto out ;
@ -3776,7 +3782,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
/* Want encryption? There you go. */
/* Want encryption? There you go. */
if ( qcow2_opts - > encrypt ) {
if ( qcow2_opts - > encrypt ) {
bdrv_graph_co_rdlock ( ) ;
ret = qcow2_set_up_encryption ( blk_bs ( blk ) , qcow2_opts - > encrypt , errp ) ;
ret = qcow2_set_up_encryption ( blk_bs ( blk ) , qcow2_opts - > encrypt , errp ) ;
bdrv_graph_co_rdunlock ( ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
goto out ;
goto out ;
}
}
@ -3813,7 +3822,7 @@ out:
return ret ;
return ret ;
}
}
static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
qcow2_co_create_opts ( BlockDriver * drv , const char * filename , QemuOpts * opts ,
qcow2_co_create_opts ( BlockDriver * drv , const char * filename , QemuOpts * opts ,
Error * * errp )
Error * * errp )
{
{
@ -3933,8 +3942,10 @@ qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts,
ret = qcow2_co_create ( create_options , errp ) ;
ret = qcow2_co_create ( create_options , errp ) ;
finish :
finish :
if ( ret < 0 ) {
if ( ret < 0 ) {
bdrv_graph_co_rdlock ( ) ;
bdrv_co_delete_file_noerr ( bs ) ;
bdrv_co_delete_file_noerr ( bs ) ;
bdrv_co_delete_file_noerr ( data_bs ) ;
bdrv_co_delete_file_noerr ( data_bs ) ;
bdrv_graph_co_rdunlock ( ) ;
} else {
} else {
ret = 0 ;
ret = 0 ;
}
}