Skip to content

Commit

Permalink
block: Mark bdrv_refresh_filename() and callers GRAPH_RDLOCK
Browse files Browse the repository at this point in the history
This adds GRAPH_RDLOCK annotations to declare that callers of
bdrv_refresh_filename() need to hold a reader lock for the graph
because it accesses the children list of a node.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20230929145157.45443-11-kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
kevmw committed Oct 12, 2023
1 parent 15f3f1f commit b7cfc7d
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 47 deletions.
23 changes: 18 additions & 5 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,9 @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
* setting @errp. In all other cases, NULL will only be returned with
* @errp set.
*/
static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
const char *filename, Error **errp)
static char * GRAPH_RDLOCK
bdrv_make_absolute_filename(BlockDriverState *relative_to,
const char *filename, Error **errp)
{
char *dir, *full_name;

Expand Down Expand Up @@ -1250,7 +1251,7 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
*child_flags &= ~BDRV_O_NATIVE_AIO;
}

static void bdrv_backing_attach(BdrvChild *c)
static void GRAPH_WRLOCK bdrv_backing_attach(BdrvChild *c)
{
BlockDriverState *parent = c->opaque;
BlockDriverState *backing_hd = c->bs;
Expand Down Expand Up @@ -1874,7 +1875,10 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
}

if (file != NULL) {
bdrv_graph_rdlock_main_loop();
bdrv_refresh_filename(blk_bs(file));
bdrv_graph_rdunlock_main_loop();

filename = blk_bs(file)->filename;
} else {
/*
Expand Down Expand Up @@ -3644,7 +3648,10 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
}

bdrv_graph_rdlock_main_loop();
backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
bdrv_graph_rdunlock_main_loop();

if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
Expand Down Expand Up @@ -3675,7 +3682,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
}

if (implicit_backing) {
bdrv_graph_rdlock_main_loop();
bdrv_refresh_filename(backing_hd);
bdrv_graph_rdunlock_main_loop();
pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
backing_hd->filename);
}
Expand Down Expand Up @@ -4964,7 +4973,9 @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
if (local_err != NULL) {
error_propagate(errp, local_err);
} else {
bdrv_graph_rdlock_main_loop();
bdrv_refresh_filename(reopen_state->bs);
bdrv_graph_rdunlock_main_loop();
error_setg(errp, "failed while preparing to reopen image '%s'",
reopen_state->bs->filename);
}
Expand Down Expand Up @@ -5931,6 +5942,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,

bdrv_ref(top);
bdrv_drained_begin(base);
bdrv_graph_rdlock_main_loop();

if (!top->drv || !base->drv) {
goto exit;
Expand All @@ -5955,11 +5967,9 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
backing_file_str = base->filename;
}

bdrv_graph_rdlock_main_loop();
QLIST_FOREACH(c, &top->parents, next_parent) {
updated_children = g_slist_prepend(updated_children, c);
}
bdrv_graph_rdunlock_main_loop();

/*
* It seems correct to pass detach_subchain=true here, but it triggers
Expand Down Expand Up @@ -6005,6 +6015,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,

ret = 0;
exit:
bdrv_graph_rdunlock_main_loop();
bdrv_drained_end(base);
bdrv_unref(top);
return ret;
Expand Down Expand Up @@ -6295,6 +6306,7 @@ BlockDeviceInfoList *bdrv_named_nodes_list(bool flat,
BlockDriverState *bs;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

list = NULL;
QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) {
Expand Down Expand Up @@ -6763,6 +6775,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
BlockDriverState *bs_below;

GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();

if (!bs || !bs->drv || !backing_file) {
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion block/nfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ static void nfs_refresh_filename(BlockDriverState *bs)
}
}

static char *nfs_dirname(BlockDriverState *bs, Error **errp)
static char * GRAPH_RDLOCK nfs_dirname(BlockDriverState *bs, Error **errp)
{
NFSClient *client = bs->opaque;

Expand Down
11 changes: 6 additions & 5 deletions block/qapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,8 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
* Helper function for other query info functions. Store information about @bs
* in @info, setting @errp on error.
*/
static void bdrv_do_query_node_info(BlockDriverState *bs,
BlockNodeInfo *info,
Error **errp)
static void GRAPH_RDLOCK
bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, Error **errp)
{
int64_t size;
const char *backing_filename;
Expand Down Expand Up @@ -423,8 +422,8 @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
}

/* @p_info will be set only on success. */
static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
Error **errp)
static void GRAPH_RDLOCK
bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, Error **errp)
{
BlockInfo *info = g_malloc0(sizeof(*info));
BlockDriverState *bs = blk_bs(blk);
Expand Down Expand Up @@ -672,6 +671,8 @@ BlockInfoList *qmp_query_block(Error **errp)
BlockBackend *blk;
Error *local_err = NULL;

GRAPH_RDLOCK_GUARD_MAINLOOP();

for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
BlockInfoList *info;

Expand Down
2 changes: 2 additions & 0 deletions block/raw-format.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,9 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
BDRV_REQ_ZERO_WRITE;

if (bs->probed && !bdrv_is_read_only(bs)) {
bdrv_graph_rdlock_main_loop();
bdrv_refresh_filename(bs->file->bs);
bdrv_graph_rdunlock_main_loop();
fprintf(stderr,
"WARNING: Image format was not specified for '%s' and probing "
"guessed raw.\n"
Expand Down
4 changes: 4 additions & 0 deletions block/vhdx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1001,11 +1001,15 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
uint64_t signature;
Error *local_err = NULL;

GLOBAL_STATE_CODE();

ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}

GRAPH_RDLOCK_GUARD_MAINLOOP();

s->bat = NULL;
s->first_visible_write = true;

Expand Down
5 changes: 3 additions & 2 deletions block/vhdx.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,9 @@ uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,

bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);

int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
Error **errp);
int GRAPH_RDLOCK
vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
Error **errp);

int coroutine_fn GRAPH_RDLOCK
vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
Expand Down
51 changes: 33 additions & 18 deletions block/vmdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,8 +578,8 @@ static int vmdk_add_extent(BlockDriverState *bs,
return 0;
}

static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
Error **errp)
static int GRAPH_RDLOCK
vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, Error **errp)
{
int ret;
size_t l1_size;
Expand Down Expand Up @@ -641,9 +641,9 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
return ret;
}

static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
BdrvChild *file,
int flags, Error **errp)
static int GRAPH_RDLOCK
vmdk_open_vmfs_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
Error **errp)
{
int ret;
uint32_t magic;
Expand Down Expand Up @@ -797,9 +797,9 @@ static int check_se_sparse_volatile_header(VMDKSESparseVolatileHeader *header,
return 0;
}

static int vmdk_open_se_sparse(BlockDriverState *bs,
BdrvChild *file,
int flags, Error **errp)
static int GRAPH_RDLOCK
vmdk_open_se_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
Error **errp)
{
int ret;
VMDKSESparseConstHeader const_header;
Expand Down Expand Up @@ -913,9 +913,9 @@ static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
return buf;
}

static int vmdk_open_vmdk4(BlockDriverState *bs,
BdrvChild *file,
int flags, QDict *options, Error **errp)
static int GRAPH_RDLOCK
vmdk_open_vmdk4(BlockDriverState *bs, BdrvChild *file, int flags,
QDict *options, Error **errp)
{
int ret;
uint32_t magic;
Expand Down Expand Up @@ -1095,8 +1095,9 @@ static int vmdk_parse_description(const char *desc, const char *opt_name,
}

/* Open an extent file and append to bs array */
static int vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
char *buf, QDict *options, Error **errp)
static int GRAPH_RDLOCK
vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
char *buf, QDict *options, Error **errp)
{
uint32_t magic;

Expand All @@ -1123,8 +1124,9 @@ static const char *next_line(const char *s)
return s;
}

static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
QDict *options, Error **errp)
static int GRAPH_RDLOCK
vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
Error **errp)
{
int ret;
int matches;
Expand All @@ -1143,6 +1145,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
char extent_opt_prefix[32];
Error *local_err = NULL;

GLOBAL_STATE_CODE();

for (p = desc; *p; p = next_line(p)) {
/* parse extent line in one of below formats:
*
Expand Down Expand Up @@ -1223,9 +1227,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
ret = vmdk_add_extent(bs, extent_file, true, sectors,
0, 0, 0, 0, 0, &extent, errp);
if (ret < 0) {
bdrv_graph_rdunlock_main_loop();
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
bdrv_graph_rdlock_main_loop();
goto out;
}
extent->flat_start_offset = flat_offset << 9;
Expand All @@ -1240,26 +1246,32 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
}
g_free(buf);
if (ret) {
bdrv_graph_rdunlock_main_loop();
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
bdrv_graph_rdlock_main_loop();
goto out;
}
extent = &s->extents[s->num_extents - 1];
} else if (!strcmp(type, "SESPARSE")) {
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
if (ret) {
bdrv_graph_rdunlock_main_loop();
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
bdrv_graph_rdlock_main_loop();
goto out;
}
extent = &s->extents[s->num_extents - 1];
} else {
error_setg(errp, "Unsupported extent type '%s'", type);
bdrv_graph_rdunlock_main_loop();
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
bdrv_graph_rdlock_main_loop();
ret = -ENOTSUP;
goto out;
}
Expand All @@ -1283,8 +1295,9 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
return ret;
}

static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
QDict *options, Error **errp)
static int GRAPH_RDLOCK
vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf, QDict *options,
Error **errp)
{
int ret;
char ct[128];
Expand Down Expand Up @@ -2900,7 +2913,7 @@ static int vmdk_has_zero_init(BlockDriverState *bs)
return 1;
}

static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
static VmdkExtentInfo * GRAPH_RDLOCK vmdk_get_extent_info(VmdkExtent *extent)
{
VmdkExtentInfo *info = g_new0(VmdkExtentInfo, 1);

Expand Down Expand Up @@ -2985,6 +2998,8 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
VmdkExtentInfoList **tail;

assume_graph_lock(); /* FIXME */

*spec_info = (ImageInfoSpecific){
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
.u = {
Expand Down
13 changes: 13 additions & 0 deletions blockdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,8 @@ static void drive_backup_action(DriveBackup *backup,
bool set_backing_hd = false;
int ret;

GLOBAL_STATE_CODE();

tran_add(tran, &drive_backup_drv, state);

if (!backup->has_mode) {
Expand Down Expand Up @@ -1735,7 +1737,10 @@ static void drive_backup_action(DriveBackup *backup,
BlockDriverState *explicit_backing =
bdrv_skip_implicit_filters(source);

bdrv_graph_rdlock_main_loop();
bdrv_refresh_filename(explicit_backing);
bdrv_graph_rdunlock_main_loop();

bdrv_img_create(backup->target, format,
explicit_backing->filename,
explicit_backing->drv->format_name, NULL,
Expand Down Expand Up @@ -2398,6 +2403,8 @@ void qmp_block_stream(const char *job_id, const char *device,
Error *local_err = NULL;
int job_flags = JOB_DEFAULT;

GLOBAL_STATE_CODE();

if (base && base_node) {
error_setg(errp, "'base' and 'base-node' cannot be specified "
"at the same time");
Expand Down Expand Up @@ -2448,7 +2455,10 @@ void qmp_block_stream(const char *job_id, const char *device,
goto out;
}
assert(bdrv_get_aio_context(base_bs) == aio_context);

bdrv_graph_rdlock_main_loop();
bdrv_refresh_filename(base_bs);
bdrv_graph_rdunlock_main_loop();
}

if (bottom) {
Expand Down Expand Up @@ -3076,7 +3086,10 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
break;
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
/* create new image with backing file */
bdrv_graph_rdlock_main_loop();
bdrv_refresh_filename(explicit_backing);
bdrv_graph_rdunlock_main_loop();

bdrv_img_create(arg->target, format,
explicit_backing->filename,
explicit_backing->drv->format_name,
Expand Down

0 comments on commit b7cfc7d

Please sign in to comment.