Pull request

-----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEhpWov9P5fNqsNXdanKSrs4Grc8gFAmNZg14ACgkQnKSrs4Gr
 c8hwwwf/Udbnt6n4SShezEIYRe0udLvuyo1HwcMNLWjllHLfp/yNDcPsGk+r13Ue
 TxrvbVaucxB5RPdN67KmzPyu+wPM/o0nij7c4CkBvwNPXmfUCF97Lj0prEL+ZeHp
 HmNg08FRfHM2vKMFyJXqDAidBecUDizLrP9C3nc/LAF6fr9ds+vfFuB/12eSXvZ+
 RLnaAj7KLt2MzkgWbDiC6066TPZWCcwFJmc0zkCAthCepokDrKfSHc+0u9U/NXA9
 Qv7qKcEBYq3vP3SCvDtbKU3Ig4CoiwO3A3O9wZTypamU2816H9HtEJ5NPtjNUFPF
 dm3siyKODbDx4mzba/Xv/26lHGSsJA==
 =bmGV
 -----END PGP SIGNATURE-----

Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging

Pull request

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCAAdFiEEhpWov9P5fNqsNXdanKSrs4Grc8gFAmNZg14ACgkQnKSrs4Gr
# c8hwwwf/Udbnt6n4SShezEIYRe0udLvuyo1HwcMNLWjllHLfp/yNDcPsGk+r13Ue
# TxrvbVaucxB5RPdN67KmzPyu+wPM/o0nij7c4CkBvwNPXmfUCF97Lj0prEL+ZeHp
# HmNg08FRfHM2vKMFyJXqDAidBecUDizLrP9C3nc/LAF6fr9ds+vfFuB/12eSXvZ+
# RLnaAj7KLt2MzkgWbDiC6066TPZWCcwFJmc0zkCAthCepokDrKfSHc+0u9U/NXA9
# Qv7qKcEBYq3vP3SCvDtbKU3Ig4CoiwO3A3O9wZTypamU2816H9HtEJ5NPtjNUFPF
# dm3siyKODbDx4mzba/Xv/26lHGSsJA==
# =bmGV
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 26 Oct 2022 14:58:38 EDT
# gpg:                using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [ultimate]
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>" [ultimate]
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* tag 'block-pull-request' of https://gitlab.com/stefanha/qemu:
  virtio-blk: use BDRV_REQ_REGISTERED_BUF optimization hint
  blkio: implement BDRV_REQ_REGISTERED_BUF optimization
  stubs: add qemu_ram_block_from_host() and qemu_ram_get_fd()
  exec/cpu-common: add qemu_ram_get_fd()
  block: add BlockRAMRegistrar
  numa: use QLIST_FOREACH_SAFE() for RAM block notifiers
  block: return errors from bdrv_register_buf()
  block: add BDRV_REQ_REGISTERED_BUF request flag
  block: use BdrvRequestFlags type for supported flag fields
  block: pass size to bdrv_unregister_buf()
  numa: call ->ram_block_removed() in ram_block_notifer_remove()
  blkio: add libblkio block driver
  coroutine: add flag to re-queue at front of CoQueue

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2022-10-30 15:07:25 -04:00
commit 75d30fde55
42 changed files with 1435 additions and 96 deletions

View File

@ -2510,6 +2510,7 @@ F: block*
F: block/
F: hw/block/
F: include/block/
F: include/sysemu/block-*.h
F: qemu-img*
F: docs/tools/qemu-img.rst
F: qemu-io*
@ -3415,6 +3416,12 @@ L: qemu-block@nongnu.org
S: Maintained
F: block/vdi.c
blkio
M: Stefan Hajnoczi <stefanha@redhat.com>
L: qemu-block@nongnu.org
S: Maintained
F: block/blkio.c
iSCSI
M: Ronnie Sahlberg <ronniesahlberg@gmail.com>
M: Paolo Bonzini <pbonzini@redhat.com>

14
block.c
View File

@ -1641,6 +1641,20 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
goto open_failed;
}
assert(!(bs->supported_read_flags & ~BDRV_REQ_MASK));
assert(!(bs->supported_write_flags & ~BDRV_REQ_MASK));
/*
* Always allow the BDRV_REQ_REGISTERED_BUF optimization hint. This saves
* drivers that pass read/write requests through to a child the trouble of
* declaring support explicitly.
*
* Drivers must not propagate this flag accidentally when they initiate I/O
* to a bounce buffer. That case should be rare though.
*/
bs->supported_read_flags |= BDRV_REQ_REGISTERED_BUF;
bs->supported_write_flags |= BDRV_REQ_REGISTERED_BUF;
ret = refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not refresh total sector count");

1008
block/blkio.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -235,8 +235,8 @@ blkverify_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
qemu_iovec_init(&raw_qiov, qiov->niov);
qemu_iovec_clone(&raw_qiov, qiov, buf);
ret = blkverify_co_prwv(bs, &r, offset, bytes, qiov, &raw_qiov, flags,
false);
ret = blkverify_co_prwv(bs, &r, offset, bytes, qiov, &raw_qiov,
flags & ~BDRV_REQ_REGISTERED_BUF, false);
cmp_offset = qemu_iovec_compare(qiov, &raw_qiov);
if (cmp_offset != -1) {

View File

@ -2545,16 +2545,16 @@ static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter)
}
}
void blk_register_buf(BlockBackend *blk, void *host, size_t size)
bool blk_register_buf(BlockBackend *blk, void *host, size_t size, Error **errp)
{
GLOBAL_STATE_CODE();
bdrv_register_buf(blk_bs(blk), host, size);
return bdrv_register_buf(blk_bs(blk), host, size, errp);
}
void blk_unregister_buf(BlockBackend *blk, void *host)
void blk_unregister_buf(BlockBackend *blk, void *host, size_t size)
{
GLOBAL_STATE_CODE();
bdrv_unregister_buf(blk_bs(blk), host);
bdrv_unregister_buf(blk_bs(blk), host, size);
}
int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,

View File

@ -0,0 +1,58 @@
/*
* BlockBackend RAM Registrar
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "sysemu/block-backend.h"
#include "sysemu/block-ram-registrar.h"
#include "qapi/error.h"
static void ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size)
{
BlockRAMRegistrar *r = container_of(n, BlockRAMRegistrar, notifier);
Error *err = NULL;
if (!r->ok) {
return; /* don't try again if we've already failed */
}
if (!blk_register_buf(r->blk, host, max_size, &err)) {
error_report_err(err);
ram_block_notifier_remove(&r->notifier);
r->ok = false;
}
}
static void ram_block_removed(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size)
{
BlockRAMRegistrar *r = container_of(n, BlockRAMRegistrar, notifier);
blk_unregister_buf(r->blk, host, max_size);
}
void blk_ram_registrar_init(BlockRAMRegistrar *r, BlockBackend *blk)
{
r->blk = blk;
r->notifier = (RAMBlockNotifier){
.ram_block_added = ram_block_added,
.ram_block_removed = ram_block_removed,
/*
* .ram_block_resized() is not necessary because we use the max_size
* value that does not change across resize.
*/
};
r->ok = true;
ram_block_notifier_add(&r->notifier);
}
void blk_ram_registrar_destroy(BlockRAMRegistrar *r)
{
if (r->ok) {
ram_block_notifier_remove(&r->notifier);
}
}

View File

@ -410,7 +410,6 @@ block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
assert(!flags);
assert(payload_offset < INT64_MAX);
assert(QEMU_IS_ALIGNED(offset, sector_size));
assert(QEMU_IS_ALIGNED(bytes, sector_size));
@ -473,7 +472,8 @@ block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
assert(!(flags & ~BDRV_REQ_FUA));
flags &= ~BDRV_REQ_REGISTERED_BUF;
assert(payload_offset < INT64_MAX);
assert(QEMU_IS_ALIGNED(offset, sector_size));
assert(QEMU_IS_ALIGNED(bytes, sector_size));

View File

@ -2133,7 +2133,6 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
int64_t bytes, QEMUIOVector *qiov,
BdrvRequestFlags flags)
{
assert(flags == 0);
return raw_co_prw(bs, offset, bytes, qiov, QEMU_AIO_WRITE);
}

View File

@ -1236,7 +1236,6 @@ static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
QEMUIOVector *qiov,
int flags)
{
assert(!flags);
return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
}

View File

@ -1130,8 +1130,7 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
int ret;
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
assert(!(flags & ~BDRV_REQ_MASK));
assert(!(flags & BDRV_REQ_NO_FALLBACK));
assert(!(flags & ~bs->supported_read_flags));
if (!drv) {
return -ENOMEDIUM;
@ -1195,23 +1194,29 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
BdrvRequestFlags flags)
{
BlockDriver *drv = bs->drv;
bool emulate_fua = false;
int64_t sector_num;
unsigned int nb_sectors;
QEMUIOVector local_qiov;
int ret;
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
assert(!(flags & ~BDRV_REQ_MASK));
assert(!(flags & BDRV_REQ_NO_FALLBACK));
if (!drv) {
return -ENOMEDIUM;
}
if ((flags & BDRV_REQ_FUA) &&
(~bs->supported_write_flags & BDRV_REQ_FUA)) {
flags &= ~BDRV_REQ_FUA;
emulate_fua = true;
}
flags &= bs->supported_write_flags;
if (drv->bdrv_co_pwritev_part) {
ret = drv->bdrv_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset,
flags & bs->supported_write_flags);
flags &= ~bs->supported_write_flags;
flags);
goto emulate_flags;
}
@ -1221,9 +1226,7 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
}
if (drv->bdrv_co_pwritev) {
ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov,
flags & bs->supported_write_flags);
flags &= ~bs->supported_write_flags;
ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov, flags);
goto emulate_flags;
}
@ -1233,10 +1236,8 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
.coroutine = qemu_coroutine_self(),
};
acb = drv->bdrv_aio_pwritev(bs, offset, bytes, qiov,
flags & bs->supported_write_flags,
acb = drv->bdrv_aio_pwritev(bs, offset, bytes, qiov, flags,
bdrv_co_io_em_complete, &co);
flags &= ~bs->supported_write_flags;
if (acb == NULL) {
ret = -EIO;
} else {
@ -1254,12 +1255,10 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
assert(drv->bdrv_co_writev);
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov,
flags & bs->supported_write_flags);
flags &= ~bs->supported_write_flags;
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov, flags);
emulate_flags:
if (ret == 0 && (flags & BDRV_REQ_FUA)) {
if (ret == 0 && emulate_fua) {
ret = bdrv_co_flush(bs);
}
@ -1487,11 +1486,14 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
align);
/* TODO: We would need a per-BDS .supported_read_flags and
/*
* TODO: We would need a per-BDS .supported_read_flags and
* potential fallback support, if we ever implement any read flags
* to pass through to drivers. For now, there aren't any
* passthrough flags. */
assert(!(flags & ~(BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH)));
* passthrough flags except the BDRV_REQ_REGISTERED_BUF optimization hint.
*/
assert(!(flags & ~(BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH |
BDRV_REQ_REGISTERED_BUF)));
/* Handle Copy on Read and associated serialisation */
if (flags & BDRV_REQ_COPY_ON_READ) {
@ -1532,7 +1534,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
goto out;
}
assert(!(flags & ~bs->supported_read_flags));
assert(!(flags & ~(bs->supported_read_flags | BDRV_REQ_REGISTERED_BUF)));
max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align);
if (bytes <= max_bytes && bytes <= max_transfer) {
@ -1721,7 +1723,8 @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad)
static int bdrv_pad_request(BlockDriverState *bs,
QEMUIOVector **qiov, size_t *qiov_offset,
int64_t *offset, int64_t *bytes,
BdrvRequestPadding *pad, bool *padded)
BdrvRequestPadding *pad, bool *padded,
BdrvRequestFlags *flags)
{
int ret;
@ -1749,6 +1752,10 @@ static int bdrv_pad_request(BlockDriverState *bs,
if (padded) {
*padded = true;
}
if (flags) {
/* Can't use optimization hint with bounce buffer */
*flags &= ~BDRV_REQ_REGISTERED_BUF;
}
return 0;
}
@ -1803,7 +1810,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
}
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad,
NULL);
NULL, &flags);
if (ret < 0) {
goto fail;
}
@ -1848,6 +1855,11 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
return -ENOTSUP;
}
/* By definition there is no user buffer so this flag doesn't make sense */
if (flags & BDRV_REQ_REGISTERED_BUF) {
return -EINVAL;
}
/* Invalidate the cached block-status data range if this write overlaps */
bdrv_bsc_invalidate_range(bs, offset, bytes);
@ -2133,6 +2145,9 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
bool padding;
BdrvRequestPadding pad;
/* This flag doesn't make sense for padding or zero writes */
flags &= ~BDRV_REQ_REGISTERED_BUF;
padding = bdrv_init_padding(bs, offset, bytes, &pad);
if (padding) {
assert(!(flags & BDRV_REQ_NO_WAIT));
@ -2250,7 +2265,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
* alignment only if there is no ZERO flag.
*/
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad,
&padded);
&padded, &flags);
if (ret < 0) {
return ret;
}
@ -3262,29 +3277,57 @@ void bdrv_io_unplug(BlockDriverState *bs)
}
}
void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size)
/* Helper that undoes bdrv_register_buf() when it fails partway through */
static void bdrv_register_buf_rollback(BlockDriverState *bs,
void *host,
size_t size,
BdrvChild *final_child)
{
BdrvChild *child;
QLIST_FOREACH(child, &bs->children, next) {
if (child == final_child) {
break;
}
bdrv_unregister_buf(child->bs, host, size);
}
if (bs->drv && bs->drv->bdrv_unregister_buf) {
bs->drv->bdrv_unregister_buf(bs, host, size);
}
}
bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
Error **errp)
{
BdrvChild *child;
GLOBAL_STATE_CODE();
if (bs->drv && bs->drv->bdrv_register_buf) {
bs->drv->bdrv_register_buf(bs, host, size);
if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) {
return false;
}
}
QLIST_FOREACH(child, &bs->children, next) {
bdrv_register_buf(child->bs, host, size);
if (!bdrv_register_buf(child->bs, host, size, errp)) {
bdrv_register_buf_rollback(bs, host, size, child);
return false;
}
}
return true;
}
void bdrv_unregister_buf(BlockDriverState *bs, void *host)
void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
{
BdrvChild *child;
GLOBAL_STATE_CODE();
if (bs->drv && bs->drv->bdrv_unregister_buf) {
bs->drv->bdrv_unregister_buf(bs, host);
bs->drv->bdrv_unregister_buf(bs, host, size);
}
QLIST_FOREACH(child, &bs->children, next) {
bdrv_unregister_buf(child->bs, host);
bdrv_unregister_buf(child->bs, host, size);
}
}

View File

@ -46,6 +46,7 @@ block_ss.add(files(
), zstd, zlib, gnutls)
softmmu_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
softmmu_ss.add(files('block-ram-registrar.c'))
if get_option('qcow1').allowed()
block_ss.add(files('qcow.c'))
@ -92,6 +93,7 @@ block_modules = {}
modsrc = []
foreach m : [
[blkio, 'blkio', files('blkio.c')],
[curl, 'curl', files('curl.c')],
[glusterfs, 'gluster', files('gluster.c')],
[libiscsi, 'iscsi', [files('iscsi.c'), libm]],

View File

@ -1486,6 +1486,8 @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
qemu_iovec_init(&bounce_qiov, 1);
qemu_iovec_add(&bounce_qiov, bounce_buf, bytes);
qiov = &bounce_qiov;
flags &= ~BDRV_REQ_REGISTERED_BUF;
}
ret = bdrv_mirror_top_do_write(bs, MIRROR_METHOD_COPY, offset, bytes, qiov,

View File

@ -1222,7 +1222,6 @@ static int coroutine_fn nbd_client_co_preadv(BlockDriverState *bs, int64_t offse
};
assert(bytes <= NBD_MAX_BUFFER_SIZE);
assert(!flags);
if (!bytes) {
return 0;

View File

@ -1587,22 +1587,22 @@ static void nvme_aio_unplug(BlockDriverState *bs)
}
}
static void nvme_register_buf(BlockDriverState *bs, void *host, size_t size)
static bool nvme_register_buf(BlockDriverState *bs, void *host, size_t size,
Error **errp)
{
int ret;
Error *local_err = NULL;
BDRVNVMeState *s = bs->opaque;
ret = qemu_vfio_dma_map(s->vfio, host, size, false, NULL, &local_err);
if (ret) {
/* FIXME: we may run out of IOVA addresses after repeated
* bdrv_register_buf/bdrv_unregister_buf, because nvme_vfio_dma_unmap
* doesn't reclaim addresses for fixed mappings. */
error_reportf_err(local_err, "nvme_register_buf failed: ");
}
/*
* FIXME: we may run out of IOVA addresses after repeated
* bdrv_register_buf/bdrv_unregister_buf, because nvme_vfio_dma_unmap
* doesn't reclaim addresses for fixed mappings.
*/
ret = qemu_vfio_dma_map(s->vfio, host, size, false, NULL, errp);
return ret == 0;
}
static void nvme_unregister_buf(BlockDriverState *bs, void *host)
static void nvme_unregister_buf(BlockDriverState *bs, void *host, size_t size)
{
BDRVNVMeState *s = bs->opaque;

View File

@ -329,7 +329,6 @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
QEMUIOVector hd_qiov;
int ret = 0;
assert(!flags);
qemu_iovec_init(&hd_qiov, qiov->niov);
while (nb_sectors > 0) {

View File

@ -628,7 +628,6 @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
uint8_t *buf;
void *orig_buf;
assert(!flags);
if (qiov->niov > 1) {
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
if (buf == NULL) {
@ -725,7 +724,6 @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
uint8_t *buf;
void *orig_buf;
assert(!flags);
s->cluster_cache_offset = -1; /* disable compressed cache */
/* We must always copy the iov when encrypting, so we

View File

@ -1395,7 +1395,6 @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
int64_t sector_num, int nb_sectors,
QEMUIOVector *qiov, int flags)
{
assert(!flags);
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
}

View File

@ -258,6 +258,8 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
qemu_iovec_add(&local_qiov, buf, 512);
qemu_iovec_concat(&local_qiov, qiov, 512, qiov->size - 512);
qiov = &local_qiov;
flags &= ~BDRV_REQ_REGISTERED_BUF;
}
ret = raw_adjust_offset(bs, &offset, bytes, true);

View File

@ -261,7 +261,6 @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
int ret;
int64_t n;
assert(!flags);
ret = replication_get_io_status(s);
if (ret < 0) {
goto out;

View File

@ -1196,7 +1196,6 @@ static coroutine_fn int ssh_co_writev(BlockDriverState *bs,
BDRVSSHState *s = bs->opaque;
int ret;
assert(!flags);
qemu_co_mutex_lock(&s->lock);
ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE, qiov);

View File

@ -1342,7 +1342,6 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
uint64_t bat_prior_offset = 0;
bool bat_update = false;
assert(!flags);
qemu_iovec_init(&hd_qiov, qiov->niov);
qemu_co_mutex_lock(&s->lock);

View File

@ -21,6 +21,7 @@
#include "hw/block/block.h"
#include "hw/qdev-properties.h"
#include "sysemu/blockdev.h"
#include "sysemu/block-ram-registrar.h"
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"
#include "hw/virtio/virtio-blk.h"
@ -362,12 +363,14 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
}
}
static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
static inline void submit_requests(VirtIOBlock *s, MultiReqBuffer *mrb,
int start, int num_reqs, int niov)
{
BlockBackend *blk = s->blk;
QEMUIOVector *qiov = &mrb->reqs[start]->qiov;
int64_t sector_num = mrb->reqs[start]->sector_num;
bool is_write = mrb->is_write;
BdrvRequestFlags flags = 0;
if (num_reqs > 1) {
int i;
@ -398,12 +401,18 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
num_reqs - 1);
}
if (blk_ram_registrar_ok(&s->blk_ram_registrar)) {
flags |= BDRV_REQ_REGISTERED_BUF;
}
if (is_write) {
blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
virtio_blk_rw_complete, mrb->reqs[start]);
blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov,
flags, virtio_blk_rw_complete,
mrb->reqs[start]);
} else {
blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
virtio_blk_rw_complete, mrb->reqs[start]);
blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov,
flags, virtio_blk_rw_complete,
mrb->reqs[start]);
}
}
@ -425,14 +434,14 @@ static int multireq_compare(const void *a, const void *b)
}
}
static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
static void virtio_blk_submit_multireq(VirtIOBlock *s, MultiReqBuffer *mrb)
{
int i = 0, start = 0, num_reqs = 0, niov = 0, nb_sectors = 0;
uint32_t max_transfer;
int64_t sector_num = 0;
if (mrb->num_reqs == 1) {
submit_requests(blk, mrb, 0, 1, -1);
submit_requests(s, mrb, 0, 1, -1);
mrb->num_reqs = 0;
return;
}
@ -452,11 +461,11 @@ static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
* 3. merge would exceed maximum transfer length of backend device
*/
if (sector_num + nb_sectors != req->sector_num ||
niov > blk_get_max_iov(blk) - req->qiov.niov ||
niov > blk_get_max_iov(s->blk) - req->qiov.niov ||
req->qiov.size > max_transfer ||
nb_sectors > (max_transfer -
req->qiov.size) / BDRV_SECTOR_SIZE) {
submit_requests(blk, mrb, start, num_reqs, niov);
submit_requests(s, mrb, start, num_reqs, niov);
num_reqs = 0;
}
}
@ -472,7 +481,7 @@ static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
num_reqs++;
}
submit_requests(blk, mrb, start, num_reqs, niov);
submit_requests(s, mrb, start, num_reqs, niov);
mrb->num_reqs = 0;
}
@ -487,7 +496,7 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
* Make sure all outstanding writes are posted to the backing device.
*/
if (mrb->is_write && mrb->num_reqs > 0) {
virtio_blk_submit_multireq(s->blk, mrb);
virtio_blk_submit_multireq(s, mrb);
}
blk_aio_flush(s->blk, virtio_blk_flush_complete, req);
}
@ -667,7 +676,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
if (mrb->num_reqs > 0 && (mrb->num_reqs == VIRTIO_BLK_MAX_MERGE_REQS ||
is_write != mrb->is_write ||
!s->conf.request_merging)) {
virtio_blk_submit_multireq(s->blk, mrb);
virtio_blk_submit_multireq(s, mrb);
}
assert(mrb->num_reqs < VIRTIO_BLK_MAX_MERGE_REQS);
@ -774,7 +783,7 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
} while (!virtio_queue_empty(vq));
if (mrb.num_reqs) {
virtio_blk_submit_multireq(s->blk, &mrb);
virtio_blk_submit_multireq(s, &mrb);
}
blk_io_unplug(s->blk);
@ -823,7 +832,7 @@ void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh)
}
if (mrb.num_reqs) {
virtio_blk_submit_multireq(s->blk, &mrb);
virtio_blk_submit_multireq(s, &mrb);
}
if (is_bh) {
blk_dec_in_flight(s->conf.conf.blk);
@ -1205,6 +1214,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
}
s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
blk_ram_registrar_init(&s->blk_ram_registrar, s->blk);
blk_set_dev_ops(s->blk, &virtio_block_ops, s);
blk_iostatus_enable(s->blk);
@ -1230,6 +1240,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev)
virtio_del_queue(vdev, i);
}
qemu_coroutine_dec_pool_size(conf->num_queues * conf->queue_size / 2);
blk_ram_registrar_destroy(&s->blk_ram_registrar);
qemu_del_vm_change_state_handler(s->change);
blockdev_mark_auto_del(s->blk);
virtio_cleanup(vdev);

View File

@ -822,6 +822,19 @@ static int ram_block_notify_add_single(RAMBlock *rb, void *opaque)
return 0;
}
static int ram_block_notify_remove_single(RAMBlock *rb, void *opaque)
{
const ram_addr_t max_size = qemu_ram_get_max_length(rb);
const ram_addr_t size = qemu_ram_get_used_length(rb);
void *host = qemu_ram_get_host_addr(rb);
RAMBlockNotifier *notifier = opaque;
if (host) {
notifier->ram_block_removed(notifier, host, size, max_size);
}
return 0;
}
void ram_block_notifier_add(RAMBlockNotifier *n)
{
QLIST_INSERT_HEAD(&ram_list.ramblock_notifiers, n, next);
@ -835,13 +848,18 @@ void ram_block_notifier_add(RAMBlockNotifier *n)
void ram_block_notifier_remove(RAMBlockNotifier *n)
{
QLIST_REMOVE(n, next);
if (n->ram_block_removed) {
qemu_ram_foreach_block(ram_block_notify_remove_single, n);
}
}
void ram_block_notify_add(void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;
RAMBlockNotifier *next;
QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_added) {
notifier->ram_block_added(notifier, host, size, max_size);
}
@ -851,8 +869,9 @@ void ram_block_notify_add(void *host, size_t size, size_t max_size)
void ram_block_notify_remove(void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;
RAMBlockNotifier *next;
QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_removed) {
notifier->ram_block_removed(notifier, host, size, max_size);
}
@ -862,8 +881,9 @@ void ram_block_notify_remove(void *host, size_t size, size_t max_size)
void ram_block_notify_resize(void *host, size_t old_size, size_t new_size)
{
RAMBlockNotifier *notifier;
RAMBlockNotifier *next;
QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_resized) {
notifier->ram_block_resized(notifier, host, old_size, new_size);
}

View File

@ -80,6 +80,15 @@ typedef enum {
*/
BDRV_REQ_MAY_UNMAP = 0x4,
/*
* An optimization hint when all QEMUIOVector elements are within
* previously registered bdrv_register_buf() memory ranges.
*
* Code that replaces the user's QEMUIOVector elements with bounce buffers
* must take care to clear this flag.
*/
BDRV_REQ_REGISTERED_BUF = 0x8,
BDRV_REQ_FUA = 0x10,
BDRV_REQ_WRITE_COMPRESSED = 0x20,

View File

@ -243,9 +243,15 @@ void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);
* Register/unregister a buffer for I/O. For example, VFIO drivers are
* interested to know the memory areas that would later be used for I/O, so
* that they can prepare IOMMU mapping etc., to get better performance.
*
* Buffers must not overlap and they must be unregistered with the same <host,
* size> values that they were registered with.
*
* Returns: true on success, false on failure
*/
void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size);
void bdrv_unregister_buf(BlockDriverState *bs, void *host);
bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
Error **errp);
void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size);
void bdrv_cancel_in_flight(BlockDriverState *bs);

View File

@ -433,9 +433,12 @@ struct BlockDriver {
* that it can do IOMMU mapping with VFIO etc., in order to get better
* performance. In the case of VFIO drivers, this callback is used to do
* DMA mapping for hot buffers.
*
* Returns: true on success, false on failure
*/
void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
bool (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size,
Error **errp);
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host, size_t size);
/*
* This field is modified only under the BQL, and is part of
@ -1051,7 +1054,7 @@ struct BlockDriverState {
/*
* Flags honored during pread
*/
unsigned int supported_read_flags;
BdrvRequestFlags supported_read_flags;
/*
* Flags honored during pwrite (so far: BDRV_REQ_FUA,
* BDRV_REQ_WRITE_UNCHANGED).
@ -1069,12 +1072,12 @@ struct BlockDriverState {
* flag), or they have to explicitly take the WRITE permission for
* their children.
*/
unsigned int supported_write_flags;
BdrvRequestFlags supported_write_flags;
/*
* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED)
*/
unsigned int supported_zero_flags;
BdrvRequestFlags supported_zero_flags;
/*
* Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
*
@ -1082,7 +1085,7 @@ struct BlockDriverState {
* that any added space reads as all zeros. If this can't be guaranteed,
* the operation must fail.
*/
unsigned int supported_truncate_flags;
BdrvRequestFlags supported_truncate_flags;
/* the following member gives a name to every node on the bs graph. */
char node_name[32];

View File

@ -92,6 +92,7 @@ void qemu_ram_set_uf_zeroable(RAMBlock *rb);
bool qemu_ram_is_migratable(RAMBlock *rb);
void qemu_ram_set_migratable(RAMBlock *rb);
void qemu_ram_unset_migratable(RAMBlock *rb);
int qemu_ram_get_fd(RAMBlock *rb);
size_t qemu_ram_pagesize(RAMBlock *block);
size_t qemu_ram_pagesize_largest(void);

View File

@ -19,6 +19,7 @@
#include "hw/block/block.h"
#include "sysemu/iothread.h"
#include "sysemu/block-backend.h"
#include "sysemu/block-ram-registrar.h"
#include "qom/object.h"
#define TYPE_VIRTIO_BLK "virtio-blk-device"
@ -64,6 +65,7 @@ struct VirtIOBlock {
struct VirtIOBlockDataPlane *dataplane;
uint64_t host_features;
size_t config_size;
BlockRAMRegistrar blk_ram_registrar;
};
typedef struct VirtIOBlockReq {

View File

@ -198,14 +198,25 @@ typedef struct CoQueue {
*/
void qemu_co_queue_init(CoQueue *queue);
typedef enum {
/*
* Enqueue at front instead of back. Use this to re-queue a request when
* its wait condition is not satisfied after being woken up.
*/
CO_QUEUE_WAIT_FRONT = 0x1,
} CoQueueWaitFlags;
/**
* Adds the current coroutine to the CoQueue and transfers control to the
* caller of the coroutine. The mutex is unlocked during the wait and
* locked again afterwards.
*/
#define qemu_co_queue_wait(queue, lock) \
qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock))
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock);
qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock), 0)
#define qemu_co_queue_wait_flags(queue, lock, flags) \
qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock), (flags))
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock,
CoQueueWaitFlags flags);
/**
* Removes the next coroutine from the CoQueue, and queue it to run after

View File

@ -106,8 +106,8 @@ void blk_io_limits_enable(BlockBackend *blk, const char *group);
void blk_io_limits_update_group(BlockBackend *blk, const char *group);
void blk_set_force_allow_inactivate(BlockBackend *blk);
void blk_register_buf(BlockBackend *blk, void *host, size_t size);
void blk_unregister_buf(BlockBackend *blk, void *host);
bool blk_register_buf(BlockBackend *blk, void *host, size_t size, Error **errp);
void blk_unregister_buf(BlockBackend *blk, void *host, size_t size);
const BdrvChild *blk_root(BlockBackend *blk);

View File

@ -0,0 +1,37 @@
/*
* BlockBackend RAM Registrar
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef BLOCK_RAM_REGISTRAR_H
#define BLOCK_RAM_REGISTRAR_H
#include "exec/ramlist.h"
/**
* struct BlockRAMRegistrar:
*
* Keeps RAMBlock memory registered with a BlockBackend using
* blk_register_buf() including hotplugged memory.
*
* Emulated devices or other BlockBackend users initialize a BlockRAMRegistrar
* with blk_ram_registrar_init() before submitting I/O requests with the
* BDRV_REQ_REGISTERED_BUF flag set.
*/
typedef struct {
BlockBackend *blk;
RAMBlockNotifier notifier;
bool ok;
} BlockRAMRegistrar;
void blk_ram_registrar_init(BlockRAMRegistrar *r, BlockBackend *blk);
void blk_ram_registrar_destroy(BlockRAMRegistrar *r);
/* Have all RAMBlocks been registered successfully? */
static inline bool blk_ram_registrar_ok(BlockRAMRegistrar *r)
{
return r->ok;
}
#endif /* BLOCK_RAM_REGISTRAR_H */

View File

@ -771,6 +771,13 @@ if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
required: get_option('virglrenderer'),
kwargs: static_kwargs)
endif
blkio = not_found
if not get_option('blkio').auto() or have_block
blkio = dependency('blkio',
method: 'pkg-config',
required: get_option('blkio'),
kwargs: static_kwargs)
endif
curl = not_found
if not get_option('curl').auto() or have_block
curl = dependency('libcurl', version: '>=7.29.0',
@ -1815,6 +1822,7 @@ config_host_data.set('CONFIG_LIBUDEV', libudev.found())
config_host_data.set('CONFIG_LZO', lzo.found())
config_host_data.set('CONFIG_MPATH', mpathpersist.found())
config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
config_host_data.set('CONFIG_BLKIO', blkio.found())
config_host_data.set('CONFIG_CURL', curl.found())
config_host_data.set('CONFIG_CURSES', curses.found())
config_host_data.set('CONFIG_GBM', gbm.found())
@ -3869,6 +3877,7 @@ summary_info += {'PAM': pam}
summary_info += {'iconv support': iconv}
summary_info += {'curses support': curses}
summary_info += {'virgl support': virgl}
summary_info += {'blkio support': blkio}
summary_info += {'curl support': curl}
summary_info += {'Multipath support': mpathpersist}
summary_info += {'PNG support': png}

View File

@ -117,6 +117,8 @@ option('bzip2', type : 'feature', value : 'auto',
description: 'bzip2 support for DMG images')
option('cap_ng', type : 'feature', value : 'auto',
description: 'cap_ng support')
option('blkio', type : 'feature', value : 'auto',
description: 'libblkio block device driver')
option('bpf', type : 'feature', value : 'auto',
description: 'eBPF support')
option('cocoa', type : 'feature', value : 'auto',

View File

@ -2951,11 +2951,18 @@
'file', 'snapshot-access', 'ftp', 'ftps', 'gluster',
{'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
{'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
'http', 'https', 'iscsi',
'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
'http', 'https',
{ 'name': 'io_uring', 'if': 'CONFIG_BLKIO' },
'iscsi',
'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme',
{ 'name': 'nvme-io_uring', 'if': 'CONFIG_BLKIO' },
'parallels', 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum',
'raw', 'rbd',
{ 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
'ssh', 'throttle', 'vdi', 'vhdx',
{ 'name': 'virtio-blk-vhost-user', 'if': 'CONFIG_BLKIO' },
{ 'name': 'virtio-blk-vhost-vdpa', 'if': 'CONFIG_BLKIO' },
'vmdk', 'vpc', 'vvfat' ] }
##
# @BlockdevOptionsFile:
@ -3678,6 +3685,58 @@
'*debug': 'int',
'*logfile': 'str' } }
##
# @BlockdevOptionsIoUring:
#
# Driver specific block device options for the io_uring backend.
#
# @filename: path to the image file
#
# Since: 7.2
##
{ 'struct': 'BlockdevOptionsIoUring',
'data': { 'filename': 'str' },
'if': 'CONFIG_BLKIO' }
##
# @BlockdevOptionsNvmeIoUring:
#
# Driver specific block device options for the nvme-io_uring backend.
#
# @filename: path to the image file
#
# Since: 7.2
##
{ 'struct': 'BlockdevOptionsNvmeIoUring',
'data': { 'filename': 'str' },
'if': 'CONFIG_BLKIO' }
##
# @BlockdevOptionsVirtioBlkVhostUser:
#
# Driver specific block device options for the virtio-blk-vhost-user backend.
#
# @path: path to the vhost-user UNIX domain socket.
#
# Since: 7.2
##
{ 'struct': 'BlockdevOptionsVirtioBlkVhostUser',
'data': { 'path': 'str' },
'if': 'CONFIG_BLKIO' }
##
# @BlockdevOptionsVirtioBlkVhostVdpa:
#
# Driver specific block device options for the virtio-blk-vhost-vdpa backend.
#
# @path: path to the vhost-vdpa character device.
#
# Since: 7.2
##
{ 'struct': 'BlockdevOptionsVirtioBlkVhostVdpa',
'data': { 'path': 'str' },
'if': 'CONFIG_BLKIO' }
##
# @IscsiTransport:
#
@ -4305,6 +4364,8 @@
'if': 'HAVE_HOST_BLOCK_DEVICE' },
'http': 'BlockdevOptionsCurlHttp',
'https': 'BlockdevOptionsCurlHttps',
'io_uring': { 'type': 'BlockdevOptionsIoUring',
'if': 'CONFIG_BLKIO' },
'iscsi': 'BlockdevOptionsIscsi',
'luks': 'BlockdevOptionsLUKS',
'nbd': 'BlockdevOptionsNbd',
@ -4312,6 +4373,8 @@
'null-aio': 'BlockdevOptionsNull',
'null-co': 'BlockdevOptionsNull',
'nvme': 'BlockdevOptionsNVMe',
'nvme-io_uring': { 'type': 'BlockdevOptionsNvmeIoUring',
'if': 'CONFIG_BLKIO' },
'parallels': 'BlockdevOptionsGenericFormat',
'preallocate':'BlockdevOptionsPreallocate',
'qcow2': 'BlockdevOptionsQcow2',
@ -4327,6 +4390,12 @@
'throttle': 'BlockdevOptionsThrottle',
'vdi': 'BlockdevOptionsGenericFormat',
'vhdx': 'BlockdevOptionsGenericFormat',
'virtio-blk-vhost-user':
{ 'type': 'BlockdevOptionsVirtioBlkVhostUser',
'if': 'CONFIG_BLKIO' },
'virtio-blk-vhost-vdpa':
{ 'type': 'BlockdevOptionsVirtioBlkVhostVdpa',
'if': 'CONFIG_BLKIO' },
'vmdk': 'BlockdevOptionsGenericCOWFormat',
'vpc': 'BlockdevOptionsGenericFormat',
'vvfat': 'BlockdevOptionsVVFAT'

View File

@ -4371,7 +4371,7 @@ static int img_bench(int argc, char **argv)
struct timeval t1, t2;
int i;
bool force_share = false;
size_t buf_size;
size_t buf_size = 0;
for (;;) {
static const struct option long_options[] = {
@ -4570,7 +4570,7 @@ static int img_bench(int argc, char **argv)
data.buf = blk_blockalign(blk, buf_size);
memset(data.buf, pattern, data.nrreq * data.bufsize);
blk_register_buf(blk, data.buf, buf_size);
blk_register_buf(blk, data.buf, buf_size, &error_fatal);
data.qiov = g_new(QEMUIOVector, data.nrreq);
for (i = 0; i < data.nrreq; i++) {
@ -4593,7 +4593,7 @@ static int img_bench(int argc, char **argv)
out:
if (data.buf) {
blk_unregister_buf(blk, data.buf);
blk_unregister_buf(blk, data.buf, buf_size);
}
qemu_vfree(data.buf);
blk_unref(blk);

View File

@ -67,6 +67,7 @@ meson_options_help() {
printf "%s\n" ' auth-pam PAM access control'
printf "%s\n" ' avx2 AVX2 optimizations'
printf "%s\n" ' avx512f AVX512F optimizations'
printf "%s\n" ' blkio libblkio block device driver'
printf "%s\n" ' bochs bochs image format support'
printf "%s\n" ' bpf eBPF support'
printf "%s\n" ' brlapi brlapi character device driver'
@ -198,6 +199,8 @@ _meson_option_parse() {
--disable-gcov) printf "%s" -Db_coverage=false ;;
--enable-lto) printf "%s" -Db_lto=true ;;
--disable-lto) printf "%s" -Db_lto=false ;;
--enable-blkio) printf "%s" -Dblkio=enabled ;;
--disable-blkio) printf "%s" -Dblkio=disabled ;;
--block-drv-ro-whitelist=*) quote_sh "-Dblock_drv_ro_whitelist=$2" ;;
--block-drv-rw-whitelist=*) quote_sh "-Dblock_drv_rw_whitelist=$2" ;;
--enable-block-drv-whitelist-in-tools) printf "%s" -Dblock_drv_whitelist_in_tools=true ;;

View File

@ -1748,6 +1748,11 @@ void qemu_ram_unset_migratable(RAMBlock *rb)
rb->flags &= ~RAM_MIGRATABLE;
}
int qemu_ram_get_fd(RAMBlock *rb)
{
return rb->fd;
}
/* Called with iothread lock held. */
void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
{

View File

@ -29,6 +29,7 @@ stub_ss.add(files('migr-blocker.c'))
stub_ss.add(files('module-opts.c'))
stub_ss.add(files('monitor.c'))
stub_ss.add(files('monitor-core.c'))
stub_ss.add(files('physmem.c'))
stub_ss.add(files('qemu-timer-notify-cb.c'))
stub_ss.add(files('qmp_memory_device.c'))
stub_ss.add(files('qmp-command-available.c'))

13
stubs/physmem.c Normal file
View File

@ -0,0 +1,13 @@
#include "qemu/osdep.h"
#include "exec/cpu-common.h"
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
ram_addr_t *offset)
{
return NULL;
}
int qemu_ram_get_fd(RAMBlock *rb)
{
return -1;
}

View File

@ -16,6 +16,9 @@ static void test_modules_load(const void *data)
int main(int argc, char *argv[])
{
const char *modules[] = {
#ifdef CONFIG_BLKIO
"block-", "blkio",
#endif
#ifdef CONFIG_CURL
"block-", "curl",
#endif

View File

@ -39,10 +39,15 @@ void qemu_co_queue_init(CoQueue *queue)
QSIMPLEQ_INIT(&queue->entries);
}
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock)
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock,
CoQueueWaitFlags flags)
{
Coroutine *self = qemu_coroutine_self();
QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
if (flags & CO_QUEUE_WAIT_FRONT) {
QSIMPLEQ_INSERT_HEAD(&queue->entries, self, co_queue_next);
} else {
QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
}
if (lock) {
qemu_lockable_unlock(lock);

View File

@ -847,10 +847,13 @@ void qemu_vfio_close(QEMUVFIOState *s)
if (!s) {
return;
}
ram_block_notifier_remove(&s->ram_notifier);
for (i = 0; i < s->nr_mappings; ++i) {
qemu_vfio_undo_mapping(s, &s->mappings[i], NULL);
}
ram_block_notifier_remove(&s->ram_notifier);
g_free(s->usable_iova_ranges);
s->nb_iova_ranges = 0;
qemu_vfio_reset(s);