Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
block: .bdrv_open is non-coroutine and unlocked
Drivers were a bit confused about whether .bdrv_open can run in a
coroutine and whether or not it holds a graph lock.

It cannot keep a graph lock from the caller across the whole function
because it both changes the graph (requires a writer lock) and does I/O
(requires a reader lock). Therefore, it should take these locks
internally as needed.

The functions used to be called in coroutine context during image
creation. This was buggy for other reasons, and as of commit 3219230,
all block drivers go through no_co_wrappers. So it is not called in
coroutine context any more.

Fix qcow2 and qed to work with the correct assumptions: The graph lock
needs to be taken internally instead of just assuming it's already
there, and the coroutine path is dead code that can be removed.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20230504115750.54437-9-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
Kevin Wolf committed May 10, 2023
1 parent 4ee1f85 commit 1a30b0f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 26 deletions.
6 changes: 3 additions & 3 deletions block.c
Expand Up @@ -1610,9 +1610,9 @@ static void bdrv_assign_node_name(BlockDriverState *bs,
* bdrv_refresh_total_sectors() which polls when called from non-coroutine
* context.
*/
static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
const char *node_name, QDict *options,
int open_flags, Error **errp)
static int no_coroutine_fn GRAPH_UNLOCKED
bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
QDict *options, int open_flags, Error **errp)
{
Error *local_err = NULL;
int i, ret;
Expand Down
15 changes: 6 additions & 9 deletions block/qcow2.c
Expand Up @@ -1891,7 +1891,7 @@ static void coroutine_fn qcow2_open_entry(void *opaque)
QCow2OpenCo *qoc = opaque;
BDRVQcow2State *s = qoc->bs->opaque;

assume_graph_lock(); /* FIXME */
GRAPH_RDLOCK_GUARD();

qemu_co_mutex_lock(&s->lock);
qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
Expand Down Expand Up @@ -1920,14 +1920,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
/* Initialise locks */
qemu_co_mutex_init(&s->lock);

if (qemu_in_coroutine()) {
/* From bdrv_co_create. */
qcow2_open_entry(&qoc);
} else {
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
}
assert(!qemu_in_coroutine());
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);

return qoc.ret;
}

Expand Down
18 changes: 8 additions & 10 deletions block/qed.c
Expand Up @@ -557,11 +557,13 @@ typedef struct QEDOpenCo {
int ret;
} QEDOpenCo;

static void coroutine_fn GRAPH_RDLOCK bdrv_qed_open_entry(void *opaque)
static void coroutine_fn bdrv_qed_open_entry(void *opaque)
{
QEDOpenCo *qoc = opaque;
BDRVQEDState *s = qoc->bs->opaque;

GRAPH_RDLOCK_GUARD();

qemu_co_mutex_lock(&s->table_lock);
qoc->ret = bdrv_qed_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp);
qemu_co_mutex_unlock(&s->table_lock);
Expand All @@ -579,21 +581,17 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
};
int ret;

assume_graph_lock(); /* FIXME */

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

bdrv_qed_init_state(bs);
if (qemu_in_coroutine()) {
bdrv_qed_open_entry(&qoc);
} else {
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
}
assert(!qemu_in_coroutine());
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);

return qoc.ret;
}

Expand Down
8 changes: 4 additions & 4 deletions include/block/block_int-common.h
Expand Up @@ -236,12 +236,12 @@ struct BlockDriver {
void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
void (*bdrv_join_options)(QDict *options, QDict *old_options);

int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags,
Error **errp);
int GRAPH_UNLOCKED_PTR (*bdrv_open)(
BlockDriverState *bs, QDict *options, int flags, Error **errp);

/* Protocol drivers should implement this instead of bdrv_open */
int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags,
Error **errp);
int GRAPH_UNLOCKED_PTR (*bdrv_file_open)(
BlockDriverState *bs, QDict *options, int flags, Error **errp);
void (*bdrv_close)(BlockDriverState *bs);

int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create)(
Expand Down

0 comments on commit 1a30b0f

Please sign in to comment.