From 65a9bb25d6b7a4bb41edb102fa0363d81800b417 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 26 Jun 2014 13:23:17 +0200 Subject: block: New bdrv_nb_sectors() A call to retrieve the image size converts between bytes and sectors several times: * BlockDriver method bdrv_getlength() returns bytes. * refresh_total_sectors() converts to sectors, rounding up, and stores in total_sectors. * bdrv_getlength() converts total_sectors back to bytes (now rounded up to a multiple of the sector size). * Callers wanting sectors rather bytes convert it right back. Example: bdrv_get_geometry(). bdrv_nb_sectors() provides a way to omit the last two conversions. It's exactly bdrv_getlength() with the conversion to bytes omitted. It's functionally like bdrv_get_geometry() without its odd error handling. Reimplement bdrv_getlength() and bdrv_get_geometry() on top of bdrv_nb_sectors(). The next patches will convert some users of bdrv_getlength() to bdrv_nb_sectors(). Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Benoit Canet Signed-off-by: Stefan Hajnoczi --- include/block/block.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/block') diff --git a/include/block/block.h b/include/block/block.h index f08471d7e1..d4c816d738 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -275,6 +275,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, const char *backing_file); int bdrv_get_backing_file_depth(BlockDriverState *bs); int bdrv_truncate(BlockDriverState *bs, int64_t offset); +int64_t bdrv_nb_sectors(BlockDriverState *bs); int64_t bdrv_getlength(BlockDriverState *bs); int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); -- cgit v1.2.3-55-g7522 From ac2662a913ee5854b1269256adbdc14e57ba480a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 7 Jul 2014 15:15:52 +0200 Subject: coroutine: make pool size dynamic Allow coroutine users to adjust the pool size. For example, if the guest has multiple emulated disk drives we should keep around more coroutines. Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake --- include/block/coroutine.h | 11 +++++++++++ qemu-coroutine.c | 26 +++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'include/block') diff --git a/include/block/coroutine.h b/include/block/coroutine.h index b408f96b82..b9b7f488c9 100644 --- a/include/block/coroutine.h +++ b/include/block/coroutine.h @@ -223,4 +223,15 @@ void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type, * Note that this function clobbers the handlers for the file descriptor. */ void coroutine_fn yield_until_fd_readable(int fd); + +/** + * Add or subtract from the coroutine pool size + * + * The coroutine implementation keeps a pool of coroutines to be reused by + * qemu_coroutine_create(). This makes coroutine creation cheap. Heavy + * coroutine users should call this to reserve pool space. Call it again with + * a negative number to release pool space. + */ +void qemu_coroutine_adjust_pool_size(int n); + #endif /* QEMU_COROUTINE_H */ diff --git a/qemu-coroutine.c b/qemu-coroutine.c index 470852100a..bd574aa1b5 100644 --- a/qemu-coroutine.c +++ b/qemu-coroutine.c @@ -19,14 +19,14 @@ #include "block/coroutine_int.h" enum { - /* Maximum free pool size prevents holding too many freed coroutines */ - POOL_MAX_SIZE = 64, + POOL_DEFAULT_SIZE = 64, }; /** Free list to speed up creation */ static QemuMutex pool_lock; static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool); static unsigned int pool_size; +static unsigned int pool_max_size = POOL_DEFAULT_SIZE; Coroutine *qemu_coroutine_create(CoroutineEntry *entry) { @@ -55,7 +55,7 @@ static void coroutine_delete(Coroutine *co) { if (CONFIG_COROUTINE_POOL) { qemu_mutex_lock(&pool_lock); - if (pool_size < POOL_MAX_SIZE) { + if (pool_size < pool_max_size) { QSLIST_INSERT_HEAD(&pool, co, pool_next); co->caller = NULL; pool_size++; @@ -137,3 +137,23 @@ void coroutine_fn qemu_coroutine_yield(void) self->caller = NULL; coroutine_swap(self, to); } + +void qemu_coroutine_adjust_pool_size(int n) +{ + qemu_mutex_lock(&pool_lock); + + pool_max_size += n; + + /* Callers should never take away more than they added */ + assert(pool_max_size >= POOL_DEFAULT_SIZE); + + /* Trim oversized pool down to new max */ + while (pool_size > pool_max_size) { + Coroutine *co = QSLIST_FIRST(&pool); + QSLIST_REMOVE_HEAD(&pool, pool_next); + pool_size--; + qemu_coroutine_delete(co); + } + + qemu_mutex_unlock(&pool_lock); +} -- cgit v1.2.3-55-g7522 From 7d2a35cc921ea4832083a7e8598461868bb538ce Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 20 May 2014 12:24:05 +0200 Subject: block: Introduce qemu_try_blockalign() This function returns NULL instead of aborting when an allocation fails. Signed-off-by: Kevin Wolf Reviewed-by: Benoit Canet --- block.c | 13 +++++++++++++ include/block/block.h | 1 + include/qemu/osdep.h | 1 + util/oslib-posix.c | 16 ++++++++++------ util/oslib-win32.c | 9 +++++++-- 5 files changed, 32 insertions(+), 8 deletions(-) (limited to 'include/block') diff --git a/block.c b/block.c index d7cb7d48fa..3365c05b9d 100644 --- a/block.c +++ b/block.c @@ -5258,6 +5258,19 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size) return qemu_memalign(bdrv_opt_mem_align(bs), size); } +void *qemu_try_blockalign(BlockDriverState *bs, size_t size) +{ + size_t align = bdrv_opt_mem_align(bs); + + /* Ensure that NULL is never returned on success */ + assert(align > 0); + if (size == 0) { + size = align; + } + + return qemu_try_memalign(align, size); +} + /* * Check if all memory in this vector is sector aligned. */ diff --git a/include/block/block.h b/include/block/block.h index d4c816d738..e94b701667 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -455,6 +455,7 @@ void bdrv_img_create(const char *filename, const char *fmt, size_t bdrv_opt_mem_align(BlockDriverState *bs); void bdrv_set_guest_block_size(BlockDriverState *bs, int align); void *qemu_blockalign(BlockDriverState *bs, size_t size); +void *qemu_try_blockalign(BlockDriverState *bs, size_t size); bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov); struct HBitmapIter; diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 8480d523f0..9dd43fc2db 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -95,6 +95,7 @@ typedef signed int int_fast16_t; #define qemu_printf printf int qemu_daemon(int nochdir, int noclose); +void *qemu_try_memalign(size_t alignment, size_t size); void *qemu_memalign(size_t alignment, size_t size); void *qemu_anon_ram_alloc(size_t size); void qemu_vfree(void *ptr); diff --git a/util/oslib-posix.c b/util/oslib-posix.c index cdbfb2e270..016a047cfc 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -94,7 +94,7 @@ void *qemu_oom_check(void *ptr) return ptr; } -void *qemu_memalign(size_t alignment, size_t size) +void *qemu_try_memalign(size_t alignment, size_t size) { void *ptr; @@ -106,19 +106,23 @@ void *qemu_memalign(size_t alignment, size_t size) int ret; ret = posix_memalign(&ptr, alignment, size); if (ret != 0) { - fprintf(stderr, "Failed to allocate %zu B: %s\n", - size, strerror(ret)); - abort(); + errno = ret; + ptr = NULL; } #elif defined(CONFIG_BSD) - ptr = qemu_oom_check(valloc(size)); + ptr = valloc(size); #else - ptr = qemu_oom_check(memalign(alignment, size)); + ptr = memalign(alignment, size); #endif trace_qemu_memalign(alignment, size, ptr); return ptr; } +void *qemu_memalign(size_t alignment, size_t size) +{ + return qemu_oom_check(qemu_try_memalign(alignment, size)); +} + /* alloc shared memory pages */ void *qemu_anon_ram_alloc(size_t size) { diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 507cedd84d..a3eab4acba 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -50,18 +50,23 @@ void *qemu_oom_check(void *ptr) return ptr; } -void *qemu_memalign(size_t alignment, size_t size) +void *qemu_try_memalign(size_t alignment, size_t size) { void *ptr; if (!size) { abort(); } - ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); + ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); trace_qemu_memalign(alignment, size, ptr); return ptr; } +void *qemu_memalign(size_t alignment, size_t size) +{ + return qemu_oom_check(qemu_try_memalign(alignment, size)); +} + void *qemu_anon_ram_alloc(size_t size) { void *ptr; -- cgit v1.2.3-55-g7522