Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
block: Call .bdrv_co_create(_opts) unlocked
These are functions that modify the graph, so they must be able to take
a writer lock. This is impossible if they already hold the reader lock.
If they need a reader lock for some of their operations, they should
take it internally.

Many of them go through blk_*(), which will always take the lock itself.
Direct calls of bdrv_*() need to take the reader lock. Note that while
locking for bdrv_co_*() calls is checked by TSA, this is not the case
for the mixed_coroutine_fns bdrv_*(). Holding the lock is still required
when they are called from coroutine context like here!

This effectively reverts 4ec8df0, but adds some internal locking
instead.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230510203601.418015-2-kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
Kevin Wolf committed May 19, 2023
1 parent 41f8b63 commit 4db7ba3
Show file tree
Hide file tree
Showing 14 changed files with 78 additions and 70 deletions.
1 change: 0 additions & 1 deletion block.c
Expand Up @@ -533,7 +533,6 @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
int ret;
GLOBAL_STATE_CODE();
ERRP_GUARD();
assert_bdrv_graph_readable();

if (!drv->bdrv_co_create_opts) {
error_setg(errp, "Driver '%s' does not support image creation",
Expand Down
1 change: 0 additions & 1 deletion block/create.c
Expand Up @@ -43,7 +43,6 @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
int ret;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD();

job_progress_set_remaining(&s->common, 1);
ret = s->drv->bdrv_co_create(s->opts, errp);
Expand Down
25 changes: 12 additions & 13 deletions block/crypto.c
Expand Up @@ -99,12 +99,10 @@ struct BlockCryptoCreateData {
};


static int block_crypto_create_write_func(QCryptoBlock *block,
size_t offset,
const uint8_t *buf,
size_t buflen,
void *opaque,
Error **errp)
static int coroutine_fn GRAPH_UNLOCKED
block_crypto_create_write_func(QCryptoBlock *block, size_t offset,
const uint8_t *buf, size_t buflen, void *opaque,
Error **errp)
{
struct BlockCryptoCreateData *data = opaque;
ssize_t ret;
Expand All @@ -117,10 +115,9 @@ static int block_crypto_create_write_func(QCryptoBlock *block,
return 0;
}

static int block_crypto_create_init_func(QCryptoBlock *block,
size_t headerlen,
void *opaque,
Error **errp)
static int coroutine_fn GRAPH_UNLOCKED
block_crypto_create_init_func(QCryptoBlock *block, size_t headerlen,
void *opaque, Error **errp)
{
struct BlockCryptoCreateData *data = opaque;
Error *local_error = NULL;
Expand Down Expand Up @@ -314,7 +311,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
}


static int coroutine_fn
static int coroutine_fn GRAPH_UNLOCKED
block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
QCryptoBlockCreateOptions *opts,
PreallocMode prealloc, Error **errp)
Expand Down Expand Up @@ -627,7 +624,7 @@ static int block_crypto_open_luks(BlockDriverState *bs,
bs, options, flags, errp);
}

static int coroutine_fn
static int coroutine_fn GRAPH_UNLOCKED
block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
{
BlockdevCreateOptionsLUKS *luks_opts;
Expand Down Expand Up @@ -665,7 +662,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
return ret;
}

static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
Expand Down Expand Up @@ -727,7 +724,9 @@ block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
* beforehand, it has been truncated and corrupted in the process.
*/
if (ret) {
bdrv_graph_co_rdlock();
bdrv_co_delete_file_noerr(bs);
bdrv_graph_co_rdunlock();
}

bdrv_co_unref(bs);
Expand Down
6 changes: 3 additions & 3 deletions block/parallels.c
Expand Up @@ -522,8 +522,8 @@ parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
}


static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
Error **errp)
static int coroutine_fn GRAPH_UNLOCKED
parallels_co_create(BlockdevCreateOptions* opts, Error **errp)
{
BlockdevCreateOptionsParallels *parallels_opts;
BlockDriverState *bs;
Expand Down Expand Up @@ -622,7 +622,7 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
goto out;
}

static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
parallels_co_create_opts(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
Expand Down
6 changes: 3 additions & 3 deletions block/qcow.c
Expand Up @@ -800,8 +800,8 @@ static void qcow_close(BlockDriverState *bs)
error_free(s->migration_blocker);
}

static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
Error **errp)
static int coroutine_fn GRAPH_UNLOCKED
qcow_co_create(BlockdevCreateOptions *opts, Error **errp)
{
BlockdevCreateOptionsQcow *qcow_opts;
int header_size, backing_filename_len, l1_size, shift, i;
Expand Down Expand Up @@ -921,7 +921,7 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
return ret;
}

static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
qcow_co_create_opts(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
Expand Down
37 changes: 24 additions & 13 deletions block/qcow2.c
Expand Up @@ -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,
void *opaque, Error **errp)
static int coroutine_fn GRAPH_RDLOCK
qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen, void *opaque,
Error **errp)
{
BlockDriverState *bs = opaque;
BDRVQcow2State *s = bs->opaque;
Expand All @@ -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;
assert(qcow2_pre_write_overlap_check(bs, 0, ret, clusterlen, false) == 0);
ret = bdrv_pwrite_zeroes(bs->file,
ret,
clusterlen, 0);
ret = bdrv_co_pwrite_zeroes(bs->file, ret, clusterlen, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not zero fill encryption header");
return -1;
Expand All @@ -156,9 +155,11 @@ static int qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
}


static int qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
const uint8_t *buf, size_t buflen,
void *opaque, Error **errp)
/* 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,
void *opaque, Error **errp)
{
BlockDriverState *bs = opaque;
BDRVQcow2State *s = bs->opaque;
Expand Down Expand Up @@ -3137,9 +3138,10 @@ static int qcow2_change_backing_file(BlockDriverState *bs,
return qcow2_update_header(bs);
}

static int qcow2_set_up_encryption(BlockDriverState *bs,
QCryptoBlockCreateOptions *cryptoopts,
Error **errp)
static int coroutine_fn GRAPH_RDLOCK
qcow2_set_up_encryption(BlockDriverState *bs,
QCryptoBlockCreateOptions *cryptoopts,
Error **errp)
{
BDRVQcow2State *s = bs->opaque;
QCryptoBlock *crypto = NULL;
Expand Down Expand Up @@ -3426,7 +3428,7 @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
return refcount_bits;
}

static int coroutine_fn
static int coroutine_fn GRAPH_UNLOCKED
qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
{
BlockdevCreateOptionsQcow2 *qcow2_opts;
Expand Down Expand Up @@ -3724,8 +3726,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
goto out;
}

bdrv_graph_co_rdlock();
ret = qcow2_alloc_clusters(blk_bs(blk), 3 * cluster_size);
if (ret < 0) {
bdrv_graph_co_rdunlock();
error_setg_errno(errp, -ret, "Could not allocate clusters for qcow2 "
"header and refcount table");
goto out;
Expand All @@ -3743,6 +3747,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)

/* Create a full header (including things like feature table) */
ret = qcow2_update_header(blk_bs(blk));
bdrv_graph_co_rdunlock();

if (ret < 0) {
error_setg_errno(errp, -ret, "Could not update qcow2 header");
goto out;
Expand Down Expand Up @@ -3776,7 +3782,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)

/* Want encryption? There you go. */
if (qcow2_opts->encrypt) {
bdrv_graph_co_rdlock();
ret = qcow2_set_up_encryption(blk_bs(blk), qcow2_opts->encrypt, errp);
bdrv_graph_co_rdunlock();

if (ret < 0) {
goto out;
}
Expand Down Expand Up @@ -3813,7 +3822,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
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,
Error **errp)
{
Expand Down Expand Up @@ -3933,8 +3942,10 @@ qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts,
ret = qcow2_co_create(create_options, errp);
finish:
if (ret < 0) {
bdrv_graph_co_rdlock();
bdrv_co_delete_file_noerr(bs);
bdrv_co_delete_file_noerr(data_bs);
bdrv_graph_co_rdunlock();
} else {
ret = 0;
}
Expand Down
6 changes: 3 additions & 3 deletions block/qed.c
Expand Up @@ -630,8 +630,8 @@ static void bdrv_qed_close(BlockDriverState *bs)
qemu_vfree(s->l1_table);
}

static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
Error **errp)
static int coroutine_fn GRAPH_UNLOCKED
bdrv_qed_co_create(BlockdevCreateOptions *opts, Error **errp)
{
BlockdevCreateOptionsQed *qed_opts;
BlockBackend *blk = NULL;
Expand Down Expand Up @@ -751,7 +751,7 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
return ret;
}

static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
Expand Down
2 changes: 1 addition & 1 deletion block/raw-format.c
Expand Up @@ -457,7 +457,7 @@ static int raw_has_zero_init(BlockDriverState *bs)
return bdrv_has_zero_init(bs->file->bs);
}

static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
raw_co_create_opts(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
Expand Down
11 changes: 6 additions & 5 deletions block/vdi.c
Expand Up @@ -734,8 +734,9 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
return ret;
}

static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
size_t block_size, Error **errp)
static int coroutine_fn GRAPH_UNLOCKED
vdi_co_do_create(BlockdevCreateOptions *create_options, size_t block_size,
Error **errp)
{
BlockdevCreateOptionsVdi *vdi_opts;
int ret = 0;
Expand Down Expand Up @@ -892,13 +893,13 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
return ret;
}

static int coroutine_fn vdi_co_create(BlockdevCreateOptions *create_options,
Error **errp)
static int coroutine_fn GRAPH_UNLOCKED
vdi_co_create(BlockdevCreateOptions *create_options, Error **errp)
{
return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp);
}

static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
vdi_co_create_opts(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
Expand Down
8 changes: 5 additions & 3 deletions block/vhdx.c
Expand Up @@ -1506,7 +1506,7 @@ vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
* There are 2 headers, and the highest sequence number will represent
* the active header
*/
static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
vhdx_create_new_headers(BlockBackend *blk, uint64_t image_size,
uint32_t log_size)
{
Expand All @@ -1515,6 +1515,8 @@ vhdx_create_new_headers(BlockBackend *blk, uint64_t image_size,
int ret = 0;
VHDXHeader *hdr = NULL;

GRAPH_RDLOCK_GUARD();

hdr = g_new0(VHDXHeader, 1);

hdr->signature = VHDX_HEADER_SIGNATURE;
Expand Down Expand Up @@ -1898,7 +1900,7 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
* .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
* 1MB
*/
static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
vhdx_co_create(BlockdevCreateOptions *opts, Error **errp)
{
BlockdevCreateOptionsVhdx *vhdx_opts;
Expand Down Expand Up @@ -2060,7 +2062,7 @@ vhdx_co_create(BlockdevCreateOptions *opts, Error **errp)
return ret;
}

static int coroutine_fn GRAPH_RDLOCK
static int coroutine_fn GRAPH_UNLOCKED
vhdx_co_create_opts(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
Expand Down

0 comments on commit 4db7ba3

Please sign in to comment.