Block layer patches

- configure: Enable -Wthread-safety if present
 - no_co_wrapper to fix bdrv_open*() calls from coroutine context
 - curl fixes, including enablement of newer libcurl versions
 - MAINTAINERS: drop Vladimir from parallels block driver
 - hbitmap: fix hbitmap_status() return value for first dirty bit case
 - file-posix: Fix assertion failure in write_zeroes after moving
   bdrv_getlength() to co_wrapper
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmPvgm0RHGt3b2xmQHJl
 ZGhhdC5jb20ACgkQfwmycsiPL9ZxQg//ZWwwh/s/P1PnKAjInNZZNklAWKThNEbZ
 cF1S94w26IhEQqM0i6MflqcDsPU5t4xZtBUOizx++9M4G8amWnomJSdczUcKULla
 Az9yweFC1Gu6ENdw+ql5VOzCfpdH5Bn9Jkly5fxuI4vmnBz1PH1Dnd3P4wuLq2sL
 xna5dijVEhRc5mTKWjbp4nFfvQhucuEBPSNjgnZwEPbhciWxTMmB1GmyRvTxZy8v
 UY8PcoTlxdKeVQ6DTmkOirphpGj7HeNCEQnZppWs7vHys2oGi9kmR5qTKUNZxGrY
 8yWiCiVDqbb50fhEC1srhph79bCij87QC1N33Bm+NuGjnjG4bKVx2B9DC8+6S/JS
 e3x6u+r0dd6/t0rjKnt1+inYqmM+i5lBJ7+R0yhWUQ+DYkvttNf5yiotD8qvccWJ
 Kcx14lfjPLK7siAMEY5K0bNMimhN4RR9oCLoPTOHei+vlxdfiMm2XPN61NNht5gD
 lYZ8JMBsEF/o2ebqTgsJrIHS+Q/8MqcwSunBc54fcXZoF+eiza3W2ArXLNfAEfGE
 U4JowNK2PrTIrpEjD+Vs0RsBBSmN5PcYIAz04ioODpDnYMq73/t3x9MKdVoxOT64
 AM7w58fSyWu8iwvkeA0d3XeVtSHFqZ49PqqIem4IegtnC/AXMUNrJ/VT99xHjeJY
 oLhOJz7LUg0=
 =FtaA
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging

Block layer patches

- configure: Enable -Wthread-safety if present
- no_co_wrapper to fix bdrv_open*() calls from coroutine context
- curl fixes, including enablement of newer libcurl versions
- MAINTAINERS: drop Vladimir from parallels block driver
- hbitmap: fix hbitmap_status() return value for first dirty bit case
- file-posix: Fix assertion failure in write_zeroes after moving
  bdrv_getlength() to co_wrapper

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmPvgm0RHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9ZxQg//ZWwwh/s/P1PnKAjInNZZNklAWKThNEbZ
# cF1S94w26IhEQqM0i6MflqcDsPU5t4xZtBUOizx++9M4G8amWnomJSdczUcKULla
# Az9yweFC1Gu6ENdw+ql5VOzCfpdH5Bn9Jkly5fxuI4vmnBz1PH1Dnd3P4wuLq2sL
# xna5dijVEhRc5mTKWjbp4nFfvQhucuEBPSNjgnZwEPbhciWxTMmB1GmyRvTxZy8v
# UY8PcoTlxdKeVQ6DTmkOirphpGj7HeNCEQnZppWs7vHys2oGi9kmR5qTKUNZxGrY
# 8yWiCiVDqbb50fhEC1srhph79bCij87QC1N33Bm+NuGjnjG4bKVx2B9DC8+6S/JS
# e3x6u+r0dd6/t0rjKnt1+inYqmM+i5lBJ7+R0yhWUQ+DYkvttNf5yiotD8qvccWJ
# Kcx14lfjPLK7siAMEY5K0bNMimhN4RR9oCLoPTOHei+vlxdfiMm2XPN61NNht5gD
# lYZ8JMBsEF/o2ebqTgsJrIHS+Q/8MqcwSunBc54fcXZoF+eiza3W2ArXLNfAEfGE
# U4JowNK2PrTIrpEjD+Vs0RsBBSmN5PcYIAz04ioODpDnYMq73/t3x9MKdVoxOT64
# AM7w58fSyWu8iwvkeA0d3XeVtSHFqZ49PqqIem4IegtnC/AXMUNrJ/VT99xHjeJY
# oLhOJz7LUg0=
# =FtaA
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 17 Feb 2023 13:34:37 GMT
# gpg:                using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg:                issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (22 commits)
  hbitmap: fix hbitmap_status() return value for first dirty bit case
  block/file-posix: don't use functions calling AIO_WAIT_WHILE in worker threads
  MAINTAINERS: drop Vladimir from parallels block driver
  block: temporarily hold the new AioContext of bs_top in bdrv_append()
  block: Handle curl 7.55.0, 7.85.0 version changes
  block: Assert non-coroutine context for bdrv_open_inherit()
  block: Fix bdrv_co_create_opts_simple() to open images with no_co_wrapper
  vpc: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  vmdk: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  vhdx: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  vdi: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  qed: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  qcow2: Fix open/create to open images with no_co_wrapper
  qcow: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  parallels: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  luks: Fix .bdrv_co_create(_opts) to open images with no_co_wrapper
  block: Create no_co_wrappers for open functions
  block-coroutine-wrapper: Introduce no_co_wrapper
  curl: Fix error path in curl_open()
  configure: Enable -Wthread-safety if present
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2023-02-20 13:39:18 +00:00
commit 2d89cb1fe5
25 changed files with 295 additions and 128 deletions

View File

@ -3579,13 +3579,11 @@ F: block/dmg.c
parallels
M: Stefan Hajnoczi <stefanha@redhat.com>
M: Denis V. Lunev <den@openvz.org>
M: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
L: qemu-block@nongnu.org
S: Supported
F: block/parallels.c
F: block/parallels-ext.c
F: docs/interop/parallels.txt
T: git https://gitlab.com/vsementsov/qemu.git block
qed
M: Stefan Hajnoczi <stefanha@redhat.com>

40
block.c
View File

@ -657,8 +657,8 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
options = qdict_new();
qdict_put_str(options, "driver", drv->format_name);
blk = blk_new_open(filename, NULL, options,
BDRV_O_RDWR | BDRV_O_RESIZE, errp);
blk = blk_co_new_open(filename, NULL, options,
BDRV_O_RDWR | BDRV_O_RESIZE, errp);
if (!blk) {
error_prepend(errp, "Protocol driver '%s' does not support image "
"creation, and opening the image failed: ",
@ -3807,13 +3807,11 @@ out:
* function eventually calls bdrv_refresh_total_sectors() which polls
* when called from non-coroutine context.
*/
static BlockDriverState *bdrv_open_inherit(const char *filename,
const char *reference,
QDict *options, int flags,
BlockDriverState *parent,
const BdrvChildClass *child_class,
BdrvChildRole child_role,
Error **errp)
static BlockDriverState * no_coroutine_fn
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
int flags, BlockDriverState *parent,
const BdrvChildClass *child_class, BdrvChildRole child_role,
Error **errp)
{
int ret;
BlockBackend *file = NULL;
@ -3829,6 +3827,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
assert(!child_class || !flags);
assert(!child_class == !parent);
GLOBAL_STATE_CODE();
assert(!qemu_in_coroutine());
if (reference) {
bool options_non_empty = options ? qdict_size(options) : false;
@ -5266,6 +5265,8 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp)
* child.
*
* This function does not create any image files.
*
* The caller must hold the AioContext lock for @bs_top.
*/
int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
Error **errp)
@ -5273,11 +5274,14 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
int ret;
BdrvChild *child;
Transaction *tran = tran_new();
AioContext *old_context, *new_context = NULL;
GLOBAL_STATE_CODE();
assert(!bs_new->backing);
old_context = bdrv_get_aio_context(bs_top);
child = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
&child_of_bds, bdrv_backing_role(bs_new),
tran, errp);
@ -5286,6 +5290,19 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
goto out;
}
/*
* bdrv_attach_child_noperm could change the AioContext of bs_top.
* bdrv_replace_node_noperm calls bdrv_drained_begin, so let's temporarily
* hold the new AioContext, since bdrv_drained_begin calls BDRV_POLL_WHILE
* that assumes the new lock is taken.
*/
new_context = bdrv_get_aio_context(bs_top);
if (old_context != new_context) {
aio_context_release(old_context);
aio_context_acquire(new_context);
}
ret = bdrv_replace_node_noperm(bs_top, bs_new, true, tran, errp);
if (ret < 0) {
goto out;
@ -5297,6 +5314,11 @@ out:
bdrv_refresh_limits(bs_top, NULL, NULL);
if (new_context && old_context != new_context) {
aio_context_release(new_context);
aio_context_acquire(old_context);
}
return ret;
}

View File

@ -314,19 +314,18 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
}
static int block_crypto_co_create_generic(BlockDriverState *bs,
int64_t size,
QCryptoBlockCreateOptions *opts,
PreallocMode prealloc,
Error **errp)
static int coroutine_fn
block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
QCryptoBlockCreateOptions *opts,
PreallocMode prealloc, Error **errp)
{
int ret;
BlockBackend *blk;
QCryptoBlock *crypto = NULL;
struct BlockCryptoCreateData data;
blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
if (!blk) {
ret = -EPERM;
goto cleanup;
@ -639,7 +638,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
luks_opts = &create_options->u.luks;
bs = bdrv_open_blockdev_ref(luks_opts->file, errp);
bs = bdrv_co_open_blockdev_ref(luks_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
@ -708,8 +707,8 @@ static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv,
goto fail;
}
bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (!bs) {
ret = -EINVAL;
goto fail;

View File

@ -38,8 +38,15 @@
// #define DEBUG_VERBOSE
/* CURL 7.85.0 switches to a string based API for specifying
* the desired protocols.
*/
#if LIBCURL_VERSION_NUM >= 0x075500
#define PROTOCOLS "HTTP,HTTPS,FTP,FTPS"
#else
#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
CURLPROTO_FTP | CURLPROTO_FTPS)
#endif
#define CURL_NUM_STATES 8
#define CURL_NUM_ACB 8
@ -510,9 +517,18 @@ static int curl_init_state(BDRVCURLState *s, CURLState *state)
* obscure protocols. For example, do not allow POP3/SMTP/IMAP see
* CVE-2013-0249.
*
* Restricting protocols is only supported from 7.19.4 upwards.
* Restricting protocols is only supported from 7.19.4 upwards. Note:
* version 7.85.0 deprecates CURLOPT_*PROTOCOLS in favour of a string
* based CURLOPT_*PROTOCOLS_STR API.
*/
#if LIBCURL_VERSION_NUM >= 0x071304
#if LIBCURL_VERSION_NUM >= 0x075500
if (curl_easy_setopt(state->curl,
CURLOPT_PROTOCOLS_STR, PROTOCOLS) ||
curl_easy_setopt(state->curl,
CURLOPT_REDIR_PROTOCOLS_STR, PROTOCOLS)) {
goto err;
}
#elif LIBCURL_VERSION_NUM >= 0x071304
if (curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS) ||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS)) {
goto err;
@ -670,7 +686,12 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
const char *file;
const char *cookie;
const char *cookie_secret;
double d;
/* CURL >= 7.55.0 uses curl_off_t for content length instead of a double */
#if LIBCURL_VERSION_NUM >= 0x073700
curl_off_t cl;
#else
double cl;
#endif
const char *secretid;
const char *protocol_delimiter;
int ret;
@ -797,27 +818,36 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
}
if (curl_easy_perform(state->curl))
goto out;
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
/* CURL 7.55.0 deprecates CURLINFO_CONTENT_LENGTH_DOWNLOAD in favour of
* the *_T version which returns a more sensible type for content length.
*/
#if LIBCURL_VERSION_NUM >= 0x073700
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl)) {
goto out;
}
#else
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl)) {
goto out;
}
#endif
/* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
* know or the size is zero. From 7.19.4 CURL returns -1 if size is not
* known and zero if it is really zero-length file. */
#if LIBCURL_VERSION_NUM >= 0x071304
if (d < 0) {
if (cl < 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Server didn't report file size.");
goto out;
}
#else
if (d <= 0) {
if (cl <= 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Unknown file size or zero-length file.");
goto out;
}
#endif
s->len = d;
s->len = cl;
if ((!strncasecmp(s->url, "http://", strlen("http://"))
|| !strncasecmp(s->url, "https://", strlen("https://")))
@ -850,8 +880,10 @@ out_noclean:
g_free(s->username);
g_free(s->proxyusername);
g_free(s->proxypassword);
curl_drop_all_sockets(s->sockets);
g_hash_table_destroy(s->sockets);
if (s->sockets) {
curl_drop_all_sockets(s->sockets);
g_hash_table_destroy(s->sockets);
}
qemu_opts_del(opts);
return -EINVAL;
}

View File

@ -1738,7 +1738,7 @@ static int handle_aiocb_write_zeroes(void *opaque)
#ifdef CONFIG_FALLOCATE
/* Last resort: we are trying to extend the file with zeroed data. This
* can be done via fallocate(fd, 0) */
len = bdrv_getlength(aiocb->bs);
len = raw_co_getlength(aiocb->bs);
if (s->has_fallocate && len >= 0 && aiocb->aio_offset >= len) {
int ret = do_fallocate(s->fd, 0, aiocb->aio_offset, aiocb->aio_nbytes);
if (ret == 0 || ret != -ENOTSUP) {

View File

@ -141,6 +141,7 @@ block_gen_c = custom_target('block-gen.c',
'../include/block/dirty-bitmap.h',
'../include/block/block_int-io.h',
'../include/block/block-global-state.h',
'../include/sysemu/block-backend-global-state.h',
'../include/sysemu/block-backend-io.h',
'coroutines.h'
),

View File

@ -565,13 +565,13 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
}
/* Create BlockBackend to write to the image */
bs = bdrv_open_blockdev_ref(parallels_opts->file, errp);
bs = bdrv_co_open_blockdev_ref(parallels_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
if (!blk) {
ret = -EPERM;
goto out;
@ -651,8 +651,8 @@ static int coroutine_fn parallels_co_create_opts(BlockDriver *drv,
goto done;
}
bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (bs == NULL) {
ret = -EIO;
goto done;

View File

@ -833,13 +833,13 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
}
/* Create BlockBackend to write to the image */
bs = bdrv_open_blockdev_ref(qcow_opts->file, errp);
bs = bdrv_co_open_blockdev_ref(qcow_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
qcow_blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE,
BLK_PERM_ALL, errp);
qcow_blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE,
BLK_PERM_ALL, errp);
if (!qcow_blk) {
ret = -EPERM;
goto exit;
@ -978,8 +978,8 @@ static int coroutine_fn qcow_co_create_opts(BlockDriver *drv,
goto fail;
}
bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (bs == NULL) {
ret = -EIO;
goto fail;

View File

@ -1617,9 +1617,9 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
if (open_data_file) {
/* Open external data file */
s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
&child_of_bds, BDRV_CHILD_DATA,
true, errp);
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,
&child_of_bds, BDRV_CHILD_DATA,
true, errp);
if (*errp) {
ret = -EINVAL;
goto fail;
@ -1627,9 +1627,10 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
if (!s->data_file && s->image_data_file) {
s->data_file = bdrv_open_child(s->image_data_file, options,
"data-file", bs, &child_of_bds,
BDRV_CHILD_DATA, false, errp);
s->data_file = bdrv_co_open_child(s->image_data_file, options,
"data-file", bs,
&child_of_bds,
BDRV_CHILD_DATA, false, errp);
if (!s->data_file) {
ret = -EINVAL;
goto fail;
@ -3454,7 +3455,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
assert(create_options->driver == BLOCKDEV_DRIVER_QCOW2);
qcow2_opts = &create_options->u.qcow2;
bs = bdrv_open_blockdev_ref(qcow2_opts->file, errp);
bs = bdrv_co_open_blockdev_ref(qcow2_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
@ -3596,7 +3597,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
ret = -EINVAL;
goto out;
}
data_bs = bdrv_open_blockdev_ref(qcow2_opts->data_file, errp);
data_bs = bdrv_co_open_blockdev_ref(qcow2_opts->data_file, errp);
if (data_bs == NULL) {
ret = -EIO;
goto out;
@ -3629,8 +3630,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
}
/* Create BlockBackend to write to the image */
blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
if (!blk) {
ret = -EPERM;
goto out;
@ -3712,9 +3713,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
if (data_bs) {
qdict_put_str(options, "data-file", data_bs->node_name);
}
blk = blk_new_open(NULL, NULL, options,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH,
errp);
blk = blk_co_new_open(NULL, NULL, options,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH,
errp);
if (blk == NULL) {
ret = -EIO;
goto out;
@ -3793,9 +3794,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
if (data_bs) {
qdict_put_str(options, "data-file", data_bs->node_name);
}
blk = blk_new_open(NULL, NULL, options,
BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO,
errp);
blk = blk_co_new_open(NULL, NULL, options,
BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO,
errp);
if (blk == NULL) {
ret = -EIO;
goto out;
@ -3877,8 +3878,8 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv,
goto finish;
}
bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (bs == NULL) {
ret = -EIO;
goto finish;
@ -3892,9 +3893,9 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv,
goto finish;
}
data_bs = bdrv_open(val, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
errp);
data_bs = bdrv_co_open(val, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
errp);
if (data_bs == NULL) {
ret = -EIO;
goto finish;

View File

@ -676,13 +676,13 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
}
/* Create BlockBackend to write to the image */
bs = bdrv_open_blockdev_ref(qed_opts->file, errp);
bs = bdrv_co_open_blockdev_ref(qed_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
if (!blk) {
ret = -EPERM;
goto out;
@ -783,8 +783,8 @@ static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv,
goto fail;
}
bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (bs == NULL) {
ret = -EIO;
goto fail;

View File

@ -800,14 +800,14 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
}
/* Create BlockBackend to write to the image */
bs_file = bdrv_open_blockdev_ref(vdi_opts->file, errp);
bs_file = bdrv_co_open_blockdev_ref(vdi_opts->file, errp);
if (!bs_file) {
ret = -EIO;
goto exit;
}
blk = blk_new_with_bs(bs_file, BLK_PERM_WRITE | BLK_PERM_RESIZE,
BLK_PERM_ALL, errp);
blk = blk_co_new_with_bs(bs_file, BLK_PERM_WRITE | BLK_PERM_RESIZE,
BLK_PERM_ALL, errp);
if (!blk) {
ret = -EPERM;
goto exit;
@ -940,8 +940,8 @@ static int coroutine_fn vdi_co_create_opts(BlockDriver *drv,
goto done;
}
bs_file = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs_file = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (!bs_file) {
ret = -EIO;
goto done;

View File

@ -1991,13 +1991,13 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
}
/* Create BlockBackend to write to the image */
bs = bdrv_open_blockdev_ref(vhdx_opts->file, errp);
bs = bdrv_co_open_blockdev_ref(vhdx_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
if (!blk) {
ret = -EPERM;
goto delete_and_exit;
@ -2090,8 +2090,8 @@ static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv,
goto fail;
}
bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (bs == NULL) {
ret = -EIO;
goto fail;

View File

@ -2299,9 +2299,9 @@ static int coroutine_fn vmdk_create_extent(const char *filename,
goto exit;
}
blk = blk_new_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
errp);
blk = blk_co_new_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
errp);
if (blk == NULL) {
ret = -EIO;
goto exit;
@ -2518,8 +2518,8 @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
}
assert(full_backing);
backing = blk_new_open(full_backing, NULL, NULL,
BDRV_O_NO_BACKING, errp);
backing = blk_co_new_open(full_backing, NULL, NULL,
BDRV_O_NO_BACKING, errp);
g_free(full_backing);
if (backing == NULL) {
ret = -EIO;
@ -2781,7 +2781,7 @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
BlockdevCreateOptionsVmdk *opts = opaque;
if (idx == 0) {
bs = bdrv_open_blockdev_ref(opts->file, errp);
bs = bdrv_co_open_blockdev_ref(opts->file, errp);
} else {
int i;
BlockdevRefList *list = opts->extents;
@ -2796,14 +2796,16 @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
error_setg(errp, "Extent [%d] not specified", idx - 1);
return NULL;
}
bs = bdrv_open_blockdev_ref(list->value, errp);
bs = bdrv_co_open_blockdev_ref(list->value, errp);
}
if (!bs) {
return NULL;
}
blk = blk_new_with_bs(bs,
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
BLK_PERM_ALL, errp);
blk = blk_co_new_with_bs(bs,
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
BLK_PERM_RESIZE,
BLK_PERM_ALL,
errp);
if (!blk) {
return NULL;
}

View File

@ -1005,13 +1005,13 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
}
/* Create BlockBackend to write to the image */
bs = bdrv_open_blockdev_ref(vpc_opts->file, errp);
bs = bdrv_co_open_blockdev_ref(vpc_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
if (!blk) {
ret = -EPERM;
goto out;
@ -1117,8 +1117,8 @@ static int coroutine_fn vpc_co_create_opts(BlockDriver *drv,
goto fail;
}
bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
bs = bdrv_co_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (bs == NULL) {
ret = -EIO;
goto fail;

View File

@ -36,6 +36,7 @@ extern char **environ;
#include "target_os_signal.h"
#include "target.h"
#include "exec/gdbstub.h"
#include "qemu/clang-tsa.h"
/*
* This struct is used to hold certain information about the image. Basically,
@ -234,8 +235,8 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk;
extern abi_ulong mmap_next_start;
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
void mmap_fork_start(void);
void mmap_fork_end(int child);
void TSA_NO_TSA mmap_fork_start(void);
void TSA_NO_TSA mmap_fork_end(int child);
/* main.c */
extern char qemu_proc_pathname[];

1
configure vendored
View File

@ -1184,6 +1184,7 @@ add_to warn_flags -Wendif-labels
add_to warn_flags -Wexpansion-to-defined
add_to warn_flags -Wimplicit-fallthrough=2
add_to warn_flags -Wmissing-format-attribute
add_to warn_flags -Wthread-safety
nowarn_flags=
add_to nowarn_flags -Wno-initializer-overrides

View File

@ -54,6 +54,20 @@
#define co_wrapper_bdrv_rdlock no_coroutine_fn
#define co_wrapper_mixed_bdrv_rdlock no_coroutine_fn coroutine_mixed_fn
/*
* no_co_wrapper: Function specifier used by block-coroutine-wrapper.py
*
* Function specifier which does nothing but mark functions to be generated by
* scripts/block-coroutine-wrapper.py.
*
* A no_co_wrapper function declaration creates a coroutine_fn wrapper around
* functions that must not be called in coroutine context. It achieves this by
* scheduling a BH in the bottom half that runs the respective non-coroutine
* function. The coroutine yields after scheduling the BH and is reentered when
* the wrapped function returns.
*/
#define no_co_wrapper
#include "block/blockjob.h"
/* block.c */

View File

@ -77,16 +77,26 @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
int flags, Error **errp);
int bdrv_drop_filter(BlockDriverState *bs, Error **errp);
BdrvChild *bdrv_open_child(const char *filename,
QDict *options, const char *bdref_key,
BlockDriverState *parent,
const BdrvChildClass *child_class,
BdrvChildRole child_role,
bool allow_none, Error **errp);
BdrvChild * no_coroutine_fn
bdrv_open_child(const char *filename, QDict *options, const char *bdref_key,
BlockDriverState *parent, const BdrvChildClass *child_class,
BdrvChildRole child_role, bool allow_none, Error **errp);
BdrvChild * coroutine_fn no_co_wrapper
bdrv_co_open_child(const char *filename, QDict *options, const char *bdref_key,
BlockDriverState *parent, const BdrvChildClass *child_class,
BdrvChildRole child_role, bool allow_none, Error **errp);
int bdrv_open_file_child(const char *filename,
QDict *options, const char *bdref_key,
BlockDriverState *parent, Error **errp);
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
BlockDriverState * no_coroutine_fn
bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
BlockDriverState * coroutine_fn no_co_wrapper
bdrv_co_open_blockdev_ref(BlockdevRef *ref, Error **errp);
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
Error **errp);
int bdrv_set_backing_hd_drained(BlockDriverState *bs,
@ -94,8 +104,15 @@ int bdrv_set_backing_hd_drained(BlockDriverState *bs,
Error **errp);
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
const char *bdref_key, Error **errp);
BlockDriverState *bdrv_open(const char *filename, const char *reference,
QDict *options, int flags, Error **errp);
BlockDriverState * no_coroutine_fn
bdrv_open(const char *filename, const char *reference, QDict *options,
int flags, Error **errp);
BlockDriverState * coroutine_fn no_co_wrapper
bdrv_co_open(const char *filename, const char *reference,
QDict *options, int flags, Error **errp);
BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv,
const char *node_name,
QDict *options, int flags,

View File

@ -25,6 +25,7 @@
#include "exec/cpu_ldst.h"
#endif
#include "qemu/interval-tree.h"
#include "qemu/clang-tsa.h"
/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS
@ -759,8 +760,8 @@ static inline tb_page_addr_t get_page_addr_code(CPUArchState *env,
}
#if defined(CONFIG_USER_ONLY)
void mmap_lock(void);
void mmap_unlock(void);
void TSA_NO_TSA mmap_lock(void);
void TSA_NO_TSA mmap_unlock(void);
bool have_mmap_lock(void);
/**

View File

@ -330,7 +330,7 @@ bool hbitmap_next_dirty_area(const HBitmap *hb, int64_t start, int64_t end,
int64_t *dirty_start, int64_t *dirty_count);
/*
* bdrv_dirty_bitmap_status:
* hbitmap_status:
* @hb: The HBitmap to operate on
* @start: The bit to start from
* @count: Number of bits to proceed

View File

@ -3,6 +3,7 @@
#include "qemu/processor.h"
#include "qemu/atomic.h"
#include "qemu/clang-tsa.h"
typedef struct QemuCond QemuCond;
typedef struct QemuSemaphore QemuSemaphore;
@ -24,9 +25,12 @@ typedef struct QemuThread QemuThread;
void qemu_mutex_init(QemuMutex *mutex);
void qemu_mutex_destroy(QemuMutex *mutex);
int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line);
void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line);
void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line);
int TSA_NO_TSA qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file,
const int line);
void TSA_NO_TSA qemu_mutex_lock_impl(QemuMutex *mutex, const char *file,
const int line);
void TSA_NO_TSA qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file,
const int line);
void qemu_rec_mutex_init(QemuRecMutex *mutex);
void qemu_rec_mutex_destroy(QemuRecMutex *mutex);
@ -153,8 +157,8 @@ void qemu_cond_destroy(QemuCond *cond);
*/
void qemu_cond_signal(QemuCond *cond);
void qemu_cond_broadcast(QemuCond *cond);
void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex,
const char *file, const int line);
void TSA_NO_TSA qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex,
const char *file, const int line);
bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms,
const char *file, const int line);

View File

@ -23,10 +23,23 @@
*/
BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm);
BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
uint64_t shared_perm, Error **errp);
BlockBackend *blk_new_open(const char *filename, const char *reference,
QDict *options, int flags, Error **errp);
BlockBackend * no_coroutine_fn
blk_new_with_bs(BlockDriverState *bs, uint64_t perm, uint64_t shared_perm,
Error **errp);
BlockBackend * coroutine_fn no_co_wrapper
blk_co_new_with_bs(BlockDriverState *bs, uint64_t perm, uint64_t shared_perm,
Error **errp);
BlockBackend * no_coroutine_fn
blk_new_open(const char *filename, const char *reference, QDict *options,
int flags, Error **errp);
BlockBackend * coroutine_fn no_co_wrapper
blk_co_new_open(const char *filename, const char *reference, QDict *options,
int flags, Error **errp);
int blk_get_refcnt(BlockBackend *blk);
void blk_ref(BlockBackend *blk);
void blk_unref(BlockBackend *blk);

View File

@ -63,8 +63,8 @@ class ParamDecl:
class FuncDecl:
def __init__(self, return_type: str, name: str, args: str,
variant: str) -> None:
def __init__(self, wrapper_type: str, return_type: str, name: str,
args: str, variant: str) -> None:
self.return_type = return_type.strip()
self.name = name.strip()
self.struct_name = snake_to_camel(self.name)
@ -72,8 +72,21 @@ class FuncDecl:
self.create_only_co = 'mixed' not in variant
self.graph_rdlock = 'bdrv_rdlock' in variant
subsystem, subname = self.name.split('_', 1)
self.co_name = f'{subsystem}_co_{subname}'
self.wrapper_type = wrapper_type
if wrapper_type == 'co':
subsystem, subname = self.name.split('_', 1)
self.target_name = f'{subsystem}_co_{subname}'
else:
assert wrapper_type == 'no_co'
subsystem, co_infix, subname = self.name.split('_', 2)
if co_infix != 'co':
raise ValueError(f"Invalid no_co function name: {self.name}")
if not self.create_only_co:
raise ValueError(f"no_co function can't be mixed: {self.name}")
if self.graph_rdlock:
raise ValueError(f"no_co function can't be rdlock: {self.name}")
self.target_name = f'{subsystem}_{subname}'
t = self.args[0].type
if t == 'BlockDriverState *':
@ -105,7 +118,8 @@ class FuncDecl:
# Match wrappers declared with a co_wrapper mark
func_decl_re = re.compile(r'^(?P<return_type>[a-zA-Z][a-zA-Z0-9_]* [\*]?)'
r'\s*co_wrapper'
r'(\s*coroutine_fn)?'
r'\s*(?P<wrapper_type>(no_)?co)_wrapper'
r'(?P<variant>(_[a-z][a-z0-9_]*)?)\s*'
r'(?P<wrapper_name>[a-z][a-z0-9_]*)'
r'\((?P<args>[^)]*)\);$', re.MULTILINE)
@ -113,7 +127,8 @@ func_decl_re = re.compile(r'^(?P<return_type>[a-zA-Z][a-zA-Z0-9_]* [\*]?)'
def func_decl_iter(text: str) -> Iterator:
for m in func_decl_re.finditer(text):
yield FuncDecl(return_type=m.group('return_type'),
yield FuncDecl(wrapper_type=m.group('wrapper_type'),
return_type=m.group('return_type'),
name=m.group('wrapper_name'),
args=m.group('args'),
variant=m.group('variant'))
@ -133,7 +148,7 @@ def create_mixed_wrapper(func: FuncDecl) -> str:
"""
Checks if we are already in coroutine
"""
name = func.co_name
name = func.target_name
struct_name = func.struct_name
graph_assume_lock = 'assume_graph_lock();' if func.graph_rdlock else ''
@ -163,7 +178,7 @@ def create_co_wrapper(func: FuncDecl) -> str:
"""
Assumes we are not in coroutine, and creates one
"""
name = func.co_name
name = func.target_name
struct_name = func.struct_name
return f"""\
{func.return_type} {func.name}({ func.gen_list('{decl}') })
@ -183,10 +198,11 @@ def create_co_wrapper(func: FuncDecl) -> str:
}}"""
def gen_wrapper(func: FuncDecl) -> str:
def gen_co_wrapper(func: FuncDecl) -> str:
assert not '_co_' in func.name
assert func.wrapper_type == 'co'
name = func.co_name
name = func.target_name
struct_name = func.struct_name
graph_lock=''
@ -225,11 +241,56 @@ static void coroutine_fn {name}_entry(void *opaque)
{creation_function(func)}"""
def gen_no_co_wrapper(func: FuncDecl) -> str:
assert '_co_' in func.name
assert func.wrapper_type == 'no_co'
name = func.target_name
struct_name = func.struct_name
return f"""\
/*
* Wrappers for {name}
*/
typedef struct {struct_name} {{
Coroutine *co;
{func.return_field}
{ func.gen_block(' {decl};') }
}} {struct_name};
static void {name}_bh(void *opaque)
{{
{struct_name} *s = opaque;
{func.get_result}{name}({ func.gen_list('s->{name}') });
aio_co_wake(s->co);
}}
{func.return_type} coroutine_fn {func.name}({ func.gen_list('{decl}') })
{{
{struct_name} s = {{
.co = qemu_coroutine_self(),
{ func.gen_block(' .{name} = {name},') }
}};
assert(qemu_in_coroutine());
aio_bh_schedule_oneshot(qemu_get_aio_context(), {name}_bh, &s);
qemu_coroutine_yield();
{func.ret}
}}"""
def gen_wrappers(input_code: str) -> str:
res = ''
for func in func_decl_iter(input_code):
res += '\n\n\n'
res += gen_wrapper(func)
if func.wrapper_type == 'co':
res += gen_co_wrapper(func)
else:
res += gen_no_co_wrapper(func)
return res

View File

@ -331,7 +331,7 @@ bool hbitmap_status(const HBitmap *hb, int64_t start, int64_t count,
assert(next_zero > start);
*pnum = next_zero - start;
return false;
return true;
}
bool hbitmap_empty(const HBitmap *hb)

View File

@ -223,7 +223,7 @@ void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, con
error_exit(err, __func__);
}
static bool
static bool TSA_NO_TSA
qemu_cond_timedwait_ts(QemuCond *cond, QemuMutex *mutex, struct timespec *ts,
const char *file, const int line)
{