Block layer patches

- Cleanup bs->backing and bs->file handling
 - Refactor bdrv_try_set_aio_context using transactions
 - Changes for improved coroutine_fn consistency
 - vhost-user-blk: fix the resize crash
 - io_uring: Use of io_uring_register_ring_fd() led to breakage, revert
 - vvfat: Fix some problems with r/w mode
 - Code cleanup
 - MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmNazhIRHGt3b2xmQHJl
 ZGhhdC5jb20ACgkQfwmycsiPL9ZyTw/8Dfck/SuxfyeLlnQItkjaV4cnqWOU8vHs
 9x0KhlptCs+HXdF/3iicpA0lHojn7mNnbdFGjPRY4E0LriQv91TQ5ycdEmrseFPf
 sgeQlgdKCVU/pHjZ2wYarm2pE43Cx85a5xuufmw+7w49dNNZn14l4t+DgviuClVM
 nuVaogfZFbYyetre+Qd2TgLl+gJ+0d4o7Zs5lSWLrT8t0L9AGkcWPA7Nrbl6loIE
 dOautV4G7jLjuMiCeJZOGcnuRVe3gCQ5rCGBFzzH4DUtz4BmiYx4hd3LMEsP0PMM
 CrsfDZS04Ztybl9M7TmJuwkAm1gx1JDMOuJuh18lbJocIOBvhkKKxY2wI5LIdZVI
 ZntmU36RowkX+GGu/PYpYyMjBDClJppZCl7vnjyLYsVt6r0Vu6SmlHpJhcRYabhe
 96Kv1LXH9A6+ogKPU3Layw6JGjg01GNr1ALuT7PO3pGto/JshmOuBEJJDucoF84M
 5AfxFCohMROVldwblA6M0eKnlQBgtr5BvtgbV54BBo88VlFJgDJFQn7R09cTFUEo
 UwaJoS+nIaiZ0bQQVZhZloVppUaTdVJojzfVRCZZctga96/tu1HSFnGLnbEFpUN3
 KOf+XnVNS6Ro+nPSDf9bMjbIom2JicGFfV+6yMgIoxY/d5UA2dTZfefil4TAlSod
 6PsTgg+jrm8=
 =/Fw0
 -----END PGP SIGNATURE-----

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

Block layer patches

- Cleanup bs->backing and bs->file handling
- Refactor bdrv_try_set_aio_context using transactions
- Changes for improved coroutine_fn consistency
- vhost-user-blk: fix the resize crash
- io_uring: Use of io_uring_register_ring_fd() led to breakage, revert
- vvfat: Fix some problems with r/w mode
- Code cleanup
- MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmNazhIRHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9ZyTw/8Dfck/SuxfyeLlnQItkjaV4cnqWOU8vHs
# 9x0KhlptCs+HXdF/3iicpA0lHojn7mNnbdFGjPRY4E0LriQv91TQ5ycdEmrseFPf
# sgeQlgdKCVU/pHjZ2wYarm2pE43Cx85a5xuufmw+7w49dNNZn14l4t+DgviuClVM
# nuVaogfZFbYyetre+Qd2TgLl+gJ+0d4o7Zs5lSWLrT8t0L9AGkcWPA7Nrbl6loIE
# dOautV4G7jLjuMiCeJZOGcnuRVe3gCQ5rCGBFzzH4DUtz4BmiYx4hd3LMEsP0PMM
# CrsfDZS04Ztybl9M7TmJuwkAm1gx1JDMOuJuh18lbJocIOBvhkKKxY2wI5LIdZVI
# ZntmU36RowkX+GGu/PYpYyMjBDClJppZCl7vnjyLYsVt6r0Vu6SmlHpJhcRYabhe
# 96Kv1LXH9A6+ogKPU3Layw6JGjg01GNr1ALuT7PO3pGto/JshmOuBEJJDucoF84M
# 5AfxFCohMROVldwblA6M0eKnlQBgtr5BvtgbV54BBo88VlFJgDJFQn7R09cTFUEo
# UwaJoS+nIaiZ0bQQVZhZloVppUaTdVJojzfVRCZZctga96/tu1HSFnGLnbEFpUN3
# KOf+XnVNS6Ro+nPSDf9bMjbIom2JicGFfV+6yMgIoxY/d5UA2dTZfefil4TAlSod
# 6PsTgg+jrm8=
# =/Fw0
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 27 Oct 2022 14:29:38 EDT
# 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: (58 commits)
  block/block-backend: blk_set_enable_write_cache is IO_CODE
  monitor: switch to *_co_* functions
  vmdk: switch to *_co_* functions
  vhdx: switch to *_co_* functions
  vdi: switch to *_co_* functions
  qed: switch to *_co_* functions
  qcow2: switch to *_co_* functions
  qcow: switch to *_co_* functions
  parallels: switch to *_co_* functions
  mirror: switch to *_co_* functions
  block: switch to *_co_* functions
  commit: switch to *_co_* functions
  vmdk: manually add more coroutine_fn annotations
  qcow2: manually add more coroutine_fn annotations
  qcow: manually add more coroutine_fn annotations
  blkdebug: add missing coroutine_fn annotation for indirect-called functions
  qcow2: add coroutine_fn annotation for indirect-called functions
  block: add missing coroutine_fn annotation to BlockDriverState callbacks
  coroutine-io: add missing coroutine_fn annotation to prototypes
  coroutine-lock: add missing coroutine_fn annotation to prototypes
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2022-10-30 15:15:12 -04:00
commit d5ab9490cd
63 changed files with 1002 additions and 1001 deletions

View file

@ -2509,6 +2509,8 @@ S: Supported
F: block*
F: block/
F: hw/block/
F: qapi/block*.json
F: qapi/transaction.json
F: include/block/
F: include/sysemu/block-*.h
F: qemu-img*
@ -2583,16 +2585,6 @@ F: include/qemu/co-shared-resource.h
T: git https://gitlab.com/jsnow/qemu.git jobs
T: git https://gitlab.com/vsementsov/qemu.git block
Block QAPI, monitor, command line
M: Markus Armbruster <armbru@redhat.com>
S: Supported
F: blockdev.c
F: blockdev-hmp-cmds.c
F: block/qapi.c
F: qapi/block*.json
F: qapi/transaction.json
T: git https://repo.or.cz/qemu/armbru.git block-next
Compute Express Link
M: Ben Widawsky <ben.widawsky@intel.com>
M: Jonathan Cameron <jonathan.cameron@huawei.com>

883
block.c

File diff suppressed because it is too large Load diff

View file

@ -309,7 +309,7 @@ static void coroutine_fn backup_pause(Job *job)
}
}
static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
static void backup_set_speed(BlockJob *job, int64_t speed)
{
BackupBlockJob *s = container_of(job, BackupBlockJob, common);

View file

@ -503,12 +503,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Open the image file */
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
ret = -EINVAL;
ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image",
bs, errp);
if (ret < 0) {
goto out;
}
@ -672,7 +669,7 @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
}
static int blkdebug_co_flush(BlockDriverState *bs)
static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
{
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);

View file

@ -155,11 +155,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Open the file */
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
errp);
if (!bs->file) {
ret = -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
goto fail;
}
@ -257,10 +254,6 @@ fail_log:
s->log_file = NULL;
}
fail:
if (ret < 0) {
bdrv_unref_child(bs, bs->file);
bs->file = NULL;
}
qemu_opts_del(opts);
return ret;
}

View file

@ -26,11 +26,8 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
int ret;
/* Open the image file */
bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
ret = -EINVAL;
ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
if (ret < 0) {
goto fail;
}

View file

@ -122,12 +122,9 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Open the raw file */
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
ret = -EINVAL;
ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw",
bs, errp);
if (ret < 0) {
goto fail;
}

View file

@ -134,10 +134,9 @@ static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter);
static void blk_root_change_media(BdrvChild *child, bool load);
static void blk_root_resize(BdrvChild *child);
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
GSList **ignore, Error **errp);
static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
GSList **ignore);
static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
GHashTable *visited, Transaction *tran,
Error **errp);
static char *blk_root_get_parent_desc(BdrvChild *child)
{
@ -334,8 +333,7 @@ static const BdrvChildClass child_root = {
.attach = blk_root_attach,
.detach = blk_root_detach,
.can_set_aio_ctx = blk_root_can_set_aio_ctx,
.set_aio_ctx = blk_root_set_aio_ctx,
.change_aio_ctx = blk_root_change_aio_ctx,
.get_parent_aio_context = blk_root_get_parent_aio_context,
};
@ -1946,7 +1944,7 @@ bool blk_enable_write_cache(BlockBackend *blk)
void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
{
GLOBAL_STATE_CODE();
IO_CODE();
blk->enable_write_cache = wce;
}
@ -2149,8 +2147,11 @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
bdrv_ref(bs);
if (update_root_node) {
ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
errp);
/*
* update_root_node MUST be false for blk_root_set_aio_ctx_commit(),
* as we are already in the commit function of a transaction.
*/
ret = bdrv_try_change_aio_context(bs, new_context, blk->root, errp);
if (ret < 0) {
bdrv_unref(bs);
return ret;
@ -2177,31 +2178,52 @@ int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
return blk_do_set_aio_context(blk, new_context, true, errp);
}
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
GSList **ignore, Error **errp)
typedef struct BdrvStateBlkRootContext {
AioContext *new_ctx;
BlockBackend *blk;
} BdrvStateBlkRootContext;
static void blk_root_set_aio_ctx_commit(void *opaque)
{
BlockBackend *blk = child->opaque;
BdrvStateBlkRootContext *s = opaque;
BlockBackend *blk = s->blk;
if (blk->allow_aio_context_change) {
return true;
}
/* Only manually created BlockBackends that are not attached to anything
* can change their AioContext without updating their user. */
if (!blk->name || blk->dev) {
/* TODO Add BB name/QOM path */
error_setg(errp, "Cannot change iothread of active block backend");
return false;
}
return true;
blk_do_set_aio_context(blk, s->new_ctx, false, &error_abort);
}
static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
GSList **ignore)
static TransactionActionDrv set_blk_root_context = {
.commit = blk_root_set_aio_ctx_commit,
.clean = g_free,
};
static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
GHashTable *visited, Transaction *tran,
Error **errp)
{
BlockBackend *blk = child->opaque;
blk_do_set_aio_context(blk, ctx, false, &error_abort);
BdrvStateBlkRootContext *s;
if (!blk->allow_aio_context_change) {
/*
* Manually created BlockBackends (those with a name) that are not
* attached to anything can change their AioContext without updating
* their user; return an error for others.
*/
if (!blk->name || blk->dev) {
/* TODO Add BB name/QOM path */
error_setg(errp, "Cannot change iothread of active block backend");
return false;
}
}
s = g_new(BdrvStateBlkRootContext, 1);
*s = (BdrvStateBlkRootContext) {
.new_ctx = ctx,
.blk = blk,
};
tran_add(tran, &set_blk_root_context, s);
return true;
}
void blk_add_aio_context_notifier(BlockBackend *blk,

View file

@ -110,10 +110,9 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
ret = bdrv_pread(bs->file, 0, sizeof(bochs), &bochs, 0);

View file

@ -71,10 +71,9 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
/* read header */

View file

@ -135,7 +135,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
}
if (base_len < len) {
ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
ret = blk_co_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
if (ret) {
return ret;
}
@ -238,6 +238,7 @@ static BlockDriver bdrv_commit_top = {
.bdrv_child_perm = bdrv_commit_top_child_perm,
.is_filter = true,
.filtered_child_is_backing = true,
};
void commit_start(const char *job_id, BlockDriverState *bs,

View file

@ -412,6 +412,7 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
int64_t cluster_size;
g_autoptr(BlockdevOptions) full_opts = NULL;
BlockdevOptionsCbw *opts;
int ret;
full_opts = cbw_parse_options(options, errp);
if (!full_opts) {
@ -420,11 +421,9 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
assert(full_opts->driver == BLOCKDEV_DRIVER_COPY_BEFORE_WRITE);
opts = &full_opts->u.copy_before_write;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds,

View file

@ -41,12 +41,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
BDRVStateCOR *state = bs->opaque;
/* Find a bottom node name, if any */
const char *bottom_node = qdict_get_try_str(options, "bottom");
int ret;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
bs->supported_read_flags = BDRV_REQ_PREFETCH;

View file

@ -261,15 +261,14 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
{
BlockCrypto *crypto = bs->opaque;
QemuOpts *opts = NULL;
int ret = -EINVAL;
int ret;
QCryptoBlockOpenOptions *open_opts = NULL;
unsigned int cflags = 0;
QDict *cryptoopts = NULL;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
bs->supported_write_flags = BDRV_REQ_FUA &
@ -277,6 +276,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
ret = -EINVAL;
goto cleanup;
}
@ -285,6 +285,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
open_opts = block_crypto_open_opts_init(cryptoopts, errp);
if (!open_opts) {
ret = -EINVAL;
goto cleanup;
}

View file

@ -440,10 +440,9 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
block_module_load_one("dmg-bz2");

View file

@ -129,7 +129,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
/* Ignore errors with fixed-iothread=false */
set_context_errp = fixed_iothread ? errp : NULL;
ret = bdrv_try_set_aio_context(bs, new_ctx, set_context_errp);
ret = bdrv_try_change_aio_context(bs, new_ctx, NULL, set_context_errp);
if (ret == 0) {
aio_context_release(ctx);
aio_context_acquire(new_ctx);

View file

@ -30,11 +30,9 @@
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
int ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {

View file

@ -2744,8 +2744,8 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
return 1;
}
ret = bdrv_common_block_status_above(bs, NULL, false, false, offset,
bytes, &pnum, NULL, NULL, NULL);
ret = bdrv_co_common_block_status_above(bs, NULL, false, false, offset,
bytes, &pnum, NULL, NULL, NULL);
if (ret < 0) {
return ret;
@ -2754,8 +2754,8 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
return (pnum == bytes) && (ret & BDRV_BLOCK_ZERO);
}
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
int64_t bytes, int64_t *pnum)
int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
int64_t *pnum)
{
int ret;
int64_t dummy;

View file

@ -11,7 +11,6 @@
#include "qemu/osdep.h"
#include <liburing.h>
#include "block/aio.h"
#include "qemu/error-report.h"
#include "qemu/queue.h"
#include "block/block.h"
#include "block/raw-aio.h"
@ -19,7 +18,6 @@
#include "qapi/error.h"
#include "trace.h"
/* io_uring ring size */
#define MAX_ENTRIES 128
@ -432,17 +430,8 @@ LuringState *luring_init(Error **errp)
}
ioq_init(&s->io_q);
#ifdef CONFIG_LIBURING_REGISTER_RING_FD
if (io_uring_register_ring_fd(&s->ring) < 0) {
/*
* Only warn about this error: we will fallback to the non-optimized
* io_uring operations.
*/
warn_report("failed to register linux io_uring ring file descriptor");
}
#endif
return s;
}
void luring_cleanup(LuringState *s)

View file

@ -922,8 +922,8 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
* active layer. */
if (s->base == blk_bs(s->target)) {
if (s->bdev_length > target_length) {
ret = blk_truncate(s->target, s->bdev_length, false,
PREALLOC_MODE_OFF, 0, NULL);
ret = blk_co_truncate(s->target, s->bdev_length, false,
PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0) {
goto immediate_exit;
}
@ -1589,6 +1589,7 @@ static BlockDriver bdrv_mirror_top = {
.bdrv_child_perm = bdrv_mirror_top_child_perm,
.is_filter = true,
.filtered_child_is_backing = true,
};
static BlockJob *mirror_start_job(

View file

@ -489,7 +489,7 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, err);
}
void hmp_block_resize(Monitor *mon, const QDict *qdict)
void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_str(qdict, "device");
int64_t size = qdict_get_int(qdict, "size");

View file

@ -418,7 +418,11 @@ static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts,
int flags, int open_flags, Error **errp)
{
int64_t ret = -EINVAL;
#ifdef _WIN32
struct __stat64 st;
#else
struct stat st;
#endif
char *file = NULL, *strp = NULL;
qemu_mutex_init(&client->mutex);
@ -781,7 +785,11 @@ static int nfs_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
NFSClient *client = state->bs->opaque;
#ifdef _WIN32
struct __stat64 st;
#else
struct stat st;
#endif
int ret = 0;
if (state->flags & BDRV_O_RDWR && bdrv_is_read_only(state->bs)) {

View file

@ -205,18 +205,18 @@ static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
* force the safer-but-slower fallocate.
*/
if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
ret = bdrv_truncate(bs->file,
(s->data_end + space) << BDRV_SECTOR_BITS,
false, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE,
NULL);
ret = bdrv_co_truncate(bs->file,
(s->data_end + space) << BDRV_SECTOR_BITS,
false, PREALLOC_MODE_OFF,
BDRV_REQ_ZERO_WRITE, NULL);
if (ret == -ENOTSUP) {
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
}
}
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
ret = bdrv_pwrite_zeroes(bs->file,
s->data_end << BDRV_SECTOR_BITS,
space << BDRV_SECTOR_BITS, 0);
ret = bdrv_co_pwrite_zeroes(bs->file,
s->data_end << BDRV_SECTOR_BITS,
space << BDRV_SECTOR_BITS, 0);
}
if (ret < 0) {
return ret;
@ -278,8 +278,8 @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
if (off + to_write > s->header_size) {
to_write = s->header_size - off;
}
ret = bdrv_pwrite(bs->file, off, to_write, (uint8_t *)s->header + off,
0);
ret = bdrv_co_pwrite(bs->file, off, to_write,
(uint8_t *)s->header + off, 0);
if (ret < 0) {
qemu_co_mutex_unlock(&s->lock);
return ret;
@ -503,8 +503,8 @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
* In order to really repair the image, we must shrink it.
* That means we have to pass exact=true.
*/
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
PREALLOC_MODE_OFF, 0, &local_err);
ret = bdrv_co_truncate(bs->file, res->image_end_offset, true,
PREALLOC_MODE_OFF, 0, &local_err);
if (ret < 0) {
error_report_err(local_err);
res->check_errors++;
@ -599,12 +599,12 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
memset(tmp, 0, sizeof(tmp));
memcpy(tmp, &header, sizeof(header));
ret = blk_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
ret = blk_co_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
if (ret < 0) {
goto exit;
}
ret = blk_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
(bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
ret = blk_co_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
(bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
if (ret < 0) {
goto exit;
}
@ -736,10 +736,9 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
Error *local_err = NULL;
char *buf;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);

View file

@ -134,6 +134,7 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVPreallocateState *s = bs->opaque;
int ret;
/*
* s->data_end and friends should be initialized on permission update.
@ -141,11 +142,9 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
*/
s->file_end = s->zero_start = s->data_end = -EINVAL;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) {

View file

@ -92,7 +92,8 @@ typedef struct BDRVQcowState {
static QemuOptsList qcow_create_opts;
static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
static int coroutine_fn decompress_cluster(BlockDriverState *bs,
uint64_t cluster_offset);
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
@ -121,10 +122,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
encryptfmt = qdict_get_try_str(encryptopts, "format");
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
ret = -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
goto fail;
}
@ -351,10 +350,11 @@ static int qcow_reopen_prepare(BDRVReopenState *state,
* return 0 if not allocated, 1 if *result is assigned, and negative
* errno on failure.
*/
static int get_cluster_offset(BlockDriverState *bs,
uint64_t offset, int allocate,
int compressed_size,
int n_start, int n_end, uint64_t *result)
static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
uint64_t offset, int allocate,
int compressed_size,
int n_start, int n_end,
uint64_t *result)
{
BDRVQcowState *s = bs->opaque;
int min_index, i, j, l1_index, l2_index, ret;
@ -381,9 +381,9 @@ static int get_cluster_offset(BlockDriverState *bs,
s->l1_table[l1_index] = l2_offset;
tmp = cpu_to_be64(l2_offset);
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
ret = bdrv_pwrite_sync(bs->file,
s->l1_table_offset + l1_index * sizeof(tmp),
sizeof(tmp), &tmp, 0);
ret = bdrv_co_pwrite_sync(bs->file,
s->l1_table_offset + l1_index * sizeof(tmp),
sizeof(tmp), &tmp, 0);
if (ret < 0) {
return ret;
}
@ -414,14 +414,14 @@ static int get_cluster_offset(BlockDriverState *bs,
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
if (new_l2_table) {
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
ret = bdrv_pwrite_sync(bs->file, l2_offset,
s->l2_size * sizeof(uint64_t), l2_table, 0);
ret = bdrv_co_pwrite_sync(bs->file, l2_offset,
s->l2_size * sizeof(uint64_t), l2_table, 0);
if (ret < 0) {
return ret;
}
} else {
ret = bdrv_pread(bs->file, l2_offset, s->l2_size * sizeof(uint64_t),
l2_table, 0);
ret = bdrv_co_pread(bs->file, l2_offset,
s->l2_size * sizeof(uint64_t), l2_table, 0);
if (ret < 0) {
return ret;
}
@ -453,8 +453,8 @@ static int get_cluster_offset(BlockDriverState *bs,
cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
/* write the cluster content */
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_size,
s->cluster_cache, 0);
ret = bdrv_co_pwrite(bs->file, cluster_offset, s->cluster_size,
s->cluster_cache, 0);
if (ret < 0) {
return ret;
}
@ -469,8 +469,9 @@ static int get_cluster_offset(BlockDriverState *bs,
if (cluster_offset + s->cluster_size > INT64_MAX) {
return -E2BIG;
}
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
false, PREALLOC_MODE_OFF, 0, NULL);
ret = bdrv_co_truncate(bs->file,
cluster_offset + s->cluster_size,
false, PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0) {
return ret;
}
@ -492,9 +493,9 @@ static int get_cluster_offset(BlockDriverState *bs,
return -EIO;
}
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
ret = bdrv_pwrite(bs->file, cluster_offset + i,
BDRV_SECTOR_SIZE,
s->cluster_data, 0);
ret = bdrv_co_pwrite(bs->file, cluster_offset + i,
BDRV_SECTOR_SIZE,
s->cluster_data, 0);
if (ret < 0) {
return ret;
}
@ -514,8 +515,8 @@ static int get_cluster_offset(BlockDriverState *bs,
} else {
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
}
ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
sizeof(tmp), &tmp, 0);
ret = bdrv_co_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
sizeof(tmp), &tmp, 0);
if (ret < 0) {
return ret;
}
@ -585,7 +586,8 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
return 0;
}
static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
static int coroutine_fn decompress_cluster(BlockDriverState *bs,
uint64_t cluster_offset)
{
BDRVQcowState *s = bs->opaque;
int ret, csize;
@ -596,7 +598,7 @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
csize = cluster_offset >> (63 - s->cluster_bits);
csize &= (s->cluster_size - 1);
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
ret = bdrv_pread(bs->file, coffset, csize, s->cluster_data, 0);
ret = bdrv_co_pread(bs->file, coffset, csize, s->cluster_data, 0);
if (ret < 0)
return -1;
if (decompress_buffer(s->cluster_cache, s->cluster_size,
@ -888,14 +890,14 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
}
/* write all the data */
ret = blk_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
ret = blk_co_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
if (ret < 0) {
goto exit;
}
if (qcow_opts->has_backing_file) {
ret = blk_pwrite(qcow_blk, sizeof(header), backing_filename_len,
qcow_opts->backing_file, 0);
ret = blk_co_pwrite(qcow_blk, sizeof(header), backing_filename_len,
qcow_opts->backing_file, 0);
if (ret < 0) {
goto exit;
}
@ -904,8 +906,8 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
tmp = g_malloc0(BDRV_SECTOR_SIZE);
for (i = 0; i < DIV_ROUND_UP(sizeof(uint64_t) * l1_size, BDRV_SECTOR_SIZE);
i++) {
ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
BDRV_SECTOR_SIZE, tmp, 0);
ret = blk_co_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
BDRV_SECTOR_SIZE, tmp, 0);
if (ret < 0) {
g_free(tmp);
goto exit;

View file

@ -955,8 +955,8 @@ static void set_readonly_helper(gpointer bitmap, gpointer value)
* If header_updated is not NULL then it is set appropriately regardless of
* the return value.
*/
bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
Error **errp)
bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
bool *header_updated, Error **errp)
{
BDRVQcow2State *s = bs->opaque;
Qcow2BitmapList *bm_list;

View file

@ -31,7 +31,8 @@
#include "qemu/memalign.h"
#include "trace.h"
int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs,
uint64_t exact_size)
{
BDRVQcow2State *s = bs->opaque;
int new_l1_size, i, ret;
@ -47,14 +48,14 @@ int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
#endif
BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE);
ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset +
new_l1_size * L1E_SIZE,
(s->l1_size - new_l1_size) * L1E_SIZE, 0);
ret = bdrv_co_pwrite_zeroes(bs->file,
s->l1_table_offset + new_l1_size * L1E_SIZE,
(s->l1_size - new_l1_size) * L1E_SIZE, 0);
if (ret < 0) {
goto fail;
}
ret = bdrv_flush(bs->file->bs);
ret = bdrv_co_flush(bs->file->bs);
if (ret < 0) {
goto fail;
}
@ -823,10 +824,10 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
*
* Return 0 on success and -errno in error cases
*/
int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int compressed_size,
uint64_t *host_offset)
int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int compressed_size,
uint64_t *host_offset)
{
BDRVQcow2State *s = bs->opaque;
int l2_index, ret;
@ -1488,8 +1489,9 @@ static int coroutine_fn handle_dependencies(BlockDriverState *bs,
*
* -errno: in error cases
*/
static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
static int coroutine_fn handle_copied(BlockDriverState *bs,
uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
QCowL2Meta **m)
{
BDRVQcow2State *s = bs->opaque;
int l2_index;
@ -1653,8 +1655,9 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
*
* -errno: in error cases
*/
static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
static int coroutine_fn handle_alloc(BlockDriverState *bs,
uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
QCowL2Meta **m)
{
BDRVQcow2State *s = bs->opaque;
int l2_index;

View file

@ -97,7 +97,7 @@ static void update_max_refcount_table_index(BDRVQcow2State *s)
s->max_refcount_table_index = i;
}
int qcow2_refcount_init(BlockDriverState *bs)
int coroutine_fn qcow2_refcount_init(BlockDriverState *bs)
{
BDRVQcow2State *s = bs->opaque;
unsigned int refcount_table_size2, i;
@ -118,8 +118,8 @@ int qcow2_refcount_init(BlockDriverState *bs)
goto fail;
}
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
ret = bdrv_pread(bs->file, s->refcount_table_offset,
refcount_table_size2, s->refcount_table, 0);
ret = bdrv_co_pread(bs->file, s->refcount_table_offset,
refcount_table_size2, s->refcount_table, 0);
if (ret < 0) {
goto fail;
}
@ -3559,8 +3559,8 @@ static int64_t get_refblock_offset(BlockDriverState *bs, uint64_t offset)
return covering_refblock_offset;
}
static int qcow2_discard_refcount_block(BlockDriverState *bs,
uint64_t discard_block_offs)
static int coroutine_fn
qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
{
BDRVQcow2State *s = bs->opaque;
int64_t refblock_offs;
@ -3616,7 +3616,7 @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
return 0;
}
int qcow2_shrink_reftable(BlockDriverState *bs)
int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs)
{
BDRVQcow2State *s = bs->opaque;
uint64_t *reftable_tmp =
@ -3657,9 +3657,9 @@ int qcow2_shrink_reftable(BlockDriverState *bs)
reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]);
}
ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset,
s->refcount_table_size * REFTABLE_ENTRY_SIZE,
reftable_tmp, 0);
ret = bdrv_co_pwrite_sync(bs->file, s->refcount_table_offset,
s->refcount_table_size * REFTABLE_ENTRY_SIZE,
reftable_tmp, 0);
/*
* If the write in the reftable failed the image may contain a partially
* overwritten reftable. In this case it would be better to clear the

View file

@ -441,9 +441,9 @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
} QEMU_PACKED snapshot_table_pointer;
/* qcow2_do_open() discards this information in check mode */
ret = bdrv_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
sizeof(snapshot_table_pointer), &snapshot_table_pointer,
0);
ret = bdrv_co_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
sizeof(snapshot_table_pointer), &snapshot_table_pointer,
0);
if (ret < 0) {
result->check_errors++;
fprintf(stderr, "ERROR failed to read the snapshot table pointer from "

View file

@ -1306,7 +1306,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
uint64_t l1_vm_state_index;
bool update_header = false;
ret = bdrv_pread(bs->file, 0, sizeof(header), &header, 0);
ret = bdrv_co_pread(bs->file, 0, sizeof(header), &header, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read qcow2 header");
goto fail;
@ -1382,9 +1382,9 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
if (header.header_length > sizeof(header)) {
s->unknown_header_fields_size = header.header_length - sizeof(header);
s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
ret = bdrv_pread(bs->file, sizeof(header),
s->unknown_header_fields_size,
s->unknown_header_fields, 0);
ret = bdrv_co_pread(bs->file, sizeof(header),
s->unknown_header_fields_size,
s->unknown_header_fields, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read unknown qcow2 header "
"fields");
@ -1579,8 +1579,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
ret = -ENOMEM;
goto fail;
}
ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
s->l1_table, 0);
ret = bdrv_co_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
s->l1_table, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read L1 table");
goto fail;
@ -1699,8 +1699,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
}
s->image_backing_file = g_malloc(len + 1);
ret = bdrv_pread(bs->file, header.backing_file_offset, len,
s->image_backing_file, 0);
ret = bdrv_co_pread(bs->file, header.backing_file_offset, len,
s->image_backing_file, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read backing file name");
goto fail;
@ -1905,11 +1905,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
.errp = errp,
.ret = -EINPROGRESS
};
int ret;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
/* Initialise locks */
@ -3679,7 +3679,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
}
ret = blk_pwrite(blk, 0, cluster_size, header, 0);
ret = blk_co_pwrite(blk, 0, cluster_size, header, 0);
g_free(header);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not write qcow2 header");
@ -3689,7 +3689,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
/* Write a refcount table with one refcount block */
refcount_table = g_malloc0(2 * cluster_size);
refcount_table[0] = cpu_to_be64(2 * cluster_size);
ret = blk_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
ret = blk_co_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
g_free(refcount_table);
if (ret < 0) {
@ -3744,8 +3744,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
}
/* Okay, now that we have a valid image, let's give it the right size */
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
0, errp);
ret = blk_co_truncate(blk, qcow2_opts->size, false,
qcow2_opts->preallocation, 0, errp);
if (ret < 0) {
error_prepend(errp, "Could not resize image: ");
goto out;
@ -5287,8 +5287,8 @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
return pos;
}
static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos)
static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
QEMUIOVector *qiov, int64_t pos)
{
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
if (offset < 0) {
@ -5299,8 +5299,8 @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
}
static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos)
static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs,
QEMUIOVector *qiov, int64_t pos)
{
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
if (offset < 0) {

View file

@ -846,7 +846,7 @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
Error **errp);
/* qcow2-refcount.c functions */
int qcow2_refcount_init(BlockDriverState *bs);
int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
void qcow2_refcount_close(BlockDriverState *bs);
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
@ -893,14 +893,14 @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
BlockDriverAmendStatusCB *status_cb,
void *cb_opaque, Error **errp);
int qcow2_shrink_reftable(BlockDriverState *bs);
int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs);
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
/* qcow2-cluster.c functions */
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
bool exact_size);
int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
@ -911,10 +911,10 @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
unsigned int *bytes,
uint64_t *host_offset, QCowL2Meta **m);
int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int compressed_size,
uint64_t *host_offset);
int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int compressed_size,
uint64_t *host_offset);
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
uint64_t *coffset, int *csize);
@ -982,8 +982,8 @@ void qcow2_cache_discard(Qcow2Cache *c, void *table);
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
void **refcount_table,
int64_t *refcount_table_size);
bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
Error **errp);
bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
bool *header_updated, Error **errp);
bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
Qcow2BitmapInfoList **info_list, Error **errp);
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
@ -991,13 +991,13 @@ int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
bool release_stored, Error **errp);
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
const char *name,
uint32_t granularity,
Error **errp);
int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
const char *name,
Error **errp);
bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
const char *name,
uint32_t granularity,
Error **errp);
int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
const char *name,
Error **errp);
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
uint32_t cluster_size);

View file

@ -100,7 +100,7 @@ static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
}
if (flush) {
ret = bdrv_flush(s->bs);
ret = bdrv_co_flush(s->bs);
if (ret < 0) {
goto out;
}

View file

@ -387,7 +387,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
int64_t file_size;
int ret;
ret = bdrv_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
ret = bdrv_co_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
if (ret < 0) {
error_setg(errp, "Failed to read QED header");
return ret;
@ -492,7 +492,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
}
/* From here on only known autoclear feature bits are valid */
bdrv_flush(bs->file->bs);
bdrv_co_flush(bs->file->bs);
}
s->l1_table = qed_alloc_table(s);
@ -561,11 +561,11 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
.errp = errp,
.ret = -EINPROGRESS
};
int ret;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
bdrv_qed_init_state(bs);
@ -693,7 +693,7 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
* The QED format associates file length with allocation status,
* so a new file (which is empty) must have a length of 0.
*/
ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
ret = blk_co_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
if (ret < 0) {
goto out;
}
@ -712,18 +712,18 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
}
qed_header_cpu_to_le(&header, &le_header);
ret = blk_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
ret = blk_co_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
if (ret < 0) {
goto out;
}
ret = blk_pwrite(blk, sizeof(le_header), header.backing_filename_size,
ret = blk_co_pwrite(blk, sizeof(le_header), header.backing_filename_size,
qed_opts->backing_file, 0);
if (ret < 0) {
goto out;
}
l1_table = g_malloc0(l1_size);
ret = blk_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
ret = blk_co_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
if (ret < 0) {
goto out;
}

View file

@ -460,8 +460,8 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
}
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
file_role, false, errp);
bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
file_role, false, errp);
if (!bs->file) {
return -EINVAL;
}

View file

@ -88,11 +88,9 @@ static int replication_open(BlockDriverState *bs, QDict *options,
const char *mode;
const char *top_id;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
ret = -EINVAL;

View file

@ -82,9 +82,9 @@ static void snapshot_access_refresh_filename(BlockDriverState *bs)
static int snapshot_access_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
false, errp);
bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
}

View file

@ -151,41 +151,29 @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
}
/**
* Return a pointer to the child BDS pointer to which we can fall
* Return a pointer to child of given BDS to which we can fall
* back if the given BDS does not support snapshots.
* Return NULL if there is no BDS to (safely) fall back to.
*
* We need to return an indirect pointer because bdrv_snapshot_goto()
* has to modify the BdrvChild pointer.
*/
static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
{
BdrvChild **fallback;
BdrvChild *fallback = bdrv_primary_child(bs);
BdrvChild *child;
/*
* The only BdrvChild pointers that are safe to modify (and which
* we can thus return a reference to) are bs->file and
* bs->backing.
*/
fallback = &bs->file;
if (!*fallback && bs->drv && bs->drv->is_filter) {
fallback = &bs->backing;
}
if (!*fallback) {
/* We allow fallback only to primary child */
if (!fallback) {
return NULL;
}
/*
* Check that there are no other children that would need to be
* snapshotted. If there are, it is not safe to fall back to
* *fallback.
* fallback.
*/
QLIST_FOREACH(child, &bs->children, next) {
if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
BDRV_CHILD_FILTERED) &&
child != *fallback)
child != fallback)
{
return NULL;
}
@ -196,8 +184,7 @@ static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
{
BdrvChild **child_ptr = bdrv_snapshot_fallback_ptr(bs);
return child_ptr ? (*child_ptr)->bs : NULL;
return child_bs(bdrv_snapshot_fallback_child(bs));
}
int bdrv_can_snapshot(BlockDriverState *bs)
@ -244,7 +231,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
Error **errp)
{
BlockDriver *drv = bs->drv;
BdrvChild **fallback_ptr;
BdrvChild *fallback;
int ret, open_ret;
GLOBAL_STATE_CODE();
@ -267,13 +254,13 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
return ret;
}
fallback_ptr = bdrv_snapshot_fallback_ptr(bs);
if (fallback_ptr) {
fallback = bdrv_snapshot_fallback_child(bs);
if (fallback) {
QDict *options;
QDict *file_options;
Error *local_err = NULL;
BlockDriverState *fallback_bs = (*fallback_ptr)->bs;
char *subqdict_prefix = g_strdup_printf("%s.", (*fallback_ptr)->name);
BlockDriverState *fallback_bs = fallback->bs;
char *subqdict_prefix = g_strdup_printf("%s.", fallback->name);
options = qdict_clone_shallow(bs->options);
@ -284,8 +271,8 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
qobject_unref(file_options);
g_free(subqdict_prefix);
/* Force .bdrv_open() below to re-attach fallback_bs on *fallback_ptr */
qdict_put_str(options, (*fallback_ptr)->name,
/* Force .bdrv_open() below to re-attach fallback_bs on fallback */
qdict_put_str(options, fallback->name,
bdrv_get_node_name(fallback_bs));
/* Now close bs, apply the snapshot on fallback_bs, and re-open bs */
@ -294,8 +281,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
}
/* .bdrv_open() will re-attach it */
bdrv_unref_child(bs, *fallback_ptr);
*fallback_ptr = NULL;
bdrv_unref_child(bs, fallback);
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
@ -309,15 +295,12 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
}
/*
* fallback_ptr is &bs->file or &bs->backing. *fallback_ptr
* was closed above and set to NULL, but the .bdrv_open() call
* has opened it again, because we set the respective option
* (with the qdict_put_str() call above).
* Assert that .bdrv_open() has attached some child on
* *fallback_ptr, and that it has attached the one we wanted
* it to (i.e., fallback_bs).
* fallback was a primary child. It was closed above and set to NULL,
* but the .bdrv_open() call has opened it again, because we set the
* respective option (with the qdict_put_str() call above).
* Assert that .bdrv_open() has attached the right BDS as primary child.
*/
assert(*fallback_ptr && fallback_bs == (*fallback_ptr)->bs);
assert(bdrv_primary_bs(bs) == fallback_bs);
bdrv_unref(fallback_bs);
return ret;
}

View file

@ -1129,9 +1129,9 @@ static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
return ret;
}
static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
int64_t offset, size_t size,
QEMUIOVector *qiov)
static coroutine_fn int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
int64_t offset, size_t size,
QEMUIOVector *qiov)
{
ssize_t r;
size_t written;

View file

@ -78,11 +78,9 @@ static int throttle_open(BlockDriverState *bs, QDict *options,
char *group;
int ret;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
bs->supported_write_flags = bs->file->bs->supported_write_flags |
BDRV_REQ_WRITE_UNCHANGED;

View file

@ -377,10 +377,9 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
int ret;
QemuUUID uuid_link, uuid_parent;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
logout("\n");
@ -664,7 +663,8 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
* so this full-cluster write does not overlap a partial write
* of the same cluster, issued from the "else" branch.
*/
ret = bdrv_pwrite(bs->file, data_offset, s->block_size, block, 0);
ret = bdrv_co_pwrite(bs->file, data_offset, s->block_size, block,
0);
qemu_co_rwlock_unlock(&s->bmap_lock);
} else {
nonallocating_write:
@ -709,7 +709,7 @@ nonallocating_write:
assert(VDI_IS_ALLOCATED(bmap_first));
*header = s->header;
vdi_header_to_le(header);
ret = bdrv_pwrite(bs->file, 0, sizeof(*header), header, 0);
ret = bdrv_co_pwrite(bs->file, 0, sizeof(*header), header, 0);
g_free(header);
if (ret < 0) {
@ -726,8 +726,8 @@ nonallocating_write:
base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
logout("will write %u block map sectors starting from entry %u\n",
n_sectors, bmap_first);
ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE,
n_sectors * SECTOR_SIZE, base, 0);
ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE,
n_sectors * SECTOR_SIZE, base, 0);
}
return ret;
@ -845,7 +845,7 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
vdi_header_print(&header);
}
vdi_header_to_le(&header);
ret = blk_pwrite(blk, offset, sizeof(header), &header, 0);
ret = blk_co_pwrite(blk, offset, sizeof(header), &header, 0);
if (ret < 0) {
error_setg(errp, "Error writing header");
goto exit;
@ -866,7 +866,7 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
bmap[i] = VDI_UNALLOCATED;
}
}
ret = blk_pwrite(blk, offset, bmap_size, bmap, 0);
ret = blk_co_pwrite(blk, offset, bmap_size, bmap, 0);
if (ret < 0) {
error_setg(errp, "Error writing bmap");
goto exit;
@ -875,8 +875,8 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
}
if (image_type == VDI_TYPE_STATIC) {
ret = blk_truncate(blk, offset + blocks * block_size, false,
PREALLOC_MODE_OFF, 0, errp);
ret = blk_co_truncate(blk, offset + blocks * block_size, false,
PREALLOC_MODE_OFF, 0, errp);
if (ret < 0) {
error_prepend(errp, "Failed to statically allocate file");
goto exit;

View file

@ -1001,10 +1001,9 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
uint64_t signature;
Error *local_err = NULL;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
s->bat = NULL;
@ -2011,15 +2010,15 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL,
&creator_items, NULL);
signature = cpu_to_le64(VHDX_FILE_SIGNATURE);
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
0);
ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to write file signature");
goto delete_and_exit;
}
if (creator) {
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
creator_items * sizeof(gunichar2), creator, 0);
ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
creator_items * sizeof(gunichar2), creator, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to write creator field");
goto delete_and_exit;

View file

@ -1308,10 +1308,9 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
BDRVVmdkState *s = bs->opaque;
uint32_t magic;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
buf = vmdk_read_desc(bs->file, 0, errp);
@ -1404,13 +1403,13 @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
* it for call to write user data in the request.
*/
static int get_whole_cluster(BlockDriverState *bs,
VmdkExtent *extent,
uint64_t cluster_offset,
uint64_t offset,
uint64_t skip_start_bytes,
uint64_t skip_end_bytes,
bool zeroed)
static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
VmdkExtent *extent,
uint64_t cluster_offset,
uint64_t offset,
uint64_t skip_start_bytes,
uint64_t skip_end_bytes,
bool zeroed)
{
int ret = VMDK_OK;
int64_t cluster_bytes;
@ -1441,16 +1440,16 @@ static int get_whole_cluster(BlockDriverState *bs,
if (copy_from_backing) {
/* qcow2 emits this on bs->file instead of bs->backing */
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
ret = bdrv_pread(bs->backing, offset, skip_start_bytes,
whole_grain, 0);
ret = bdrv_co_pread(bs->backing, offset, skip_start_bytes,
whole_grain, 0);
if (ret < 0) {
ret = VMDK_ERROR;
goto exit;
}
}
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
ret = bdrv_pwrite(extent->file, cluster_offset, skip_start_bytes,
whole_grain, 0);
ret = bdrv_co_pwrite(extent->file, cluster_offset, skip_start_bytes,
whole_grain, 0);
if (ret < 0) {
ret = VMDK_ERROR;
goto exit;
@ -1461,18 +1460,18 @@ static int get_whole_cluster(BlockDriverState *bs,
if (copy_from_backing) {
/* qcow2 emits this on bs->file instead of bs->backing */
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
cluster_bytes - skip_end_bytes,
whole_grain + skip_end_bytes, 0);
ret = bdrv_co_pread(bs->backing, offset + skip_end_bytes,
cluster_bytes - skip_end_bytes,
whole_grain + skip_end_bytes, 0);
if (ret < 0) {
ret = VMDK_ERROR;
goto exit;
}
}
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
cluster_bytes - skip_end_bytes,
whole_grain + skip_end_bytes, 0);
ret = bdrv_co_pwrite(extent->file, cluster_offset + skip_end_bytes,
cluster_bytes - skip_end_bytes,
whole_grain + skip_end_bytes, 0);
if (ret < 0) {
ret = VMDK_ERROR;
goto exit;
@ -1485,29 +1484,29 @@ exit:
return ret;
}
static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
uint32_t offset)
static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
uint32_t offset)
{
offset = cpu_to_le32(offset);
/* update L2 table */
BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE);
if (bdrv_pwrite(extent->file,
((int64_t)m_data->l2_offset * 512)
+ (m_data->l2_index * sizeof(offset)),
sizeof(offset), &offset, 0) < 0) {
if (bdrv_co_pwrite(extent->file,
((int64_t)m_data->l2_offset * 512)
+ (m_data->l2_index * sizeof(offset)),
sizeof(offset), &offset, 0) < 0) {
return VMDK_ERROR;
}
/* update backup L2 table */
if (extent->l1_backup_table_offset != 0) {
m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
if (bdrv_pwrite(extent->file,
((int64_t)m_data->l2_offset * 512)
+ (m_data->l2_index * sizeof(offset)),
sizeof(offset), &offset, 0) < 0) {
if (bdrv_co_pwrite(extent->file,
((int64_t)m_data->l2_offset * 512)
+ (m_data->l2_index * sizeof(offset)),
sizeof(offset), &offset, 0) < 0) {
return VMDK_ERROR;
}
}
if (bdrv_flush(extent->file->bs) < 0) {
if (bdrv_co_flush(extent->file->bs) < 0) {
return VMDK_ERROR;
}
if (m_data->l2_cache_entry) {
@ -1537,14 +1536,14 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
* VMDK_ERROR if failed.
*/
static int get_cluster_offset(BlockDriverState *bs,
VmdkExtent *extent,
VmdkMetaData *m_data,
uint64_t offset,
bool allocate,
uint64_t *cluster_offset,
uint64_t skip_start_bytes,
uint64_t skip_end_bytes)
static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
VmdkExtent *extent,
VmdkMetaData *m_data,
uint64_t offset,
bool allocate,
uint64_t *cluster_offset,
uint64_t skip_start_bytes,
uint64_t skip_end_bytes)
{
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
@ -1624,11 +1623,10 @@ static int get_cluster_offset(BlockDriverState *bs,
}
l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes);
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
if (bdrv_pread(extent->file,
if (bdrv_co_pread(extent->file,
(int64_t)l2_offset * 512,
l2_size_bytes,
l2_table,
0
l2_table, 0
) < 0) {
return VMDK_ERROR;
}
@ -1899,7 +1897,8 @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
cluster_buf = g_malloc(buf_bytes);
uncomp_buf = g_malloc(cluster_bytes);
BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
ret = bdrv_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, 0);
ret = bdrv_co_pread(extent->file, cluster_offset, buf_bytes, cluster_buf,
0);
if (ret < 0) {
goto out;
}
@ -2144,8 +2143,8 @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
return length;
}
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
ret = bdrv_truncate(s->extents[i].file, length, false,
PREALLOC_MODE_OFF, 0, NULL);
ret = bdrv_co_truncate(s->extents[i].file, length, false,
PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0) {
return ret;
}
@ -2586,7 +2585,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
desc_offset = 0x200;
}
ret = blk_pwrite(blk, desc_offset, desc_len, desc, 0);
ret = blk_co_pwrite(blk, desc_offset, desc_len, desc, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not write description");
goto exit;
@ -2594,7 +2593,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
* for description file */
if (desc_offset == 0) {
ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
ret = blk_co_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
if (ret < 0) {
goto exit;
}

View file

@ -233,10 +233,9 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
int ret;
int64_t bs_size;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
if (ret < 0) {
return ret;
}
opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);

View file

@ -499,7 +499,7 @@ static bool valid_filename(const unsigned char *name)
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
c > 127 ||
strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
strchr(" $%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
{
return false;
}
@ -2993,11 +2993,35 @@ DLOG(checkpoint());
vvfat_close_current_file(s);
if (sector_num == s->offset_to_bootsector && nb_sectors == 1) {
/*
* Write on bootsector. Allow only changing the reserved1 field,
* used to mark volume dirtiness
*/
unsigned char *bootsector = s->first_sectors
+ s->offset_to_bootsector * 0x200;
/*
* LATER TODO: if FAT32, this is wrong (see init_directories(),
* which always creates a FAT16 bootsector)
*/
const int reserved1_offset = offsetof(bootsector_t, u.fat16.reserved1);
for (i = 0; i < 0x200; i++) {
if (i != reserved1_offset && bootsector[i] != buf[i]) {
fprintf(stderr, "Tried to write to protected bootsector\n");
return -1;
}
}
/* Update bootsector with the only updatable byte, and return success */
bootsector[reserved1_offset] = buf[reserved1_offset];
return 0;
}
/*
* Some sanity checks:
* - do not allow writing to the boot sector
*/
if (sector_num < s->offset_to_fat)
return -1;
@ -3146,10 +3170,9 @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
array_init(&(s->commits), sizeof(commit_t));
s->qcow_filename = g_malloc(PATH_MAX);
ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
if (ret < 0) {
error_setg_errno(errp, -ret, "can't create temporary file");
s->qcow_filename = create_tmp_file(errp);
if (!s->qcow_filename) {
ret = -ENOENT;
goto err;
}

View file

@ -1630,8 +1630,8 @@ static void external_snapshot_abort(BlkActionState *common)
aio_context_release(aio_context);
aio_context_acquire(tmp_context);
ret = bdrv_try_set_aio_context(state->old_bs,
aio_context, NULL);
ret = bdrv_try_change_aio_context(state->old_bs,
aio_context, NULL, NULL);
assert(ret == 0);
aio_context_release(tmp_context);
@ -1792,12 +1792,12 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
goto out;
}
/* Honor bdrv_try_set_aio_context() context acquisition requirements. */
/* Honor bdrv_try_change_aio_context() context acquisition requirements. */
old_context = bdrv_get_aio_context(target_bs);
aio_context_release(aio_context);
aio_context_acquire(old_context);
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
if (ret < 0) {
bdrv_unref(target_bs);
aio_context_release(old_context);
@ -1892,12 +1892,12 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
return;
}
/* Honor bdrv_try_set_aio_context() context acquisition requirements. */
/* Honor bdrv_try_change_aio_context() context acquisition requirements. */
aio_context = bdrv_get_aio_context(bs);
old_context = bdrv_get_aio_context(target_bs);
aio_context_acquire(old_context);
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
if (ret < 0) {
aio_context_release(old_context);
return;
@ -2448,7 +2448,7 @@ void coroutine_fn qmp_block_resize(bool has_device, const char *device,
bdrv_co_unlock(bs);
old_ctx = bdrv_co_enter(bs);
blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
blk_co_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
bdrv_co_leave(bs, old_ctx);
bdrv_co_lock(bs);
@ -3194,12 +3194,12 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
!bdrv_has_zero_init(target_bs)));
/* Honor bdrv_try_set_aio_context() context acquisition requirements. */
/* Honor bdrv_try_change_aio_context() context acquisition requirements. */
old_context = bdrv_get_aio_context(target_bs);
aio_context_release(aio_context);
aio_context_acquire(old_context);
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
if (ret < 0) {
bdrv_unref(target_bs);
aio_context_release(old_context);
@ -3266,12 +3266,12 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
/* Honor bdrv_try_set_aio_context() context acquisition requirements. */
/* Honor bdrv_try_change_aio_context() context acquisition requirements. */
old_context = bdrv_get_aio_context(target_bs);
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(old_context);
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
aio_context_release(old_context);
aio_context_acquire(aio_context);
@ -3767,7 +3767,7 @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
old_context = bdrv_get_aio_context(bs);
aio_context_acquire(old_context);
bdrv_try_set_aio_context(bs, new_context, errp);
bdrv_try_change_aio_context(bs, new_context, NULL, errp);
aio_context_release(old_context);
}

View file

@ -126,39 +126,50 @@ static void child_job_drained_end(BdrvChild *c, int *drained_end_counter)
job_resume(&job->job);
}
static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
GSList **ignore, Error **errp)
typedef struct BdrvStateChildJobContext {
AioContext *new_ctx;
BlockJob *job;
} BdrvStateChildJobContext;
static void child_job_set_aio_ctx_commit(void *opaque)
{
BdrvStateChildJobContext *s = opaque;
BlockJob *job = s->job;
job_set_aio_context(&job->job, s->new_ctx);
}
static TransactionActionDrv change_child_job_context = {
.commit = child_job_set_aio_ctx_commit,
.clean = g_free,
};
static bool child_job_change_aio_ctx(BdrvChild *c, AioContext *ctx,
GHashTable *visited, Transaction *tran,
Error **errp)
{
BlockJob *job = c->opaque;
BdrvStateChildJobContext *s;
GSList *l;
for (l = job->nodes; l; l = l->next) {
BdrvChild *sibling = l->data;
if (!bdrv_child_can_set_aio_context(sibling, ctx, ignore, errp)) {
if (!bdrv_child_change_aio_context(sibling, ctx, visited,
tran, errp)) {
return false;
}
}
s = g_new(BdrvStateChildJobContext, 1);
*s = (BdrvStateChildJobContext) {
.new_ctx = ctx,
.job = job,
};
tran_add(tran, &change_child_job_context, s);
return true;
}
static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
GSList **ignore)
{
BlockJob *job = c->opaque;
GSList *l;
for (l = job->nodes; l; l = l->next) {
BdrvChild *sibling = l->data;
if (g_slist_find(*ignore, sibling)) {
continue;
}
*ignore = g_slist_prepend(*ignore, sibling);
bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
}
job_set_aio_context(&job->job, ctx);
}
static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
{
BlockJob *job = c->opaque;
@ -172,8 +183,7 @@ static const BdrvChildClass child_job = {
.drained_begin = child_job_drained_begin,
.drained_poll = child_job_drained_poll,
.drained_end = child_job_drained_end,
.can_set_aio_ctx = child_job_can_set_aio_ctx,
.set_aio_ctx = child_job_set_aio_ctx,
.change_aio_ctx = child_job_change_aio_ctx,
.stay_at_node = true,
.get_parent_aio_context = child_job_get_parent_aio_context,
};

View file

@ -109,7 +109,7 @@ The AioContext originates from the QEMU block layer, even though nowadays
AioContext is a generic event loop that can be used by any QEMU subsystem.
The block layer has support for AioContext integrated. Each BlockDriverState
is associated with an AioContext using bdrv_try_set_aio_context() and
is associated with an AioContext using bdrv_try_change_aio_context() and
bdrv_get_aio_context(). This allows block layer code to process I/O inside the
right AioContext. Other subsystems may wish to follow a similar approach.
@ -134,5 +134,5 @@ Long-running jobs (usually in the form of coroutines) are best scheduled in
the BlockDriverState's AioContext to avoid the need to acquire/release around
each bdrv_*() call. The functions bdrv_add/remove_aio_context_notifier,
or alternatively blk_add/remove_aio_context_notifier if you use BlockBackends,
can be used to get a notification whenever bdrv_try_set_aio_context() moves a
can be used to get a notification whenever bdrv_try_change_aio_context() moves a
BlockDriverState to a different AioContext.

View file

@ -97,6 +97,10 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);
Error *local_err = NULL;
if (!dev->started) {
return 0;
}
ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,
vdev->config_len, &local_err);
if (ret < 0) {

View file

@ -322,6 +322,45 @@ enum {
*
* At least one of DATA, METADATA, FILTERED, or COW must be set for
* every child.
*
*
* = Connection with bs->children, bs->file and bs->backing fields =
*
* 1. Filters
*
* Filter drivers have drv->is_filter = true.
*
* Filter node has exactly one FILTERED|PRIMARY child, and may have other
* children which must not have these bits (one example is the
* copy-before-write filter, which also has its target DATA child).
*
* Filter nodes never have COW children.
*
* For most filters, the filtered child is linked in bs->file, bs->backing is
* NULL. For some filters (as an exception), it is the other way around; those
* drivers will have drv->filtered_child_is_backing set to true (see that
* fields documentation for what drivers this concerns)
*
* 2. "raw" driver (block/raw-format.c)
*
* Formally it's not a filter (drv->is_filter = false)
*
* bs->backing is always NULL
*
* Only has one child, linked in bs->file. Its role is either FILTERED|PRIMARY
* (like filter) or DATA|PRIMARY depending on options.
*
* 3. Other drivers
*
* Don't have any FILTERED children.
*
* May have at most one COW child. In this case it's linked in bs->backing.
* Otherwise bs->backing is NULL. COW child is never PRIMARY.
*
* May have at most one PRIMARY child. In this case it's linked in bs->file.
* Otherwise bs->file is NULL.
*
* May also have some other children that don't have the PRIMARY or COW bit set.
*/
enum BdrvChildRoleBits {
/*

View file

@ -76,6 +76,9 @@ BdrvChild *bdrv_open_child(const char *filename,
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);
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
Error **errp);
@ -217,17 +220,12 @@ void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
*/
void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
AioContext *new_context, GSList **ignore);
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
Error **errp);
int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
BdrvChild *ignore_child, Error **errp);
bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
GSList **ignore, Error **errp);
bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
GSList **ignore, Error **errp);
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
GHashTable *visited, Transaction *tran,
Error **errp);
int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
BdrvChild *ignore_child, Error **errp);
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);

View file

@ -38,7 +38,7 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
void hmp_block_resize(Monitor *mon, const QDict *qdict);
void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict);
void hmp_block_stream(Monitor *mon, const QDict *qdict);
void hmp_block_passwd(Monitor *mon, const QDict *qdict);
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);

View file

@ -83,12 +83,13 @@ void bdrv_aio_cancel(BlockAIOCB *acb);
void bdrv_aio_cancel_async(BlockAIOCB *acb);
/* sg packet commands */
int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
/* Ensure contents are flushed to disk. */
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
int64_t bytes);
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
int64_t bytes, int64_t *pnum, int64_t *map,

View file

@ -119,6 +119,20 @@ struct BlockDriver {
* (And this filtered child must then be bs->file or bs->backing.)
*/
bool is_filter;
/*
* Only make sense for filter drivers, for others must be false.
* If true, filtered child is bs->backing. Otherwise it's bs->file.
* Two internal filters use bs->backing as filtered child and has this
* field set to true: mirror_top and commit_top. There also two such test
* filters in tests/unit/test-bdrv-graph-mod.c.
*
* Never create any more such filters!
*
* TODO: imagine how to deprecate this behavior and make all filters work
* similarly using bs->file as filtered child.
*/
bool filtered_child_is_backing;
/*
* Set to true if the BlockDriver is a format driver. Format nodes
* generally do not expect their children to be other format nodes
@ -734,13 +748,11 @@ struct BlockDriver {
void coroutine_fn (*bdrv_co_drain_end)(BlockDriverState *bs);
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
const char *name,
uint32_t granularity,
Error **errp);
int (*bdrv_co_remove_persistent_dirty_bitmap)(BlockDriverState *bs,
const char *name,
Error **errp);
bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
BlockDriverState *bs, const char *name, uint32_t granularity,
Error **errp);
int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)(
BlockDriverState *bs, const char *name, Error **errp);
};
static inline bool block_driver_can_compress(BlockDriver *drv)
@ -895,9 +907,9 @@ struct BdrvChildClass {
int (*update_filename)(BdrvChild *child, BlockDriverState *new_base,
const char *filename, Error **errp);
bool (*can_set_aio_ctx)(BdrvChild *child, AioContext *ctx,
GSList **ignore, Error **errp);
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
GHashTable *visited, Transaction *tran,
Error **errp);
AioContext *(*get_parent_aio_context)(BdrvChild *child);
@ -1045,9 +1057,6 @@ struct BlockDriverState {
QDict *full_open_options;
char exact_filename[PATH_MAX];
BdrvChild *backing;
BdrvChild *file;
/* I/O Limits */
BlockLimits bl;
@ -1106,7 +1115,19 @@ struct BlockDriverState {
* parent node of this node.
*/
BlockDriverState *inherits_from;
/*
* @backing and @file are some of @children or NULL. All these three fields
* (@file, @backing and @children) are modified only in
* bdrv_child_cb_attach() and bdrv_child_cb_detach().
*
* See also comment in include/block/block.h, to learn how backing and file
* are connected with BdrvChildRole.
*/
QLIST_HEAD(, BdrvChild) children;
BdrvChild *backing;
BdrvChild *file;
QLIST_HEAD(, BdrvChild) parents;
QDict *options;
@ -1233,7 +1254,7 @@ static inline BlockDriverState *child_bs(BdrvChild *child)
}
int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp);
int get_tmp_filename(char *filename, int size);
char *create_tmp_file(Error **errp);
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
QDict *options);

View file

@ -15,6 +15,7 @@
#define HMP_H
#include "qemu/readline.h"
#include "qemu/coroutine.h"
#include "qapi/qapi-types-common.h"
bool hmp_handle_error(Monitor *mon, Error *err);
@ -81,7 +82,7 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict);
void hmp_getfd(Monitor *mon, const QDict *qdict);
void hmp_closefd(Monitor *mon, const QDict *qdict);
void hmp_sendkey(Monitor *mon, const QDict *qdict);
void hmp_screendump(Monitor *mon, const QDict *qdict);
void coroutine_fn hmp_screendump(Monitor *mon, const QDict *qdict);
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
void hmp_chardev_change(Monitor *mon, const QDict *qdict);
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);

View file

@ -287,7 +287,7 @@ void qemu_co_rwlock_init(CoRwlock *lock);
* of a parallel writer, control is transferred to the caller of the current
* coroutine.
*/
void qemu_co_rwlock_rdlock(CoRwlock *lock);
void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock);
/**
* Write Locks the CoRwlock from a reader. This is a bit more efficient than
@ -296,7 +296,7 @@ void qemu_co_rwlock_rdlock(CoRwlock *lock);
* to the caller of the current coroutine; another writer might run while
* @qemu_co_rwlock_upgrade blocks.
*/
void qemu_co_rwlock_upgrade(CoRwlock *lock);
void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock);
/**
* Downgrades a write-side critical section to a reader. Downgrading with
@ -304,20 +304,20 @@ void qemu_co_rwlock_upgrade(CoRwlock *lock);
* followed by @qemu_co_rwlock_rdlock. This makes it more efficient, but
* may also sometimes be necessary for correctness.
*/
void qemu_co_rwlock_downgrade(CoRwlock *lock);
void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock);
/**
* Write Locks the mutex. If the lock cannot be taken immediately because
* of a parallel reader, control is transferred to the caller of the current
* coroutine.
*/
void qemu_co_rwlock_wrlock(CoRwlock *lock);
void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock);
/**
* Unlocks the read/write lock and schedules the next coroutine that was
* waiting for this lock to be run.
*/
void qemu_co_rwlock_unlock(CoRwlock *lock);
void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock);
typedef struct QemuCoSleep {
Coroutine *to_wake;
@ -389,8 +389,9 @@ void qemu_coroutine_dec_pool_size(unsigned int additional_pool_size);
* The same interface as qemu_sendv_recvv(), with added yielding.
* XXX should mark these as coroutine_fn
*/
ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
size_t offset, size_t bytes, bool do_send);
ssize_t coroutine_fn qemu_co_sendv_recvv(int sockfd, struct iovec *iov,
unsigned iov_cnt, size_t offset,
size_t bytes, bool do_send);
#define qemu_co_recvv(sockfd, iov, iov_cnt, offset, bytes) \
qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, false)
#define qemu_co_sendv(sockfd, iov, iov_cnt, offset, bytes) \
@ -399,7 +400,8 @@ ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
/**
* The same as above, but with just a single buffer
*/
ssize_t qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send);
ssize_t coroutine_fn qemu_co_send_recv(int sockfd, void *buf, size_t bytes,
bool do_send);
#define qemu_co_recv(sockfd, buf, bytes) \
qemu_co_send_recv(sockfd, buf, bytes, false)
#define qemu_co_send(sockfd, buf, bytes) \

2
job.c
View file

@ -588,7 +588,7 @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
next_aio_context = job->aio_context;
/*
* Coroutine has resumed, but in the meanwhile the job AioContext
* might have changed via bdrv_try_set_aio_context(), so we need to move
* might have changed via bdrv_try_change_aio_context(), so we need to move
* the coroutine too in the new aiocontext.
*/
while (qemu_get_current_aio_context() != next_aio_context) {

View file

@ -1853,7 +1853,6 @@ config_host_data.set('CONFIG_LIBNFS', libnfs.found())
config_host_data.set('CONFIG_LIBSSH', libssh.found())
config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
config_host_data.set('CONFIG_LIBURING_REGISTER_RING_FD', cc.has_function('io_uring_register_ring_fd', prefix: '#include <liburing.h>', dependencies:linux_io_uring))
config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
config_host_data.set('CONFIG_NUMA', numa.found())
config_host_data.set('CONFIG_OPENGL', opengl.found())

View file

@ -375,7 +375,8 @@ if [ "${VALGRIND_QEMU_VM}" == "y" ]; then
_casenotrun "Valgrind needs a valid TMPDIR for itself"
fi
VALGRIND_QEMU_VM= \
TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on
TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on |
sed -e "s#'[^']*/vl\.[A-Za-z0-9]\{6\}'#SNAPSHOT_PATH#g"
# Using snapshot=on together with read-only=on
echo "info block" |

View file

@ -459,7 +459,7 @@ wrote 4096/4096 bytes at offset 0
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Testing: -drive driver=null-co,snapshot=on
QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information

View file

@ -539,7 +539,7 @@ wrote 4096/4096 bytes at offset 0
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Testing: -drive driver=null-co,snapshot=on
QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information

View file

@ -1538,16 +1538,16 @@ static void test_set_aio_context(void)
&error_abort);
bdrv_drained_begin(bs);
bdrv_try_set_aio_context(bs, ctx_a, &error_abort);
bdrv_try_change_aio_context(bs, ctx_a, NULL, &error_abort);
aio_context_acquire(ctx_a);
bdrv_drained_end(bs);
bdrv_drained_begin(bs);
bdrv_try_set_aio_context(bs, ctx_b, &error_abort);
bdrv_try_change_aio_context(bs, ctx_b, NULL, &error_abort);
aio_context_release(ctx_a);
aio_context_acquire(ctx_b);
bdrv_try_set_aio_context(bs, qemu_get_aio_context(), &error_abort);
bdrv_try_change_aio_context(bs, qemu_get_aio_context(), NULL, &error_abort);
aio_context_release(ctx_b);
bdrv_drained_end(bs);
@ -1830,9 +1830,8 @@ static void test_drop_intermediate_poll(void)
for (i = 0; i < 3; i++) {
if (i) {
/* Takes the reference to chain[i - 1] */
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
"chain", &chain_child_class,
BDRV_CHILD_COW, &error_abort);
bdrv_attach_child(chain[i], chain[i - 1], "chain",
&chain_child_class, BDRV_CHILD_COW, &error_abort);
}
}
@ -1970,6 +1969,7 @@ static void coroutine_fn bdrv_replace_test_co_drain_end(BlockDriverState *bs)
static BlockDriver bdrv_replace_test = {
.format_name = "replace_test",
.instance_size = sizeof(BDRVReplaceTestState),
.supports_backing = true,
.bdrv_close = bdrv_replace_test_close,
.bdrv_co_preadv = bdrv_replace_test_co_preadv,
@ -2049,9 +2049,8 @@ static void do_test_replace_child_mid_drain(int old_drain_count,
new_child_bs->total_sectors = 1;
bdrv_ref(old_child_bs);
parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
&child_of_bds, BDRV_CHILD_COW,
&error_abort);
bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds,
BDRV_CHILD_COW, &error_abort);
for (i = 0; i < old_drain_count; i++) {
bdrv_drained_begin(old_child_bs);

View file

@ -26,6 +26,8 @@
static BlockDriver bdrv_pass_through = {
.format_name = "pass-through",
.is_filter = true,
.filtered_child_is_backing = true,
.bdrv_child_perm = bdrv_default_perms,
};
@ -57,6 +59,8 @@ static void exclusive_write_perms(BlockDriverState *bs, BdrvChild *c,
static BlockDriver bdrv_exclusive_writer = {
.format_name = "exclusive-writer",
.is_filter = true,
.filtered_child_is_backing = true,
.bdrv_child_perm = exclusive_write_perms,
};
@ -134,7 +138,7 @@ static void test_update_perm_tree(void)
blk_insert_bs(root, bs, &error_abort);
bdrv_attach_child(filter, bs, "child", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
BDRV_CHILD_DATA, &error_abort);
ret = bdrv_append(filter, bs, NULL);
g_assert_cmpint(ret, <, 0);
@ -228,11 +232,14 @@ static void test_parallel_exclusive_write(void)
*/
bdrv_ref(base);
bdrv_attach_child(top, fl1, "backing", &child_of_bds, BDRV_CHILD_DATA,
bdrv_attach_child(top, fl1, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
bdrv_attach_child(fl1, base, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
bdrv_attach_child(fl2, base, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_replace_node(fl1, fl2, &error_abort);
@ -241,13 +248,26 @@ static void test_parallel_exclusive_write(void)
bdrv_unref(top);
}
static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
/*
* write-to-selected node may have several DATA children, one of them may be
* "selected". Exclusive write permission is taken on selected child.
*
* We don't realize write handler itself, as we need only to test how permission
* update works.
*/
typedef struct BDRVWriteToSelectedState {
BdrvChild *selected;
} BDRVWriteToSelectedState;
static void write_to_selected_perms(BlockDriverState *bs, BdrvChild *c,
BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
{
if (bs->file && c == bs->file) {
BDRVWriteToSelectedState *s = bs->opaque;
if (s->selected && c == s->selected) {
*nperm = BLK_PERM_WRITE;
*nshared = BLK_PERM_ALL & ~BLK_PERM_WRITE;
} else {
@ -256,9 +276,10 @@ static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
}
}
static BlockDriver bdrv_write_to_file = {
.format_name = "tricky-perm",
.bdrv_child_perm = write_to_file_perms,
static BlockDriver bdrv_write_to_selected = {
.format_name = "write-to-selected",
.instance_size = sizeof(BDRVWriteToSelectedState),
.bdrv_child_perm = write_to_selected_perms,
};
@ -266,15 +287,18 @@ static BlockDriver bdrv_write_to_file = {
* The following test shows that topological-sort order is required for
* permission update, simple DFS is not enough.
*
* Consider the block driver which has two filter children: one active
* with exclusive write access and one inactive with no specific
* permissions.
* Consider the block driver (write-to-selected) which has two children: one is
* selected so we have exclusive write access to it and for the other one we
* don't need any specific permissions.
*
* And, these two children has a common base child, like this:
* (additional "top" on top is used in test just because the only public
* function to update permission should get a specific child to update.
* Making bdrv_refresh_perms() public just for this test isn't worth it)
*
*
* fl2 top
*
*
* fl2 write-to-selected top
*
*
* w
*
@ -290,14 +314,14 @@ static BlockDriver bdrv_write_to_file = {
*
* So, exclusive write is propagated.
*
* Assume, we want to make fl2 active instead of fl1.
* So, we set some option for top driver and do permission update.
* Assume, we want to select fl2 instead of fl1.
* So, we set some option for write-to-selected driver and do permission update.
*
* With simple DFS, if permission update goes first through
* top->fl1->base branch it will succeed: it firstly drop exclusive write
* permissions and than apply them for another BdrvChildren.
* But if permission update goes first through top->fl2->base branch it
* will fail, as when we try to update fl2->base child, old not yet
* write-to-selected -> fl1 -> base branch it will succeed: it firstly drop
* exclusive write permissions and than apply them for another BdrvChildren.
* But if permission update goes first through write-to-selected -> fl2 -> base
* branch it will fail, as when we try to update fl2->base child, old not yet
* updated fl1->base child will be in conflict.
*
* With topological-sort order we always update parents before children, so fl1
@ -306,9 +330,10 @@ static BlockDriver bdrv_write_to_file = {
static void test_parallel_perm_update(void)
{
BlockDriverState *top = no_perm_node("top");
BlockDriverState *tricky =
bdrv_new_open_driver(&bdrv_write_to_file, "tricky", BDRV_O_RDWR,
BlockDriverState *ws =
bdrv_new_open_driver(&bdrv_write_to_selected, "ws", BDRV_O_RDWR,
&error_abort);
BDRVWriteToSelectedState *s = ws->opaque;
BlockDriverState *base = no_perm_node("base");
BlockDriverState *fl1 = pass_through_node("fl1");
BlockDriverState *fl2 = pass_through_node("fl2");
@ -320,33 +345,35 @@ static void test_parallel_perm_update(void)
*/
bdrv_ref(base);
bdrv_attach_child(top, tricky, "file", &child_of_bds, BDRV_CHILD_DATA,
bdrv_attach_child(top, ws, "file", &child_of_bds, BDRV_CHILD_DATA,
&error_abort);
c_fl1 = bdrv_attach_child(tricky, fl1, "first", &child_of_bds,
BDRV_CHILD_FILTERED, &error_abort);
c_fl2 = bdrv_attach_child(tricky, fl2, "second", &child_of_bds,
BDRV_CHILD_FILTERED, &error_abort);
bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
c_fl1 = bdrv_attach_child(ws, fl1, "first", &child_of_bds,
BDRV_CHILD_DATA, &error_abort);
c_fl2 = bdrv_attach_child(ws, fl2, "second", &child_of_bds,
BDRV_CHILD_DATA, &error_abort);
bdrv_attach_child(fl1, base, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
bdrv_attach_child(fl2, base, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
/* Select fl1 as first child to be active */
tricky->file = c_fl1;
s->selected = c_fl1;
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
assert(c_fl1->perm & BLK_PERM_WRITE);
assert(!(c_fl2->perm & BLK_PERM_WRITE));
/* Now, try to switch active child and update permissions */
tricky->file = c_fl2;
s->selected = c_fl2;
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
assert(c_fl2->perm & BLK_PERM_WRITE);
assert(!(c_fl1->perm & BLK_PERM_WRITE));
/* Switch once more, to not care about real child order in the list */
tricky->file = c_fl1;
s->selected = c_fl1;
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
assert(c_fl1->perm & BLK_PERM_WRITE);
@ -379,7 +406,8 @@ static void test_append_greedy_filter(void)
BlockDriverState *base = no_perm_node("base");
BlockDriverState *fl = exclusive_writer_node("fl1");
bdrv_attach_child(top, base, "backing", &child_of_bds, BDRV_CHILD_COW,
bdrv_attach_child(top, base, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_append(fl, base, &error_abort);

View file

@ -765,7 +765,7 @@ static void test_propagate_mirror(void)
filter = bdrv_find_node("filter_node");
/* Change the AioContext of src */
bdrv_try_set_aio_context(src, ctx, &error_abort);
bdrv_try_change_aio_context(src, ctx, NULL, &error_abort);
g_assert(bdrv_get_aio_context(src) == ctx);
g_assert(bdrv_get_aio_context(target) == ctx);
g_assert(bdrv_get_aio_context(filter) == ctx);
@ -773,7 +773,7 @@ static void test_propagate_mirror(void)
/* Change the AioContext of target */
aio_context_acquire(ctx);
bdrv_try_set_aio_context(target, main_ctx, &error_abort);
bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
aio_context_release(ctx);
g_assert(bdrv_get_aio_context(src) == main_ctx);
g_assert(bdrv_get_aio_context(target) == main_ctx);
@ -783,7 +783,7 @@ static void test_propagate_mirror(void)
blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
blk_insert_bs(blk, src, &error_abort);
bdrv_try_set_aio_context(target, ctx, &local_err);
bdrv_try_change_aio_context(target, ctx, NULL, &local_err);
error_free_or_abort(&local_err);
g_assert(blk_get_aio_context(blk) == main_ctx);
@ -794,7 +794,7 @@ static void test_propagate_mirror(void)
/* ...unless we explicitly allow it */
aio_context_acquire(ctx);
blk_set_allow_aio_context_change(blk, true);
bdrv_try_set_aio_context(target, ctx, &error_abort);
bdrv_try_change_aio_context(target, ctx, NULL, &error_abort);
aio_context_release(ctx);
g_assert(blk_get_aio_context(blk) == ctx);
@ -806,7 +806,7 @@ static void test_propagate_mirror(void)
aio_context_acquire(ctx);
blk_set_aio_context(blk, main_ctx, &error_abort);
bdrv_try_set_aio_context(target, main_ctx, &error_abort);
bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
aio_context_release(ctx);
blk_unref(blk);