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:
commit
75d30fde55
@ -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
14
block.c
@ -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
1008
block/blkio.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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) {
|
||||
|
@ -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,
|
||||
|
58
block/block-ram-registrar.c
Normal file
58
block/block-ram-registrar.c
Normal 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);
|
||||
}
|
||||
}
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
101
block/io.c
101
block/io.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]],
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
20
block/nvme.c
20
block/nvme.c
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
37
include/sysemu/block-ram-registrar.h
Normal file
37
include/sysemu/block-ram-registrar.h
Normal 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 */
|
@ -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}
|
||||
|
@ -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',
|
||||
|
@ -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'
|
||||
|
@ -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);
|
||||
|
@ -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 ;;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
13
stubs/physmem.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user