diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-07-08 22:17:28 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-07-08 22:17:28 +0100 |
commit | 53c0123118a15cd25fe81acfa9617ddcbb9258fe (patch) | |
tree | 80746153bae235f6e76783fe9d7339bbca2fbc09 | |
parent | 9db3065c62a983286d06c207f4981408cf42184d (diff) | |
parent | 9f460c64e13897117f35ffb61f6f5e0102cabc70 (diff) | |
download | qemu-53c0123118a15cd25fe81acfa9617ddcbb9258fe.zip qemu-53c0123118a15cd25fe81acfa9617ddcbb9258fe.tar.gz qemu-53c0123118a15cd25fe81acfa9617ddcbb9258fe.tar.bz2 |
Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/block-pull-request' into staging
Pull request
# gpg: Signature made Thu 08 Jul 2021 14:11:37 BST
# gpg: using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [full]
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" [full]
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8
* remotes/stefanha-gitlab/tags/block-pull-request:
block/io: Merge discard request alignments
block: Add backend_defaults property
block/file-posix: Optimize for macOS
util/async: print leaked BH name when AioContext finalizes
util/async: add a human-readable name to BHs for debugging
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | block/file-posix.c | 27 | ||||
-rw-r--r-- | block/io.c | 2 | ||||
-rw-r--r-- | hw/block/block.c | 42 | ||||
-rw-r--r-- | include/block/aio.h | 31 | ||||
-rw-r--r-- | include/hw/block/block.h | 3 | ||||
-rw-r--r-- | include/qemu/main-loop.h | 4 | ||||
-rw-r--r-- | tests/qemu-iotests/172.out | 38 | ||||
-rw-r--r-- | tests/unit/ptimer-test-stubs.c | 2 | ||||
-rw-r--r-- | util/async.c | 25 | ||||
-rw-r--r-- | util/main-loop.c | 4 |
10 files changed, 161 insertions, 17 deletions
diff --git a/block/file-posix.c b/block/file-posix.c index a26eab0..cb9bffe 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -46,6 +46,7 @@ #if defined(HAVE_HOST_BLOCK_DEVICE) #include <paths.h> #include <sys/param.h> +#include <sys/mount.h> #include <IOKit/IOKitLib.h> #include <IOKit/IOBSD.h> #include <IOKit/storage/IOMediaBSDClient.h> @@ -1254,6 +1255,15 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) return; } +#if defined(__APPLE__) && (__MACH__) + struct statfs buf; + + if (!fstatfs(s->fd, &buf)) { + bs->bl.opt_transfer = buf.f_iosize; + bs->bl.pdiscard_alignment = buf.f_bsize; + } +#endif + if (bs->sg || S_ISBLK(st.st_mode)) { int ret = hdev_get_max_hw_transfer(s->fd, &st); @@ -1591,6 +1601,7 @@ out: } } +#if defined(CONFIG_FALLOCATE) || defined(BLKZEROOUT) || defined(BLKDISCARD) static int translate_err(int err) { if (err == -ENODEV || err == -ENOSYS || err == -EOPNOTSUPP || @@ -1599,6 +1610,7 @@ static int translate_err(int err) } return err; } +#endif #ifdef CONFIG_FALLOCATE static int do_fallocate(int fd, int mode, off_t offset, off_t len) @@ -1811,16 +1823,27 @@ static int handle_aiocb_discard(void *opaque) } } while (errno == EINTR); - ret = -errno; + ret = translate_err(-errno); #endif } else { #ifdef CONFIG_FALLOCATE_PUNCH_HOLE ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, aiocb->aio_offset, aiocb->aio_nbytes); + ret = translate_err(-errno); +#elif defined(__APPLE__) && (__MACH__) + fpunchhole_t fpunchhole; + fpunchhole.fp_flags = 0; + fpunchhole.reserved = 0; + fpunchhole.fp_offset = aiocb->aio_offset; + fpunchhole.fp_length = aiocb->aio_nbytes; + if (fcntl(s->fd, F_PUNCHHOLE, &fpunchhole) == -1) { + ret = errno == ENODEV ? -ENOTSUP : -errno; + } else { + ret = 0; + } #endif } - ret = translate_err(ret); if (ret == -ENOTSUP) { s->has_discard = false; } @@ -125,6 +125,8 @@ void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll) static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src) { + dst->pdiscard_alignment = MAX(dst->pdiscard_alignment, + src->pdiscard_alignment); dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer); dst->max_transfer = MIN_NON_ZERO(dst->max_transfer, src->max_transfer); dst->max_hw_transfer = MIN_NON_ZERO(dst->max_hw_transfer, diff --git a/hw/block/block.c b/hw/block/block.c index 1e34573..d47ebf0 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -65,24 +65,58 @@ bool blkconf_blocksizes(BlockConf *conf, Error **errp) { BlockBackend *blk = conf->blk; BlockSizes blocksizes; - int backend_ret; + BlockDriverState *bs; + bool use_blocksizes; + bool use_bs; + + switch (conf->backend_defaults) { + case ON_OFF_AUTO_AUTO: + use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes); + use_bs = false; + break; + + case ON_OFF_AUTO_ON: + use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes); + bs = blk_bs(blk); + use_bs = bs; + break; + + case ON_OFF_AUTO_OFF: + use_blocksizes = false; + use_bs = false; + break; + + default: + abort(); + } - backend_ret = blk_probe_blocksizes(blk, &blocksizes); /* fill in detected values if they are not defined via qemu command line */ if (!conf->physical_block_size) { - if (!backend_ret) { + if (use_blocksizes) { conf->physical_block_size = blocksizes.phys; } else { conf->physical_block_size = BDRV_SECTOR_SIZE; } } if (!conf->logical_block_size) { - if (!backend_ret) { + if (use_blocksizes) { conf->logical_block_size = blocksizes.log; } else { conf->logical_block_size = BDRV_SECTOR_SIZE; } } + if (use_bs) { + if (!conf->opt_io_size) { + conf->opt_io_size = bs->bl.opt_transfer; + } + if (conf->discard_granularity == -1) { + if (bs->bl.pdiscard_alignment) { + conf->discard_granularity = bs->bl.pdiscard_alignment; + } else if (bs->bl.request_alignment != 1) { + conf->discard_granularity = bs->bl.request_alignment; + } + } + } if (conf->logical_block_size > conf->physical_block_size) { error_setg(errp, diff --git a/include/block/aio.h b/include/block/aio.h index 10fcae1..807edce 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -292,19 +292,44 @@ void aio_context_acquire(AioContext *ctx); void aio_context_release(AioContext *ctx); /** + * aio_bh_schedule_oneshot_full: Allocate a new bottom half structure that will + * run only once and as soon as possible. + * + * @name: A human-readable identifier for debugging purposes. + */ +void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + const char *name); + +/** * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run * only once and as soon as possible. + * + * A convenience wrapper for aio_bh_schedule_oneshot_full() that uses cb as the + * name string. */ -void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); +#define aio_bh_schedule_oneshot(ctx, cb, opaque) \ + aio_bh_schedule_oneshot_full((ctx), (cb), (opaque), (stringify(cb))) /** - * aio_bh_new: Allocate a new bottom half structure. + * aio_bh_new_full: Allocate a new bottom half structure. * * Bottom halves are lightweight callbacks whose invocation is guaranteed * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure * is opaque and must be allocated prior to its use. + * + * @name: A human-readable identifier for debugging purposes. + */ +QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + const char *name); + +/** + * aio_bh_new: Allocate a new bottom half structure + * + * A convenience wrapper for aio_bh_new_full() that uses the cb as the name + * string. */ -QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque); +#define aio_bh_new(ctx, cb, opaque) \ + aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb))) /** * aio_notify: Force processing of pending events. diff --git a/include/hw/block/block.h b/include/hw/block/block.h index c172cbe..5902c04 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -19,6 +19,7 @@ typedef struct BlockConf { BlockBackend *blk; + OnOffAuto backend_defaults; uint32_t physical_block_size; uint32_t logical_block_size; uint32_t min_io_size; @@ -48,6 +49,8 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) } #define DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf) \ + DEFINE_PROP_ON_OFF_AUTO("backend_defaults", _state, \ + _conf.backend_defaults, ON_OFF_AUTO_AUTO), \ DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \ _conf.logical_block_size), \ DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \ diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 98aef56..8dbc6fc 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -294,7 +294,9 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms); void qemu_fd_register(int fd); -QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); +#define qemu_bh_new(cb, opaque) \ + qemu_bh_new_full((cb), (opaque), (stringify(cb))) +QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name); void qemu_bh_schedule_idle(QEMUBH *bh); enum { diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out index d53f61d..4cf4d53 100644 --- a/tests/qemu-iotests/172.out +++ b/tests/qemu-iotests/172.out @@ -21,6 +21,7 @@ Testing: dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -48,6 +49,7 @@ Testing: -fda TEST_DIR/t.qcow2 dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -85,6 +87,7 @@ Testing: -fdb TEST_DIR/t.qcow2 dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -96,6 +99,7 @@ Testing: -fdb TEST_DIR/t.qcow2 dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -137,6 +141,7 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2 dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -148,6 +153,7 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2 dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -190,6 +196,7 @@ Testing: -fdb dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -201,6 +208,7 @@ Testing: -fdb dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -228,6 +236,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -265,6 +274,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1 dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -276,6 +286,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1 dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -317,6 +328,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -328,6 +340,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -373,6 +386,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0 dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -410,6 +424,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1 dev: floppy, id "" unit = 1 (0x1) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -447,6 +462,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 1 (0x1) drive = "none1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -458,6 +474,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -509,6 +526,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 1 (0x1) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -520,6 +538,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -562,6 +581,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 1 (0x1) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -573,6 +593,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -615,6 +636,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -626,6 +648,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -668,6 +691,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -679,6 +703,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -730,6 +755,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q dev: floppy, id "" unit = 1 (0x1) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -741,6 +767,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -783,6 +810,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q dev: floppy, id "" unit = 1 (0x1) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -794,6 +822,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -842,6 +871,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -909,6 +939,7 @@ Testing: -device floppy dev: floppy, id "" unit = 0 (0x0) drive = "" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -933,6 +964,7 @@ Testing: -device floppy,drive-type=120 dev: floppy, id "" unit = 0 (0x0) drive = "" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -957,6 +989,7 @@ Testing: -device floppy,drive-type=144 dev: floppy, id "" unit = 0 (0x0) drive = "" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -981,6 +1014,7 @@ Testing: -device floppy,drive-type=288 dev: floppy, id "" unit = 0 (0x0) drive = "" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -1008,6 +1042,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -1045,6 +1080,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -1085,6 +1121,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) @@ -1122,6 +1159,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica dev: floppy, id "" unit = 0 (0x0) drive = "none0" + backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) min_io_size = 0 (0 B) diff --git a/tests/unit/ptimer-test-stubs.c b/tests/unit/ptimer-test-stubs.c index 7f801a4..2a3ef58 100644 --- a/tests/unit/ptimer-test-stubs.c +++ b/tests/unit/ptimer-test-stubs.c @@ -108,7 +108,7 @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask) return deadline; } -QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) +QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name) { QEMUBH *bh = g_new(QEMUBH, 1); diff --git a/util/async.c b/util/async.c index 5d9b7cc..9a41591 100644 --- a/util/async.c +++ b/util/async.c @@ -57,6 +57,7 @@ enum { struct QEMUBH { AioContext *ctx; + const char *name; QEMUBHFunc *cb; void *opaque; QSLIST_ENTRY(QEMUBH) next; @@ -107,7 +108,8 @@ static QEMUBH *aio_bh_dequeue(BHList *head, unsigned *flags) return bh; } -void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque) +void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, + void *opaque, const char *name) { QEMUBH *bh; bh = g_new(QEMUBH, 1); @@ -115,11 +117,13 @@ void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque) .ctx = ctx, .cb = cb, .opaque = opaque, + .name = name, }; aio_bh_enqueue(bh, BH_SCHEDULED | BH_ONESHOT); } -QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) +QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + const char *name) { QEMUBH *bh; bh = g_new(QEMUBH, 1); @@ -127,6 +131,7 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) .ctx = ctx, .cb = cb, .opaque = opaque, + .name = name, }; return bh; } @@ -339,8 +344,20 @@ aio_ctx_finalize(GSource *source) assert(QSIMPLEQ_EMPTY(&ctx->bh_slice_list)); while ((bh = aio_bh_dequeue(&ctx->bh_list, &flags))) { - /* qemu_bh_delete() must have been called on BHs in this AioContext */ - assert(flags & BH_DELETED); + /* + * qemu_bh_delete() must have been called on BHs in this AioContext. In + * many cases memory leaks, hangs, or inconsistent state occur when a + * BH is leaked because something still expects it to run. + * + * If you hit this, fix the lifecycle of the BH so that + * qemu_bh_delete() and any associated cleanup is called before the + * AioContext is finalized. + */ + if (unlikely(!(flags & BH_DELETED))) { + fprintf(stderr, "%s: BH '%s' leaked, aborting...\n", + __func__, bh->name); + abort(); + } g_free(bh); } diff --git a/util/main-loop.c b/util/main-loop.c index 4ae5b23..06b18b1 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -544,9 +544,9 @@ void main_loop_wait(int nonblocking) /* Functions to operate on the main QEMU AioContext. */ -QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) +QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name) { - return aio_bh_new(qemu_aio_context, cb, opaque); + return aio_bh_new_full(qemu_aio_context, cb, opaque, name); } /* |