Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging
Block layer patches

- Graph locking, part 3 (more block drivers)
- Compile out assert_bdrv_graph_readable() by default
- Add configure options for vmdk, vhdx and vpc
- Fix use after free in blockdev_mark_auto_del()
- migration: Attempt disk reactivation in more failure scenarios
- Coroutine correctness fixes

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmRbi6ERHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9Y66A//ZRk/0M6EZUJPAKG6m/XLTDNrOCNBZ1Tu
# kBGvxXsVQZMt4gGpBad4l2INN6IQKTIdIf+lK71EpxMPmFG6xK32btn38yywCAfQ
# lr1p5nR0Y/zSlT+XzP4yKy/CtQl6U0rkysmjCIk35bZc7uLy6eo4oFR4vmhRRt2M
# UGltB50/Nicx12YFufVjodbhv+apxTGwS2XHatmwqtjKeYReSz8mJHslEy6DvC8m
# ziNThD6YBy7hMktAhNaqUqtZD0OSWz66VMObco/4i2++sOAMZIspXQkjv3AjH74e
# lmgMhNc/xgJKPwFBPsj6F7dOKxwhdKD9jzZlx3yaBtAU18hpWX54QWuA3/CFlySc
# 5QbbqIstFTC8lqoRWThQrcHHRKbDBJCP4ImRXUIKhuPaxEzXA9zb3+f3QPTIjLSA
# KO7nxuSmO+tC7hQ1K9kAjRZHWlxxAk4clk+7UrK4UrWgGxfCUKgFg4Tyx7RrpwA6
# j4L5vwAY60LW74tikWe9xJx2QbdRoWBTTZhUyirbO7rLX1e8mS1nUWmtIsFSQxAq
# Z7nX7ygN0WEF+8qIsk3jTGaEeJoCM7+7B+X2RpSy0sftFjFYmybIiUgLMO7e+ozK
# rvUPnwlHAbGCVIJOKrUDj3cGt6k3/xnrTajUc7pCB3KKqG4pe+IlZuHyKIUMActb
# dBLaBnj0M2o=
# =hw9E
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 10 May 2023 01:18:41 PM BST
# gpg:                using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg:                issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]

* tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (28 commits)
  block: compile out assert_bdrv_graph_readable() by default
  block: Mark bdrv_refresh_limits() and callers GRAPH_RDLOCK
  block: Mark bdrv_recurse_can_replace() and callers GRAPH_RDLOCK
  block: Mark bdrv_query_block_graph_info() and callers GRAPH_RDLOCK
  block: Mark bdrv_query_bds_stats() and callers GRAPH_RDLOCK
  block: Mark BlockDriver callbacks for amend job GRAPH_RDLOCK
  block: Mark bdrv_co_debug_event() GRAPH_RDLOCK
  block: Mark bdrv_co_get_info() and callers GRAPH_RDLOCK
  block: Mark bdrv_co_get_allocated_file_size() and callers GRAPH_RDLOCK
  mirror: Require GRAPH_RDLOCK for accessing a node's parent list
  vhdx: Require GRAPH_RDLOCK for accessing a node's parent list
  nbd: Mark nbd_co_do_establish_connection() and callers GRAPH_RDLOCK
  nbd: Remove nbd_co_flush() wrapper function
  block: .bdrv_open is non-coroutine and unlocked
  graph-lock: Fix GRAPH_RDLOCK_GUARD*() to be reader lock
  graph-lock: Add GRAPH_UNLOCKED(_PTR)
  test-bdrv-drain: Don't modify the graph in coroutines
  iotests: Test resizing image attached to an iothread
  block: Don't call no_coroutine_fns in qmp_block_resize()
  block: bdrv/blk_co_unref() for calls in coroutine context
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 10, 2023
2 parents 568992e + 58a2e3f commit caa9cbd
Show file tree
Hide file tree
Showing 47 changed files with 474 additions and 240 deletions.
25 changes: 20 additions & 5 deletions block.c
Expand Up @@ -680,7 +680,7 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,

ret = 0;
out:
blk_unref(blk);
blk_co_unref(blk);
return ret;
}

Expand Down 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 Expand Up @@ -1667,7 +1667,10 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
return ret;
}

bdrv_graph_rdlock_main_loop();
bdrv_refresh_limits(bs, NULL, &local_err);
bdrv_graph_rdunlock_main_loop();

if (local_err) {
error_propagate(errp, local_err);
return -EINVAL;
Expand Down Expand Up @@ -3419,7 +3422,9 @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
}

out:
bdrv_graph_rdlock_main_loop();
bdrv_refresh_limits(parent_bs, tran, NULL);
bdrv_graph_rdunlock_main_loop();

return 0;
}
Expand Down Expand Up @@ -4917,7 +4922,9 @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
qdict_del(bs->explicit_options, "backing");
qdict_del(bs->options, "backing");

bdrv_graph_rdlock_main_loop();
bdrv_refresh_limits(bs, NULL, NULL);
bdrv_graph_rdunlock_main_loop();
bdrv_refresh_total_sectors(bs, bs->total_sectors);
}

Expand Down Expand Up @@ -5316,7 +5323,9 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
out:
tran_finalize(tran, ret);

bdrv_graph_rdlock_main_loop();
bdrv_refresh_limits(bs_top, NULL, NULL);
bdrv_graph_rdunlock_main_loop();

if (new_context && old_context != new_context) {
aio_context_release(new_context);
Expand Down Expand Up @@ -5750,7 +5759,8 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
* sums the size of all data-bearing children. (This excludes backing
* children.)
*/
static int64_t coroutine_fn bdrv_sum_allocated_file_size(BlockDriverState *bs)
static int64_t coroutine_fn GRAPH_RDLOCK
bdrv_sum_allocated_file_size(BlockDriverState *bs)
{
BdrvChild *child;
int64_t child_size, sum = 0;
Expand Down Expand Up @@ -5778,6 +5788,7 @@ int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
IO_CODE();
assert_bdrv_graph_readable();

if (!drv) {
return -ENOMEDIUM;
Expand Down Expand Up @@ -6347,6 +6358,8 @@ int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
int ret;
BlockDriver *drv = bs->drv;
IO_CODE();
assert_bdrv_graph_readable();

/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
if (!drv) {
return -ENOMEDIUM;
Expand Down Expand Up @@ -6395,6 +6408,8 @@ BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs)
void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
{
IO_CODE();
assert_bdrv_graph_readable();

if (!bs || !bs->drv || !bs->drv->bdrv_co_debug_event) {
return;
}
Expand Down
8 changes: 7 additions & 1 deletion block/amend.c
Expand Up @@ -46,6 +46,7 @@ static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
{
BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
int ret;
GRAPH_RDLOCK_GUARD();

job_progress_set_remaining(&s->common, 1);
ret = s->bs->drv->bdrv_co_amend(s->bs, s->opts, s->force, errp);
Expand All @@ -54,7 +55,8 @@ static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
return ret;
}

static int blockdev_amend_pre_run(BlockdevAmendJob *s, Error **errp)
static int GRAPH_RDLOCK
blockdev_amend_pre_run(BlockdevAmendJob *s, Error **errp)
{
if (s->bs->drv->bdrv_amend_pre_run) {
return s->bs->drv->bdrv_amend_pre_run(s->bs, errp);
Expand All @@ -67,9 +69,11 @@ static void blockdev_amend_free(Job *job)
{
BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);

bdrv_graph_rdlock_main_loop();
if (s->bs->drv->bdrv_amend_clean) {
s->bs->drv->bdrv_amend_clean(s->bs);
}
bdrv_graph_rdunlock_main_loop();

bdrv_unref(s->bs);
}
Expand All @@ -93,6 +97,8 @@ void qmp_x_blockdev_amend(const char *job_id,
BlockDriver *drv = bdrv_find_format(fmt);
BlockDriverState *bs;

GRAPH_RDLOCK_GUARD_MAINLOOP();

bs = bdrv_lookup_bs(NULL, node_name, errp);
if (!bs) {
return;
Expand Down
5 changes: 3 additions & 2 deletions block/blkverify.c
Expand Up @@ -265,8 +265,9 @@ static int coroutine_fn GRAPH_RDLOCK blkverify_co_flush(BlockDriverState *bs)
return bdrv_co_flush(s->test_file->bs);
}

static bool blkverify_recurse_can_replace(BlockDriverState *bs,
BlockDriverState *to_replace)
static bool GRAPH_RDLOCK
blkverify_recurse_can_replace(BlockDriverState *bs,
BlockDriverState *to_replace)
{
BDRVBlkverifyState *s = bs->opaque;

Expand Down
10 changes: 9 additions & 1 deletion block/block-backend.c
Expand Up @@ -2024,7 +2024,15 @@ void blk_activate(BlockBackend *blk, Error **errp)
return;
}

bdrv_activate(bs, errp);
/*
* Migration code can call this function in coroutine context, so leave
* coroutine context if necessary.
*/
if (qemu_in_coroutine()) {
bdrv_co_activate(bs, errp);
} else {
bdrv_activate(bs, errp);
}
}

bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
Expand Down
5 changes: 3 additions & 2 deletions block/coroutines.h
Expand Up @@ -61,7 +61,7 @@ bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
int coroutine_fn GRAPH_RDLOCK
bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);

int coroutine_fn
int coroutine_fn GRAPH_RDLOCK
nbd_co_do_establish_connection(BlockDriverState *bs, bool blocking,
Error **errp);

Expand All @@ -85,7 +85,8 @@ bdrv_common_block_status_above(BlockDriverState *bs,
int64_t *map,
BlockDriverState **file,
int *depth);
int co_wrapper_mixed

int co_wrapper_mixed_bdrv_rdlock
nbd_do_establish_connection(BlockDriverState *bs, bool blocking, Error **errp);

#endif /* BLOCK_COROUTINES_H */
8 changes: 4 additions & 4 deletions block/crypto.c
Expand Up @@ -355,7 +355,7 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
ret = 0;
cleanup:
qcrypto_block_free(crypto);
blk_unref(blk);
blk_co_unref(blk);
return ret;
}

Expand Down Expand Up @@ -661,7 +661,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)

ret = 0;
fail:
bdrv_unref(bs);
bdrv_co_unref(bs);
return ret;
}

Expand Down Expand Up @@ -730,13 +730,13 @@ block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
bdrv_co_delete_file_noerr(bs);
}

bdrv_unref(bs);
bdrv_co_unref(bs);
qapi_free_QCryptoBlockCreateOptions(create_opts);
qobject_unref(cryptoopts);
return ret;
}

static int coroutine_fn
static int coroutine_fn GRAPH_RDLOCK
block_crypto_co_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BlockDriverInfo subbdi;
Expand Down
3 changes: 3 additions & 0 deletions block/graph-lock.c
Expand Up @@ -265,7 +265,10 @@ void bdrv_graph_rdunlock_main_loop(void)

void assert_bdrv_graph_readable(void)
{
/* reader_count() is slow due to aio_context_list_lock lock contention */
#ifdef CONFIG_DEBUG_GRAPH_LOCK
assert(qemu_in_main_thread() || reader_count());
#endif
}

void assert_bdrv_graph_writable(void)
Expand Down
12 changes: 5 additions & 7 deletions block/io.c
Expand Up @@ -160,7 +160,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
bool have_limits;

GLOBAL_STATE_CODE();
assume_graph_lock(); /* FIXME */

if (tran) {
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
Expand Down Expand Up @@ -727,10 +726,9 @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
/**
* Round a region to cluster boundaries
*/
void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs,
int64_t offset, int64_t bytes,
int64_t *cluster_offset,
int64_t *cluster_bytes)
void coroutine_fn GRAPH_RDLOCK
bdrv_round_to_clusters(BlockDriverState *bs, int64_t offset, int64_t bytes,
int64_t *cluster_offset, int64_t *cluster_bytes)
{
BlockDriverInfo bdi;
IO_CODE();
Expand All @@ -744,7 +742,7 @@ void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs,
}
}

static coroutine_fn int bdrv_get_cluster_size(BlockDriverState *bs)
static int coroutine_fn GRAPH_RDLOCK bdrv_get_cluster_size(BlockDriverState *bs)
{
BlockDriverInfo bdi;
int ret;
Expand Down Expand Up @@ -1800,7 +1798,7 @@ bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
return ret;
}

static inline int coroutine_fn
static inline int coroutine_fn GRAPH_RDLOCK
bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
BdrvTrackedRequest *req, int flags)
{
Expand Down
18 changes: 13 additions & 5 deletions block/meson.build
Expand Up @@ -38,11 +38,6 @@ block_ss.add(files(
'snapshot-access.c',
'throttle-groups.c',
'throttle.c',
'vhdx-endian.c',
'vhdx-log.c',
'vhdx.c',
'vmdk.c',
'vpc.c',
'write-threshold.c',
), zstd, zlib, gnutls)

Expand All @@ -55,6 +50,19 @@ endif
if get_option('vdi').allowed()
block_ss.add(files('vdi.c'))
endif
if get_option('vhdx').allowed()
block_ss.add(files(
'vhdx-endian.c',
'vhdx-log.c',
'vhdx.c'
))
endif
if get_option('vmdk').allowed()
block_ss.add(files('vmdk.c'))
endif
if get_option('vpc').allowed()
block_ss.add(files('vpc.c'))
endif
if get_option('cloop').allowed()
block_ss.add(files('cloop.c'))
endif
Expand Down
18 changes: 13 additions & 5 deletions block/mirror.c
Expand Up @@ -270,8 +270,8 @@ static inline int64_t mirror_clip_bytes(MirrorBlockJob *s,

/* Round offset and/or bytes to target cluster if COW is needed, and
* return the offset of the adjusted tail against original. */
static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
uint64_t *bytes)
static int coroutine_fn mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
uint64_t *bytes)
{
bool need_cow;
int ret = 0;
Expand Down Expand Up @@ -576,8 +576,10 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
} else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) {
int64_t target_offset;
int64_t target_bytes;
bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
&target_offset, &target_bytes);
WITH_GRAPH_RDLOCK_GUARD() {
bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
&target_offset, &target_bytes);
}
if (target_offset == offset &&
target_bytes == io_bytes) {
mirror_method = ret & BDRV_BLOCK_ZERO ?
Expand Down Expand Up @@ -745,7 +747,10 @@ static int mirror_exit_common(Job *job)
* Cannot use check_to_replace_node() here, because that would
* check for an op blocker on @to_replace, and we have our own
* there.
*
* TODO Pull out the writer lock from bdrv_replace_node() to here
*/
bdrv_graph_rdlock_main_loop();
if (bdrv_recurse_can_replace(src, to_replace)) {
bdrv_replace_node(to_replace, target_bs, &local_err);
} else {
Expand All @@ -754,6 +759,7 @@ static int mirror_exit_common(Job *job)
"would not lead to an abrupt change of visible data",
to_replace->node_name, target_bs->node_name);
}
bdrv_graph_rdunlock_main_loop();
bdrv_drained_end(target_bs);
if (local_err) {
error_report_err(local_err);
Expand Down Expand Up @@ -966,11 +972,13 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
*/
bdrv_get_backing_filename(target_bs, backing_filename,
sizeof(backing_filename));
bdrv_graph_co_rdlock();
if (!bdrv_co_get_info(target_bs, &bdi) && bdi.cluster_size) {
s->target_cluster_size = bdi.cluster_size;
} else {
s->target_cluster_size = BDRV_SECTOR_SIZE;
}
bdrv_graph_co_rdunlock();
if (backing_filename[0] && !bdrv_backing_chain_next(target_bs) &&
s->granularity < s->target_cluster_size) {
s->buf_size = MAX(s->buf_size, s->target_cluster_size);
Expand Down Expand Up @@ -1416,7 +1424,7 @@ static MirrorOp *coroutine_fn active_write_prepare(MirrorBlockJob *s,
return op;
}

static void coroutine_fn active_write_settle(MirrorOp *op)
static void coroutine_fn GRAPH_RDLOCK active_write_settle(MirrorOp *op)
{
uint64_t start_chunk = op->offset / op->s->granularity;
uint64_t end_chunk = DIV_ROUND_UP(op->offset + op->bytes,
Expand Down

0 comments on commit caa9cbd

Please sign in to comment.