Skip to content

Commit

Permalink
block: Protect bs->file with graph_lock
Browse files Browse the repository at this point in the history
Almost all functions that access bs->file already take the graph
lock now. Add locking to the remaining users and finally annotate the
struct field itself as protected by the graph lock.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20231027155333.420094-25-kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
kevmw committed Nov 8, 2023
1 parent a4b740d commit 1f051dc
Show file tree
Hide file tree
Showing 15 changed files with 97 additions and 41 deletions.
11 changes: 8 additions & 3 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -1707,12 +1707,14 @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
return 0;
open_failed:
bs->drv = NULL;

bdrv_graph_wrlock(NULL);
if (bs->file != NULL) {
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, bs->file);
bdrv_graph_wrunlock();
assert(!bs->file);
}
bdrv_graph_wrunlock();

g_free(bs->opaque);
bs->opaque = NULL;
return ret;
Expand Down Expand Up @@ -1854,9 +1856,12 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
Error *local_err = NULL;
bool ro;

GLOBAL_STATE_CODE();

bdrv_graph_rdlock_main_loop();
assert(bs->file == NULL);
assert(options != NULL && bs->options != options);
GLOBAL_STATE_CODE();
bdrv_graph_rdunlock_main_loop();

opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
Expand Down
8 changes: 7 additions & 1 deletion block/blkreplay.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,13 @@ static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs)
static int blkreplay_snapshot_goto(BlockDriverState *bs,
const char *snapshot_id)
{
return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL);
BlockDriverState *file_bs;

bdrv_graph_rdlock_main_loop();
file_bs = bs->file->bs;
bdrv_graph_rdunlock_main_loop();

return bdrv_snapshot_goto(file_bs, snapshot_id, NULL);
}

static BlockDriver bdrv_blkreplay = {
Expand Down
2 changes: 1 addition & 1 deletion block/copy-before-write.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ static int coroutine_fn GRAPH_RDLOCK cbw_co_flush(BlockDriverState *bs)
* It's guaranteed that guest writes will not interact in the region until
* cbw_snapshot_read_unlock() called.
*/
static coroutine_fn BlockReq *
static BlockReq * coroutine_fn GRAPH_RDLOCK
cbw_snapshot_read_lock(BlockDriverState *bs, int64_t offset, int64_t bytes,
int64_t *pnum, BdrvChild **file)
{
Expand Down
6 changes: 6 additions & 0 deletions block/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ static int block_crypto_read_func(QCryptoBlock *block,
BlockDriverState *bs = opaque;
ssize_t ret;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

ret = bdrv_pread(bs->file, offset, buflen, buf, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read encryption header");
Expand All @@ -83,6 +86,9 @@ static int block_crypto_write_func(QCryptoBlock *block,
BlockDriverState *bs = opaque;
ssize_t ret;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

ret = bdrv_pwrite(bs->file, offset, buflen, buf, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not write encryption header");
Expand Down
16 changes: 10 additions & 6 deletions block/dmg.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0;
}

static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
static int GRAPH_RDLOCK
read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
{
uint64_t buffer;
int ret;
Expand All @@ -84,7 +85,8 @@ static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
return 0;
}

static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
static int GRAPH_RDLOCK
read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
{
uint32_t buffer;
int ret;
Expand Down Expand Up @@ -321,8 +323,9 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds,
return ret;
}

static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
uint64_t info_begin, uint64_t info_length)
static int GRAPH_RDLOCK
dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
uint64_t info_begin, uint64_t info_length)
{
BDRVDMGState *s = bs->opaque;
int ret;
Expand Down Expand Up @@ -388,8 +391,9 @@ static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
return ret;
}

static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
uint64_t info_begin, uint64_t info_length)
static int GRAPH_RDLOCK
dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
uint64_t info_begin, uint64_t info_length)
{
BDRVDMGState *s = bs->opaque;
int ret;
Expand Down
21 changes: 10 additions & 11 deletions block/parallels-ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,10 @@ typedef struct ParallelsDirtyBitmapFeature {
} QEMU_PACKED ParallelsDirtyBitmapFeature;

/* Given L1 table read bitmap data from the image and populate @bitmap */
static int parallels_load_bitmap_data(BlockDriverState *bs,
const uint64_t *l1_table,
uint32_t l1_size,
BdrvDirtyBitmap *bitmap,
Error **errp)
static int GRAPH_RDLOCK
parallels_load_bitmap_data(BlockDriverState *bs, const uint64_t *l1_table,
uint32_t l1_size, BdrvDirtyBitmap *bitmap,
Error **errp)
{
BDRVParallelsState *s = bs->opaque;
int ret = 0;
Expand Down Expand Up @@ -120,10 +119,9 @@ static int parallels_load_bitmap_data(BlockDriverState *bs,
* @data buffer (of @data_size size) is the Dirty bitmaps feature which
* consists of ParallelsDirtyBitmapFeature followed by L1 table.
*/
static BdrvDirtyBitmap *parallels_load_bitmap(BlockDriverState *bs,
uint8_t *data,
size_t data_size,
Error **errp)
static BdrvDirtyBitmap * GRAPH_RDLOCK
parallels_load_bitmap(BlockDriverState *bs, uint8_t *data, size_t data_size,
Error **errp)
{
int ret;
ParallelsDirtyBitmapFeature bf;
Expand Down Expand Up @@ -183,8 +181,9 @@ static BdrvDirtyBitmap *parallels_load_bitmap(BlockDriverState *bs,
return bitmap;
}

static int parallels_parse_format_extension(BlockDriverState *bs,
uint8_t *ext_cluster, Error **errp)
static int GRAPH_RDLOCK
parallels_parse_format_extension(BlockDriverState *bs, uint8_t *ext_cluster,
Error **errp)
{
BDRVParallelsState *s = bs->opaque;
int ret;
Expand Down
6 changes: 4 additions & 2 deletions block/parallels.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ static int mark_used(BlockDriverState *bs, unsigned long *bitmap,
* bitmap anyway, as much as we can. This information will be used for
* error resolution.
*/
static int parallels_fill_used_bitmap(BlockDriverState *bs)
static int GRAPH_RDLOCK parallels_fill_used_bitmap(BlockDriverState *bs)
{
BDRVParallelsState *s = bs->opaque;
int64_t payload_bytes;
Expand Down Expand Up @@ -1185,7 +1185,7 @@ static int parallels_probe(const uint8_t *buf, int buf_size,
return 0;
}

static int parallels_update_header(BlockDriverState *bs)
static int GRAPH_RDLOCK parallels_update_header(BlockDriverState *bs)
{
BDRVParallelsState *s = bs->opaque;
unsigned size = MAX(bdrv_opt_mem_align(bs->file->bs),
Expand Down Expand Up @@ -1428,6 +1428,8 @@ static void parallels_close(BlockDriverState *bs)
{
BDRVParallelsState *s = bs->opaque;

GRAPH_RDLOCK_GUARD_MAINLOOP();

if ((bs->open_flags & BDRV_O_RDWR) && !(bs->open_flags & BDRV_O_INACTIVE)) {
s->header->inuse = 0;
parallels_update_header(bs);
Expand Down
5 changes: 3 additions & 2 deletions block/parallels.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ typedef struct BDRVParallelsState {
Error *migration_blocker;
} BDRVParallelsState;

int parallels_read_format_extension(BlockDriverState *bs,
int64_t ext_off, Error **errp);
int GRAPH_RDLOCK
parallels_read_format_extension(BlockDriverState *bs, int64_t ext_off,
Error **errp);

#endif
19 changes: 14 additions & 5 deletions block/preallocate.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
return 0;
}

static int preallocate_truncate_to_real_size(BlockDriverState *bs, Error **errp)
static int GRAPH_RDLOCK
preallocate_truncate_to_real_size(BlockDriverState *bs, Error **errp)
{
BDRVPreallocateState *s = bs->opaque;
int ret;
Expand Down Expand Up @@ -204,6 +205,9 @@ static void preallocate_close(BlockDriverState *bs)
{
BDRVPreallocateState *s = bs->opaque;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

qemu_bh_cancel(s->drop_resize_bh);
qemu_bh_delete(s->drop_resize_bh);

Expand All @@ -227,6 +231,9 @@ static int preallocate_reopen_prepare(BDRVReopenState *reopen_state,
PreallocateOpts *opts = g_new0(PreallocateOpts, 1);
int ret;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

if (!preallocate_absorb_opts(opts, reopen_state->options,
reopen_state->bs->file->bs, errp)) {
g_free(opts);
Expand Down Expand Up @@ -287,7 +294,7 @@ static bool can_write_resize(uint64_t perm)
return (perm & BLK_PERM_WRITE) && (perm & BLK_PERM_RESIZE);
}

static bool has_prealloc_perms(BlockDriverState *bs)
static bool GRAPH_RDLOCK has_prealloc_perms(BlockDriverState *bs)
{
BDRVPreallocateState *s = bs->opaque;

Expand Down Expand Up @@ -503,7 +510,8 @@ preallocate_co_getlength(BlockDriverState *bs)
return ret;
}

static int preallocate_drop_resize(BlockDriverState *bs, Error **errp)
static int GRAPH_RDLOCK
preallocate_drop_resize(BlockDriverState *bs, Error **errp)
{
BDRVPreallocateState *s = bs->opaque;
int ret;
Expand All @@ -529,15 +537,16 @@ static int preallocate_drop_resize(BlockDriverState *bs, Error **errp)
*/
s->data_end = s->file_end = s->zero_start = -EINVAL;

bdrv_graph_rdlock_main_loop();
bdrv_child_refresh_perms(bs, bs->file, NULL);
bdrv_graph_rdunlock_main_loop();

return 0;
}

static void preallocate_drop_resize_bh(void *opaque)
{
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

/*
* In case of errors, we'll simply keep the exclusive lock on the image
* indefinitely.
Expand Down
12 changes: 10 additions & 2 deletions block/qed.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ static int bdrv_qed_reopen_prepare(BDRVReopenState *state,
return 0;
}

static void bdrv_qed_close(BlockDriverState *bs)
static void GRAPH_RDLOCK bdrv_qed_do_close(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;

Expand All @@ -631,6 +631,14 @@ static void bdrv_qed_close(BlockDriverState *bs)
qemu_vfree(s->l1_table);
}

static void GRAPH_UNLOCKED bdrv_qed_close(BlockDriverState *bs)
{
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

bdrv_qed_do_close(bs);
}

static int coroutine_fn GRAPH_UNLOCKED
bdrv_qed_co_create(BlockdevCreateOptions *opts, Error **errp)
{
Expand Down Expand Up @@ -1574,7 +1582,7 @@ bdrv_qed_co_invalidate_cache(BlockDriverState *bs, Error **errp)
BDRVQEDState *s = bs->opaque;
int ret;

bdrv_qed_close(bs);
bdrv_qed_do_close(bs);

bdrv_qed_init_state(bs);
qemu_co_mutex_lock(&s->table_lock);
Expand Down
2 changes: 1 addition & 1 deletion block/qed.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ enum {
/**
* Header functions
*/
int qed_write_header_sync(BDRVQEDState *s);
int GRAPH_RDLOCK qed_write_header_sync(BDRVQEDState *s);

/**
* L2 cache functions
Expand Down
9 changes: 6 additions & 3 deletions block/raw-format.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size,
return ret;
}

static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
uint64_t offset, bool has_size, uint64_t size,
Error **errp)
static int GRAPH_RDLOCK
raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset,
bool has_size, uint64_t size, Error **errp)
{
int64_t real_size = 0;

Expand Down Expand Up @@ -145,6 +145,9 @@ static int raw_reopen_prepare(BDRVReopenState *reopen_state,
uint64_t offset, size;
int ret;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

assert(reopen_state != NULL);
assert(reopen_state->bs != NULL);

Expand Down
5 changes: 4 additions & 1 deletion block/replication.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ static void GRAPH_UNLOCKED
secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
{
BDRVReplicationState *s = bs->opaque;
BdrvChild *active_disk = bs->file;
BdrvChild *active_disk;
Error *local_err = NULL;
int ret;

Expand All @@ -328,6 +328,7 @@ secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
return;
}

active_disk = bs->file;
if (!active_disk->bs->drv) {
error_setg(errp, "Active disk %s is ejected",
active_disk->bs->node_name);
Expand Down Expand Up @@ -755,11 +756,13 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
return;
}

bdrv_graph_rdlock_main_loop();
s->stage = BLOCK_REPLICATION_FAILOVER;
s->commit_job = commit_active_start(
NULL, bs->file->bs, s->secondary_disk->bs,
JOB_INTERNAL, 0, BLOCKDEV_ON_ERROR_REPORT,
NULL, replication_done, bs, true, errp);
bdrv_graph_rdunlock_main_loop();
break;
default:
aio_context_release(aio_context);
Expand Down

0 comments on commit 1f051dc

Please sign in to comment.