From 4e90ccc28e53eb92ecbd0cdb67da454d783ea828 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 30 Jun 2016 11:19:30 +0300 Subject: spec/parallels: fix a mistake We have only one flag for now - Empty Image flag. The patch fixes unused bits specification and marks bit 1 as usused. Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Denis V. Lunev CC: Stefan Hajnoczi Signed-off-by: Stefan Hajnoczi --- docs/specs/parallels.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/specs/parallels.txt b/docs/specs/parallels.txt index b4fe2295fb..e9271eba5d 100644 --- a/docs/specs/parallels.txt +++ b/docs/specs/parallels.txt @@ -94,7 +94,7 @@ Bytes: Bit 0: Empty Image bit. If set, the image should be considered clear. - Bits 2-31: Unused. + Bits 1-31: Unused. 56 - 63: ext_off Format Extension offset, an offset, in sectors, from the start of -- cgit v1.2.1 From 0187f5c9cb172771ba85c66e3bf61f8cde6d6561 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Jul 2016 18:33:20 +0200 Subject: linux-aio: share one LinuxAioState within an AioContext This has better performance because it executes fewer system calls and does not use a bottom half per disk. Originally proposed by Ming Lei. [Changed #include "raw-aio.h" to "block/raw-aio.h" in win32-aio.c to fix build error as reported by Peter Maydell . --Stefan] Acked-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Message-id: 1467650000-51385-1-git-send-email-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi squash! linux-aio: share one LinuxAioState within an AioContext --- async.c | 23 ++++++++++ block/linux-aio.c | 10 ++-- block/raw-aio.h | 68 --------------------------- block/raw-posix.c | 119 ++++++------------------------------------------ block/raw-win32.c | 2 +- block/win32-aio.c | 2 +- include/block/aio.h | 13 ++++++ include/block/raw-aio.h | 68 +++++++++++++++++++++++++++ 8 files changed, 126 insertions(+), 179 deletions(-) delete mode 100644 block/raw-aio.h create mode 100644 include/block/raw-aio.h diff --git a/async.c b/async.c index b4bf205a0c..6caa98cd92 100644 --- a/async.c +++ b/async.c @@ -29,6 +29,7 @@ #include "block/thread-pool.h" #include "qemu/main-loop.h" #include "qemu/atomic.h" +#include "block/raw-aio.h" /***********************************************************/ /* bottom halves (can be seen as timers which expire ASAP) */ @@ -242,6 +243,14 @@ aio_ctx_finalize(GSource *source) qemu_bh_delete(ctx->notify_dummy_bh); thread_pool_free(ctx->thread_pool); +#ifdef CONFIG_LINUX_AIO + if (ctx->linux_aio) { + laio_detach_aio_context(ctx->linux_aio, ctx); + laio_cleanup(ctx->linux_aio); + ctx->linux_aio = NULL; + } +#endif + qemu_mutex_lock(&ctx->bh_lock); while (ctx->first_bh) { QEMUBH *next = ctx->first_bh->next; @@ -282,6 +291,17 @@ ThreadPool *aio_get_thread_pool(AioContext *ctx) return ctx->thread_pool; } +#ifdef CONFIG_LINUX_AIO +LinuxAioState *aio_get_linux_aio(AioContext *ctx) +{ + if (!ctx->linux_aio) { + ctx->linux_aio = laio_init(); + laio_attach_aio_context(ctx->linux_aio, ctx); + } + return ctx->linux_aio; +} +#endif + void aio_notify(AioContext *ctx) { /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs @@ -345,6 +365,9 @@ AioContext *aio_context_new(Error **errp) false, (EventNotifierHandler *) event_notifier_dummy_cb); +#ifdef CONFIG_LINUX_AIO + ctx->linux_aio = NULL; +#endif ctx->thread_pool = NULL; qemu_mutex_init(&ctx->bh_lock); rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx); diff --git a/block/linux-aio.c b/block/linux-aio.c index 5c104bd3cd..1d702a5fc6 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -50,6 +50,8 @@ typedef struct { } LaioQueue; struct LinuxAioState { + AioContext *aio_context; + io_context_t ctx; EventNotifier e; @@ -227,15 +229,14 @@ static void ioq_submit(LinuxAioState *s) void laio_io_plug(BlockDriverState *bs, LinuxAioState *s) { - assert(!s->io_q.plugged); - s->io_q.plugged = 1; + s->io_q.plugged++; } void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s) { assert(s->io_q.plugged); - s->io_q.plugged = 0; - if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { + if (--s->io_q.plugged == 0 && + !s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { ioq_submit(s); } } @@ -325,6 +326,7 @@ void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context) void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context) { + s->aio_context = new_context; s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s); aio_set_event_notifier(new_context, &s->e, false, qemu_laio_completion_cb); diff --git a/block/raw-aio.h b/block/raw-aio.h deleted file mode 100644 index a4cdbbf1b7..0000000000 --- a/block/raw-aio.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Declarations for AIO in the raw protocol - * - * Copyright IBM, Corp. 2008 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ -#ifndef QEMU_RAW_AIO_H -#define QEMU_RAW_AIO_H - -#include "qemu/coroutine.h" -#include "qemu/iov.h" - -/* AIO request types */ -#define QEMU_AIO_READ 0x0001 -#define QEMU_AIO_WRITE 0x0002 -#define QEMU_AIO_IOCTL 0x0004 -#define QEMU_AIO_FLUSH 0x0008 -#define QEMU_AIO_DISCARD 0x0010 -#define QEMU_AIO_WRITE_ZEROES 0x0020 -#define QEMU_AIO_TYPE_MASK \ - (QEMU_AIO_READ|QEMU_AIO_WRITE|QEMU_AIO_IOCTL|QEMU_AIO_FLUSH| \ - QEMU_AIO_DISCARD|QEMU_AIO_WRITE_ZEROES) - -/* AIO flags */ -#define QEMU_AIO_MISALIGNED 0x1000 -#define QEMU_AIO_BLKDEV 0x2000 - - -/* linux-aio.c - Linux native implementation */ -#ifdef CONFIG_LINUX_AIO -typedef struct LinuxAioState LinuxAioState; -LinuxAioState *laio_init(void); -void laio_cleanup(LinuxAioState *s); -int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd, - uint64_t offset, QEMUIOVector *qiov, int type); -BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque, int type); -void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context); -void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context); -void laio_io_plug(BlockDriverState *bs, LinuxAioState *s); -void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s); -#endif - -#ifdef _WIN32 -typedef struct QEMUWin32AIOState QEMUWin32AIOState; -QEMUWin32AIOState *win32_aio_init(void); -void win32_aio_cleanup(QEMUWin32AIOState *aio); -int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile); -BlockAIOCB *win32_aio_submit(BlockDriverState *bs, - QEMUWin32AIOState *aio, HANDLE hfile, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque, int type); -void win32_aio_detach_aio_context(QEMUWin32AIOState *aio, - AioContext *old_context); -void win32_aio_attach_aio_context(QEMUWin32AIOState *aio, - AioContext *new_context); -#endif - -#endif /* QEMU_RAW_AIO_H */ diff --git a/block/raw-posix.c b/block/raw-posix.c index d1c3bd8e47..20f4d7aa8d 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -32,7 +32,7 @@ #include "trace.h" #include "block/thread-pool.h" #include "qemu/iov.h" -#include "raw-aio.h" +#include "block/raw-aio.h" #include "qapi/util.h" #include "qapi/qmp/qstring.h" @@ -137,10 +137,6 @@ typedef struct BDRVRawState { int open_flags; size_t buf_align; -#ifdef CONFIG_LINUX_AIO - int use_aio; - LinuxAioState *aio_ctx; -#endif #ifdef CONFIG_XFS bool is_xfs:1; #endif @@ -154,9 +150,6 @@ typedef struct BDRVRawState { typedef struct BDRVRawReopenState { int fd; int open_flags; -#ifdef CONFIG_LINUX_AIO - int use_aio; -#endif } BDRVRawReopenState; static int fd_open(BlockDriverState *bs); @@ -374,58 +367,15 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags) } } -static void raw_detach_aio_context(BlockDriverState *bs) -{ #ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - - if (s->use_aio) { - laio_detach_aio_context(s->aio_ctx, bdrv_get_aio_context(bs)); - } -#endif -} - -static void raw_attach_aio_context(BlockDriverState *bs, - AioContext *new_context) +static bool raw_use_aio(int bdrv_flags) { -#ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - - if (s->use_aio) { - laio_attach_aio_context(s->aio_ctx, new_context); - } -#endif -} - -#ifdef CONFIG_LINUX_AIO -static int raw_set_aio(LinuxAioState **aio_ctx, int *use_aio, int bdrv_flags) -{ - int ret = -1; - assert(aio_ctx != NULL); - assert(use_aio != NULL); /* * Currently Linux do AIO only for files opened with O_DIRECT * specified so check NOCACHE flag too */ - if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == - (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) { - - /* if non-NULL, laio_init() has already been run */ - if (*aio_ctx == NULL) { - *aio_ctx = laio_init(); - if (!*aio_ctx) { - goto error; - } - } - *use_aio = 1; - } else { - *use_aio = 0; - } - - ret = 0; - -error: - return ret; + return (bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == + (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO); } #endif @@ -494,13 +444,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, s->fd = fd; #ifdef CONFIG_LINUX_AIO - if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) { - qemu_close(fd); - ret = -errno; - error_setg_errno(errp, -ret, "Could not set AIO state"); - goto fail; - } - if (!s->use_aio && (bdrv_flags & BDRV_O_NATIVE_AIO)) { + if (!raw_use_aio(bdrv_flags) && (bdrv_flags & BDRV_O_NATIVE_AIO)) { error_setg(errp, "aio=native was specified, but it requires " "cache.direct=on, which was not specified."); ret = -EINVAL; @@ -567,8 +511,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } #endif - raw_attach_aio_context(bs, bdrv_get_aio_context(bs)); - ret = 0; fail: if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { @@ -603,18 +545,6 @@ static int raw_reopen_prepare(BDRVReopenState *state, state->opaque = g_new0(BDRVRawReopenState, 1); raw_s = state->opaque; -#ifdef CONFIG_LINUX_AIO - raw_s->use_aio = s->use_aio; - - /* we can use s->aio_ctx instead of a copy, because the use_aio flag is - * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio() - * won't override aio_ctx if aio_ctx is non-NULL */ - if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) { - error_setg(errp, "Could not set AIO state"); - return -1; - } -#endif - if (s->type == FTYPE_CD) { raw_s->open_flags |= O_NONBLOCK; } @@ -689,9 +619,6 @@ static void raw_reopen_commit(BDRVReopenState *state) qemu_close(s->fd); s->fd = raw_s->fd; -#ifdef CONFIG_LINUX_AIO - s->use_aio = raw_s->use_aio; -#endif g_free(state->opaque); state->opaque = NULL; @@ -1329,9 +1256,10 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset, if (!bdrv_qiov_is_aligned(bs, qiov)) { type |= QEMU_AIO_MISALIGNED; #ifdef CONFIG_LINUX_AIO - } else if (s->use_aio) { + } else if (bs->open_flags & BDRV_O_NATIVE_AIO) { + LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs)); assert(qiov->size == bytes); - return laio_co_submit(bs, s->aio_ctx, s->fd, offset, qiov, type); + return laio_co_submit(bs, aio, s->fd, offset, qiov, type); #endif } } @@ -1357,9 +1285,9 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset, static void raw_aio_plug(BlockDriverState *bs) { #ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - if (s->use_aio) { - laio_io_plug(bs, s->aio_ctx); + if (bs->open_flags & BDRV_O_NATIVE_AIO) { + LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs)); + laio_io_plug(bs, aio); } #endif } @@ -1367,9 +1295,9 @@ static void raw_aio_plug(BlockDriverState *bs) static void raw_aio_unplug(BlockDriverState *bs) { #ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - if (s->use_aio) { - laio_io_unplug(bs, s->aio_ctx); + if (bs->open_flags & BDRV_O_NATIVE_AIO) { + LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs)); + laio_io_unplug(bs, aio); } #endif } @@ -1389,13 +1317,6 @@ static void raw_close(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; - raw_detach_aio_context(bs); - -#ifdef CONFIG_LINUX_AIO - if (s->use_aio) { - laio_cleanup(s->aio_ctx); - } -#endif if (s->fd >= 0) { qemu_close(s->fd); s->fd = -1; @@ -1954,9 +1875,6 @@ BlockDriver bdrv_file = { .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - .create_opts = &raw_create_opts, }; @@ -2402,9 +2320,6 @@ static BlockDriver bdrv_host_device = { .bdrv_probe_blocksizes = hdev_probe_blocksizes, .bdrv_probe_geometry = hdev_probe_geometry, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - /* generic scsi device */ #ifdef __linux__ .bdrv_aio_ioctl = hdev_aio_ioctl, @@ -2524,9 +2439,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - /* removable device support */ .bdrv_is_inserted = cdrom_is_inserted, .bdrv_eject = cdrom_eject, @@ -2657,9 +2569,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - /* removable device support */ .bdrv_is_inserted = cdrom_is_inserted, .bdrv_eject = cdrom_eject, diff --git a/block/raw-win32.c b/block/raw-win32.c index 62edb1a6cc..9b813d99ae 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -27,7 +27,7 @@ #include "qemu/timer.h" #include "block/block_int.h" #include "qemu/module.h" -#include "raw-aio.h" +#include "block/raw-aio.h" #include "trace.h" #include "block/thread-pool.h" #include "qemu/iov.h" diff --git a/block/win32-aio.c b/block/win32-aio.c index 2d509a9a7b..95e3ab1541 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -27,7 +27,7 @@ #include "block/block_int.h" #include "qemu/module.h" #include "block/aio.h" -#include "raw-aio.h" +#include "block/raw-aio.h" #include "qemu/event_notifier.h" #include "qemu/iov.h" #include diff --git a/include/block/aio.h b/include/block/aio.h index 88a64eeb3c..afd72a7516 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -47,6 +47,9 @@ typedef struct AioHandler AioHandler; typedef void QEMUBHFunc(void *opaque); typedef void IOHandler(void *opaque); +struct ThreadPool; +struct LinuxAioState; + struct AioContext { GSource source; @@ -119,6 +122,13 @@ struct AioContext { /* Thread pool for performing work and receiving completion callbacks */ struct ThreadPool *thread_pool; +#ifdef CONFIG_LINUX_AIO + /* State for native Linux AIO. Uses aio_context_acquire/release for + * locking. + */ + struct LinuxAioState *linux_aio; +#endif + /* TimerLists for calling timers - one per clock type */ QEMUTimerListGroup tlg; @@ -335,6 +345,9 @@ GSource *aio_get_g_source(AioContext *ctx); /* Return the ThreadPool bound to this AioContext */ struct ThreadPool *aio_get_thread_pool(AioContext *ctx); +/* Return the LinuxAioState bound to this AioContext */ +struct LinuxAioState *aio_get_linux_aio(AioContext *ctx); + /** * aio_timer_new: * @ctx: the aio context diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h new file mode 100644 index 0000000000..a4cdbbf1b7 --- /dev/null +++ b/include/block/raw-aio.h @@ -0,0 +1,68 @@ +/* + * Declarations for AIO in the raw protocol + * + * Copyright IBM, Corp. 2008 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ +#ifndef QEMU_RAW_AIO_H +#define QEMU_RAW_AIO_H + +#include "qemu/coroutine.h" +#include "qemu/iov.h" + +/* AIO request types */ +#define QEMU_AIO_READ 0x0001 +#define QEMU_AIO_WRITE 0x0002 +#define QEMU_AIO_IOCTL 0x0004 +#define QEMU_AIO_FLUSH 0x0008 +#define QEMU_AIO_DISCARD 0x0010 +#define QEMU_AIO_WRITE_ZEROES 0x0020 +#define QEMU_AIO_TYPE_MASK \ + (QEMU_AIO_READ|QEMU_AIO_WRITE|QEMU_AIO_IOCTL|QEMU_AIO_FLUSH| \ + QEMU_AIO_DISCARD|QEMU_AIO_WRITE_ZEROES) + +/* AIO flags */ +#define QEMU_AIO_MISALIGNED 0x1000 +#define QEMU_AIO_BLKDEV 0x2000 + + +/* linux-aio.c - Linux native implementation */ +#ifdef CONFIG_LINUX_AIO +typedef struct LinuxAioState LinuxAioState; +LinuxAioState *laio_init(void); +void laio_cleanup(LinuxAioState *s); +int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd, + uint64_t offset, QEMUIOVector *qiov, int type); +BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque, int type); +void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context); +void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context); +void laio_io_plug(BlockDriverState *bs, LinuxAioState *s); +void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s); +#endif + +#ifdef _WIN32 +typedef struct QEMUWin32AIOState QEMUWin32AIOState; +QEMUWin32AIOState *win32_aio_init(void); +void win32_aio_cleanup(QEMUWin32AIOState *aio); +int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile); +BlockAIOCB *win32_aio_submit(BlockDriverState *bs, + QEMUWin32AIOState *aio, HANDLE hfile, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque, int type); +void win32_aio_detach_aio_context(QEMUWin32AIOState *aio, + AioContext *old_context); +void win32_aio_attach_aio_context(QEMUWin32AIOState *aio, + AioContext *new_context); +#endif + +#endif /* QEMU_RAW_AIO_H */ -- cgit v1.2.1 From 6977d901c43f6c2fc811c4ca9bf45bf0af6bb689 Mon Sep 17 00:00:00 2001 From: Cao jin Date: Thu, 14 Jul 2016 21:10:43 +0800 Subject: aio_ctx_check: follow CODING_STYLE replace tab with spaces Signed-off-by: Cao jin Message-id: 1468501843-14927-1-git-send-email-caoj.fnst@cn.fujitsu.com Signed-off-by: Stefan Hajnoczi --- async.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/async.c b/async.c index 6caa98cd92..0e0efc340a 100644 --- a/async.c +++ b/async.c @@ -218,7 +218,7 @@ aio_ctx_check(GSource *source) for (bh = ctx->first_bh; bh; bh = bh->next) { if (!bh->deleted && bh->scheduled) { return true; - } + } } return aio_pending(ctx) || (timerlistgroup_deadline_ns(&ctx->tlg) == 0); } -- cgit v1.2.1 From 5e1b34a3fa0a0fbf46628aab10cc49f6f855520e Mon Sep 17 00:00:00 2001 From: Roman Pen Date: Wed, 13 Jul 2016 15:03:24 +0200 Subject: linux-aio: prevent submitting more than MAX_EVENTS Invoking io_setup(MAX_EVENTS) we ask kernel to create ring buffer for us with specified number of events. But kernel ring buffer allocation logic is a bit tricky (ring buffer is page size aligned + some percpu allocation are required) so eventually more than requested events number is allocated. From a userspace side we have to follow the convention and should not try to io_submit() more or logic, which consumes completed events, should be changed accordingly. The pitfall is in the following sequence: MAX_EVENTS = 128 io_setup(MAX_EVENTS) io_submit(MAX_EVENTS) io_submit(MAX_EVENTS) /* now 256 events are in-flight */ io_getevents(MAX_EVENTS) = 128 /* we can handle only 128 events at once, to be sure * that nothing is pended the io_getevents(MAX_EVENTS) * call must be invoked once more or hang will happen. */ To prevent the hang or reiteration of io_getevents() call this patch restricts the number of in-flights, which is now limited to MAX_EVENTS. Signed-off-by: Roman Pen Reviewed-by: Fam Zheng Reviewed-by: Paolo Bonzini Reviewed-by: Stefan Hajnoczi Message-id: 1468415004-31755-1-git-send-email-roman.penyaev@profitbricks.com Cc: Stefan Hajnoczi Cc: qemu-devel@nongnu.org Signed-off-by: Stefan Hajnoczi --- block/linux-aio.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/block/linux-aio.c b/block/linux-aio.c index 1d702a5fc6..de3548f2ab 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -28,8 +28,6 @@ */ #define MAX_EVENTS 128 -#define MAX_QUEUED_IO 128 - struct qemu_laiocb { BlockAIOCB common; Coroutine *co; @@ -44,7 +42,8 @@ struct qemu_laiocb { typedef struct { int plugged; - unsigned int n; + unsigned int in_queue; + unsigned int in_flight; bool blocked; QSIMPLEQ_HEAD(, qemu_laiocb) pending; } LaioQueue; @@ -131,6 +130,7 @@ static void qemu_laio_completion_bh(void *opaque) s->event_max = 0; return; /* no more events */ } + s->io_q.in_flight -= s->event_max; } /* Reschedule so nested event loops see currently pending completions */ @@ -192,7 +192,8 @@ static void ioq_init(LaioQueue *io_q) { QSIMPLEQ_INIT(&io_q->pending); io_q->plugged = 0; - io_q->n = 0; + io_q->in_queue = 0; + io_q->in_flight = 0; io_q->blocked = false; } @@ -200,14 +201,17 @@ static void ioq_submit(LinuxAioState *s) { int ret, len; struct qemu_laiocb *aiocb; - struct iocb *iocbs[MAX_QUEUED_IO]; + struct iocb *iocbs[MAX_EVENTS]; QSIMPLEQ_HEAD(, qemu_laiocb) completed; do { + if (s->io_q.in_flight >= MAX_EVENTS) { + break; + } len = 0; QSIMPLEQ_FOREACH(aiocb, &s->io_q.pending, next) { iocbs[len++] = &aiocb->iocb; - if (len == MAX_QUEUED_IO) { + if (s->io_q.in_flight + len >= MAX_EVENTS) { break; } } @@ -220,11 +224,12 @@ static void ioq_submit(LinuxAioState *s) abort(); } - s->io_q.n -= ret; + s->io_q.in_flight += ret; + s->io_q.in_queue -= ret; aiocb = container_of(iocbs[ret - 1], struct qemu_laiocb, iocb); QSIMPLEQ_SPLIT_AFTER(&s->io_q.pending, aiocb, next, &completed); } while (ret == len && !QSIMPLEQ_EMPTY(&s->io_q.pending)); - s->io_q.blocked = (s->io_q.n > 0); + s->io_q.blocked = (s->io_q.in_queue > 0); } void laio_io_plug(BlockDriverState *bs, LinuxAioState *s) @@ -264,9 +269,10 @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset, io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e)); QSIMPLEQ_INSERT_TAIL(&s->io_q.pending, laiocb, next); - s->io_q.n++; + s->io_q.in_queue++; if (!s->io_q.blocked && - (!s->io_q.plugged || s->io_q.n >= MAX_QUEUED_IO)) { + (!s->io_q.plugged || + s->io_q.in_flight + s->io_q.in_queue >= MAX_EVENTS)) { ioq_submit(s); } -- cgit v1.2.1 From 7e00346505feb94ee740d311621eb0bf4c14d6db Mon Sep 17 00:00:00 2001 From: Cao jin Date: Fri, 15 Jul 2016 18:28:44 +0800 Subject: aio-posix: remove useless parameter Parameter **errp of aio_context_setup() is useless, remove it and clean up the related code. Cc: Stefan Hajnoczi Cc: Fam Zheng Cc: Eric Blake Signed-off-by: Cao jin Reviewed-by: Eric Blake Message-id: 1468578524-23433-1-git-send-email-caoj.fnst@cn.fujitsu.com Signed-off-by: Stefan Hajnoczi --- aio-posix.c | 3 ++- aio-win32.c | 2 +- async.c | 8 ++------ include/block/aio.h | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/aio-posix.c b/aio-posix.c index 6006122e0b..43162a9f29 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -485,12 +485,13 @@ bool aio_poll(AioContext *ctx, bool blocking) return progress; } -void aio_context_setup(AioContext *ctx, Error **errp) +void aio_context_setup(AioContext *ctx) { #ifdef CONFIG_EPOLL_CREATE1 assert(!ctx->epollfd); ctx->epollfd = epoll_create1(EPOLL_CLOEXEC); if (ctx->epollfd == -1) { + fprintf(stderr, "Failed to create epoll instance: %s", strerror(errno)); ctx->epoll_available = false; } else { ctx->epoll_available = true; diff --git a/aio-win32.c b/aio-win32.c index 6aaa32a147..c8c249e260 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -371,6 +371,6 @@ bool aio_poll(AioContext *ctx, bool blocking) return progress; } -void aio_context_setup(AioContext *ctx, Error **errp) +void aio_context_setup(AioContext *ctx) { } diff --git a/async.c b/async.c index 0e0efc340a..3bca9b0adb 100644 --- a/async.c +++ b/async.c @@ -347,14 +347,10 @@ AioContext *aio_context_new(Error **errp) { int ret; AioContext *ctx; - Error *local_err = NULL; ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext)); - aio_context_setup(ctx, &local_err); - if (local_err) { - error_propagate(errp, local_err); - goto fail; - } + aio_context_setup(ctx); + ret = event_notifier_init(&ctx->notifier, false); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to initialize event notifier"); diff --git a/include/block/aio.h b/include/block/aio.h index afd72a7516..209551deb2 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -452,6 +452,6 @@ static inline bool aio_node_check(AioContext *ctx, bool is_external) * * Initialize the aio context. */ -void aio_context_setup(AioContext *ctx, Error **errp); +void aio_context_setup(AioContext *ctx); #endif -- cgit v1.2.1 From f8dccbb63463d72dcf273b583d41810a01feab26 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 15 Jul 2016 10:46:54 +0100 Subject: checkpatch: consider git extended headers valid patches Renames look like this with git-diff(1) when diff.renames = true is set: diff --git a/a b/b similarity index 100% rename from a rename to b This raises the "Does not appear to be a unified-diff format patch" error because checkpatch.pl only considers a diff valid if it contains at least one "@@" hunk. This patch accepts renames and copies too so that checkpatch.pl exits successfully when a diff only renames/copies files. The git diff extended header format is described on the git-diff(1) man page. Reported-by: Colin Lord Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake Message-id: 1468576014-28788-1-git-send-email-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- scripts/checkpatch.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index cf32c8f5fa..afa7f79f83 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1279,6 +1279,11 @@ sub process { } } +# Accept git diff extended headers as valid patches + if ($line =~ /^(?:rename|copy) (?:from|to) [\w\/\.\-]+\s*$/) { + $is_patch = 1; + } + #check the patch for a signoff: if ($line =~ /^\s*signed-off-by:/i) { # This is a signoff, if ugly, so do not double report. -- cgit v1.2.1 From ab3b9c1be8739f109596985588eb061b7f66c1d1 Mon Sep 17 00:00:00 2001 From: Cao jin Date: Mon, 18 Jul 2016 12:05:49 +0800 Subject: virtio-blk: dataplane cleanup No need duplicate the judgment, there is one in function entry. Cc: Stefan Hajnoczi Cc: Kevin Wolf Cc: Max Reitz Signed-off-by: Cao jin Reviewed-by: Fam Zheng Message-id: 1468814749-14510-1-git-send-email-caoj.fnst@cn.fujitsu.com Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 54b9ac1da6..704a763603 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -112,10 +112,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, s->vdev = vdev; s->conf = conf; - if (conf->iothread) { - s->iothread = conf->iothread; - object_ref(OBJECT(s->iothread)); - } + s->iothread = conf->iothread; + object_ref(OBJECT(s->iothread)); s->ctx = iothread_get_aio_context(s->iothread); s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); s->batch_notify_vqs = bitmap_new(conf->num_queues); -- cgit v1.2.1 From e1029ae26d96d5de78c2d9af5eddcea92e73a46a Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 18 Jul 2016 15:19:47 +0800 Subject: MAINTAINERS: Add include/block/aio.h to block I/O path section This file is actually the header for async.c and aio-*.c., so add it to the same section. Suggested-by: Max Reitz Signed-off-by: Fam Zheng Message-id: 1468826387-10473-1-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1d0e2c39ce..83e0f1347d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1027,6 +1027,7 @@ F: async.c F: aio-*.c F: block/io.c F: migration/block* +F: include/block/aio.h T: git git://github.com/stefanha/qemu.git block Block Jobs -- cgit v1.2.1