block: Mark bdrv_unref_child() GRAPH_WRLOCK

Instead of taking the writer lock internally, require callers to already
hold it when calling bdrv_unref_child(). These callers will typically
already hold the graph lock once the locking work is completed, which
means that they can't call functions that take it internally.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20230911094620.45040-21-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Kevin Wolf 2023-09-11 11:46:19 +02:00
parent ede01e4635
commit 32a8aba37e
10 changed files with 50 additions and 8 deletions

11
block.c
View File

@ -1701,7 +1701,9 @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
open_failed: open_failed:
bs->drv = NULL; bs->drv = NULL;
if (bs->file != NULL) { if (bs->file != NULL) {
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, bs->file); bdrv_unref_child(bs, bs->file);
bdrv_graph_wrunlock();
assert(!bs->file); assert(!bs->file);
} }
g_free(bs->opaque); g_free(bs->opaque);
@ -3331,8 +3333,9 @@ static void bdrv_set_inherits_from(BlockDriverState *bs,
* @root that point to @root, where necessary. * @root that point to @root, where necessary.
* @tran is allowed to be NULL. In this case no rollback is possible * @tran is allowed to be NULL. In this case no rollback is possible
*/ */
static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child, static void GRAPH_WRLOCK
Transaction *tran) bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child,
Transaction *tran)
{ {
BdrvChild *c; BdrvChild *c;
@ -3364,10 +3367,8 @@ void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child)
return; return;
} }
bdrv_graph_wrlock(NULL);
bdrv_unset_inherits_from(parent, child, NULL); bdrv_unset_inherits_from(parent, child, NULL);
bdrv_root_unref_child(child); bdrv_root_unref_child(child);
bdrv_graph_wrunlock();
} }
@ -5164,9 +5165,11 @@ static void bdrv_close(BlockDriverState *bs)
bs->drv = NULL; bs->drv = NULL;
} }
bdrv_graph_wrlock(NULL);
QLIST_FOREACH_SAFE(child, &bs->children, next, next) { QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
bdrv_unref_child(bs, child); bdrv_unref_child(bs, child);
} }
bdrv_graph_wrunlock();
assert(!bs->backing); assert(!bs->backing);
assert(!bs->file); assert(!bs->file);

View File

@ -251,7 +251,9 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
ret = 0; ret = 0;
fail_log: fail_log:
if (ret < 0) { if (ret < 0) {
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, s->log_file); bdrv_unref_child(bs, s->log_file);
bdrv_graph_wrunlock();
s->log_file = NULL; s->log_file = NULL;
} }
fail: fail:
@ -263,8 +265,10 @@ static void blk_log_writes_close(BlockDriverState *bs)
{ {
BDRVBlkLogWritesState *s = bs->opaque; BDRVBlkLogWritesState *s = bs->opaque;
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, s->log_file); bdrv_unref_child(bs, s->log_file);
s->log_file = NULL; s->log_file = NULL;
bdrv_graph_wrunlock();
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn GRAPH_RDLOCK

View File

@ -151,8 +151,10 @@ static void blkverify_close(BlockDriverState *bs)
{ {
BDRVBlkverifyState *s = bs->opaque; BDRVBlkverifyState *s = bs->opaque;
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, s->test_file); bdrv_unref_child(bs, s->test_file);
s->test_file = NULL; s->test_file = NULL;
bdrv_graph_wrunlock();
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn GRAPH_RDLOCK

View File

@ -1880,7 +1880,7 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
g_free(s->image_data_file); g_free(s->image_data_file);
if (open_data_file && has_data_file(bs)) { if (open_data_file && has_data_file(bs)) {
bdrv_graph_co_rdunlock(); bdrv_graph_co_rdunlock();
bdrv_unref_child(bs, s->data_file); bdrv_co_unref_child(bs, s->data_file);
bdrv_graph_co_rdlock(); bdrv_graph_co_rdlock();
s->data_file = NULL; s->data_file = NULL;
} }
@ -2790,7 +2790,9 @@ static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
g_free(s->image_backing_format); g_free(s->image_backing_format);
if (close_data_file && has_data_file(bs)) { if (close_data_file && has_data_file(bs)) {
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, s->data_file); bdrv_unref_child(bs, s->data_file);
bdrv_graph_wrunlock();
s->data_file = NULL; s->data_file = NULL;
} }

View File

@ -1037,12 +1037,14 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
close_exit: close_exit:
/* cleanup on error */ /* cleanup on error */
bdrv_graph_wrlock(NULL);
for (i = 0; i < s->num_children; i++) { for (i = 0; i < s->num_children; i++) {
if (!opened[i]) { if (!opened[i]) {
continue; continue;
} }
bdrv_unref_child(bs, s->children[i]); bdrv_unref_child(bs, s->children[i]);
} }
bdrv_graph_wrunlock();
g_free(s->children); g_free(s->children);
g_free(opened); g_free(opened);
exit: exit:
@ -1055,9 +1057,11 @@ static void quorum_close(BlockDriverState *bs)
BDRVQuorumState *s = bs->opaque; BDRVQuorumState *s = bs->opaque;
int i; int i;
bdrv_graph_wrlock(NULL);
for (i = 0; i < s->num_children; i++) { for (i = 0; i < s->num_children; i++) {
bdrv_unref_child(bs, s->children[i]); bdrv_unref_child(bs, s->children[i]);
} }
bdrv_graph_wrunlock();
g_free(s->children); g_free(s->children);
} }
@ -1147,7 +1151,9 @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
memmove(&s->children[i], &s->children[i + 1], memmove(&s->children[i], &s->children[i + 1],
(s->num_children - i - 1) * sizeof(BdrvChild *)); (s->num_children - i - 1) * sizeof(BdrvChild *));
s->children = g_renew(BdrvChild *, s->children, --s->num_children); s->children = g_renew(BdrvChild *, s->children, --s->num_children);
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, child); bdrv_unref_child(bs, child);
bdrv_graph_wrunlock();
quorum_refresh_flags(bs); quorum_refresh_flags(bs);
bdrv_drained_end(bs); bdrv_drained_end(bs);

View File

@ -672,10 +672,13 @@ static void replication_done(void *opaque, int ret)
if (ret == 0) { if (ret == 0) {
s->stage = BLOCK_REPLICATION_DONE; s->stage = BLOCK_REPLICATION_DONE;
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, s->secondary_disk); bdrv_unref_child(bs, s->secondary_disk);
s->secondary_disk = NULL; s->secondary_disk = NULL;
bdrv_unref_child(bs, s->hidden_disk); bdrv_unref_child(bs, s->hidden_disk);
s->hidden_disk = NULL; s->hidden_disk = NULL;
bdrv_graph_wrunlock();
s->error = 0; s->error = 0;
} else { } else {
s->stage = BLOCK_REPLICATION_FAILOVER_FAILED; s->stage = BLOCK_REPLICATION_FAILOVER_FAILED;

View File

@ -281,7 +281,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
} }
/* .bdrv_open() will re-attach it */ /* .bdrv_open() will re-attach it */
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, fallback); bdrv_unref_child(bs, fallback);
bdrv_graph_wrunlock();
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp); ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err); open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);

View File

@ -272,6 +272,7 @@ static void vmdk_free_extents(BlockDriverState *bs)
BDRVVmdkState *s = bs->opaque; BDRVVmdkState *s = bs->opaque;
VmdkExtent *e; VmdkExtent *e;
bdrv_graph_wrlock(NULL);
for (i = 0; i < s->num_extents; i++) { for (i = 0; i < s->num_extents; i++) {
e = &s->extents[i]; e = &s->extents[i];
g_free(e->l1_table); g_free(e->l1_table);
@ -282,6 +283,8 @@ static void vmdk_free_extents(BlockDriverState *bs)
bdrv_unref_child(bs, e->file); bdrv_unref_child(bs, e->file);
} }
} }
bdrv_graph_wrunlock();
g_free(s->extents); g_free(s->extents);
} }
@ -1220,7 +1223,9 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
ret = vmdk_add_extent(bs, extent_file, true, sectors, ret = vmdk_add_extent(bs, extent_file, true, sectors,
0, 0, 0, 0, 0, &extent, errp); 0, 0, 0, 0, 0, &extent, errp);
if (ret < 0) { if (ret < 0) {
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file); bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
goto out; goto out;
} }
extent->flat_start_offset = flat_offset << 9; extent->flat_start_offset = flat_offset << 9;
@ -1235,20 +1240,26 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
} }
g_free(buf); g_free(buf);
if (ret) { if (ret) {
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file); bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
goto out; goto out;
} }
extent = &s->extents[s->num_extents - 1]; extent = &s->extents[s->num_extents - 1];
} else if (!strcmp(type, "SESPARSE")) { } else if (!strcmp(type, "SESPARSE")) {
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp); ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
if (ret) { if (ret) {
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file); bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
goto out; goto out;
} }
extent = &s->extents[s->num_extents - 1]; extent = &s->extents[s->num_extents - 1];
} else { } else {
error_setg(errp, "Unsupported extent type '%s'", type); error_setg(errp, "Unsupported extent type '%s'", type);
bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, extent_file); bdrv_unref_child(bs, extent_file);
bdrv_graph_wrunlock();
ret = -ENOTSUP; ret = -ENOTSUP;
goto out; goto out;
} }

View File

@ -225,7 +225,12 @@ void bdrv_ref(BlockDriverState *bs);
void no_coroutine_fn bdrv_unref(BlockDriverState *bs); void no_coroutine_fn bdrv_unref(BlockDriverState *bs);
void coroutine_fn no_co_wrapper bdrv_co_unref(BlockDriverState *bs); void coroutine_fn no_co_wrapper bdrv_co_unref(BlockDriverState *bs);
void GRAPH_WRLOCK bdrv_schedule_unref(BlockDriverState *bs); void GRAPH_WRLOCK bdrv_schedule_unref(BlockDriverState *bs);
void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
void GRAPH_WRLOCK
bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
void coroutine_fn no_co_wrapper_bdrv_wrlock
bdrv_co_unref_child(BlockDriverState *parent, BdrvChild *child);
BdrvChild * GRAPH_WRLOCK BdrvChild * GRAPH_WRLOCK
bdrv_attach_child(BlockDriverState *parent_bs, bdrv_attach_child(BlockDriverState *parent_bs,

View File

@ -967,9 +967,12 @@ typedef struct BDRVTestTopState {
static void bdrv_test_top_close(BlockDriverState *bs) static void bdrv_test_top_close(BlockDriverState *bs)
{ {
BdrvChild *c, *next_c; BdrvChild *c, *next_c;
bdrv_graph_wrlock(NULL);
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) { QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
bdrv_unref_child(bs, c); bdrv_unref_child(bs, c);
} }
bdrv_graph_wrunlock();
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
@ -1024,7 +1027,7 @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
} else { } else {
BdrvChild *c, *next_c; BdrvChild *c, *next_c;
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) { QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
bdrv_unref_child(bs, c); bdrv_co_unref_child(bs, c);
} }
} }
@ -1162,10 +1165,11 @@ static void detach_indirect_bh(void *opaque)
struct detach_by_parent_data *data = opaque; struct detach_by_parent_data *data = opaque;
bdrv_dec_in_flight(data->child_b->bs); bdrv_dec_in_flight(data->child_b->bs);
bdrv_graph_wrlock(NULL);
bdrv_unref_child(data->parent_b, data->child_b); bdrv_unref_child(data->parent_b, data->child_b);
bdrv_ref(data->c); bdrv_ref(data->c);
bdrv_graph_wrlock(NULL);
data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C", data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C",
&child_of_bds, BDRV_CHILD_DATA, &child_of_bds, BDRV_CHILD_DATA,
&error_abort); &error_abort);