Makefile | 8 + block/block-gen.h | 55 ++++ block/coroutines.h | 66 +++++ include/block/block.h | 25 +- include/block/generated-co-wrapper.h | 35 +++ block.c | 97 +------ block/io.c | 383 ++++----------------------- tests/test-bdrv-drain.c | 2 +- block/Makefile.objs | 1 + scripts/coroutine-wrapper.py | 173 ++++++++++++ 10 files changed, 417 insertions(+), 428 deletions(-) create mode 100644 block/block-gen.h create mode 100644 block/coroutines.h create mode 100644 include/block/generated-co-wrapper.h create mode 100755 scripts/coroutine-wrapper.py
Hi all! The aim of the series is to reduce code-duplication and writing parameters structure-packing by hand around coroutine function wrappers. It's an alternative to "[PATCH v3] block: Factor out bdrv_run_co()" patch. Benefits: - no code duplication - less indirection v5: mostly by Eric's suggestions: 01: new 02: tweak commit message 03: - fix type in commit message - rebase on 01 - keep Eric's r-b 04: - conversion splitted to 05 - script mostly rewritten - use f-strings for templating - add copyright to generated file header - wrap long lines if clang-format available - fix makefiles 05: splitted from 04 mechanical conversion 06: tweak commit message, add Eric's r-b 07: add Eric's r-b For convenience I attach generated block/block-gen.c file below. Vladimir Sementsov-Ogievskiy (7): block: return error-code from bdrv_invalidate_cache block/io: refactor coroutine wrappers block: declare some coroutine functions in block/coroutines.h scripts: add coroutine-wrapper.py block: generate coroutine-wrapper code block: drop bdrv_prwv block/io: refactor save/load vmstate Makefile | 8 + block/block-gen.h | 55 ++++ block/coroutines.h | 66 +++++ include/block/block.h | 25 +- include/block/generated-co-wrapper.h | 35 +++ block.c | 97 +------ block/io.c | 383 ++++----------------------- tests/test-bdrv-drain.c | 2 +- block/Makefile.objs | 1 + scripts/coroutine-wrapper.py | 173 ++++++++++++ 10 files changed, 417 insertions(+), 428 deletions(-) create mode 100644 block/block-gen.h create mode 100644 block/coroutines.h create mode 100644 include/block/generated-co-wrapper.h create mode 100755 scripts/coroutine-wrapper.py ===== Generated block/block-gen.c ====== /* * File is generated by scripts/coroutine-wrapper.py * * Copyright (c) 2020 Virtuozzo International GmbH. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" #include "block/coroutines.h" #include "block/block-gen.h" /* * Wrappers for bdrv_co_truncate */ typedef struct BdrvCoTruncate { BdrvPollCo poll_state; BdrvChild *child; int64_t offset; bool exact; PreallocMode prealloc; BdrvRequestFlags flags; Error **errp; } BdrvCoTruncate; static void coroutine_fn bdrv_co_truncate_entry(void *opaque) { BdrvCoTruncate *s = opaque; s->poll_state.ret = bdrv_co_truncate(s->child, s->offset, s->exact, s->prealloc, s->flags, s->errp); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) { if (qemu_in_coroutine()) { return bdrv_co_truncate(child, offset, exact, prealloc, flags, errp); } else { BdrvCoTruncate s = { .poll_state.bs = child->bs, .poll_state.in_progress = true, .child = child, .offset = offset, .exact = exact, .prealloc = prealloc, .flags = flags, .errp = errp, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_truncate_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_check */ typedef struct BdrvCoCheck { BdrvPollCo poll_state; BlockDriverState *bs; BdrvCheckResult *res; BdrvCheckMode fix; } BdrvCoCheck; static void coroutine_fn bdrv_co_check_entry(void *opaque) { BdrvCoCheck *s = opaque; s->poll_state.ret = bdrv_co_check(s->bs, s->res, s->fix); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) { if (qemu_in_coroutine()) { return bdrv_co_check(bs, res, fix); } else { BdrvCoCheck s = { .poll_state.bs = bs, .poll_state.in_progress = true, .bs = bs, .res = res, .fix = fix, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_check_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_invalidate_cache */ typedef struct BdrvCoInvalidateCache { BdrvPollCo poll_state; BlockDriverState *bs; Error **errp; } BdrvCoInvalidateCache; static void coroutine_fn bdrv_co_invalidate_cache_entry(void *opaque) { BdrvCoInvalidateCache *s = opaque; s->poll_state.ret = bdrv_co_invalidate_cache(s->bs, s->errp); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_invalidate_cache(BlockDriverState *bs, Error **errp) { if (qemu_in_coroutine()) { return bdrv_co_invalidate_cache(bs, errp); } else { BdrvCoInvalidateCache s = { .poll_state.bs = bs, .poll_state.in_progress = true, .bs = bs, .errp = errp, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_invalidate_cache_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_flush */ typedef struct BdrvCoFlush { BdrvPollCo poll_state; BlockDriverState *bs; } BdrvCoFlush; static void coroutine_fn bdrv_co_flush_entry(void *opaque) { BdrvCoFlush *s = opaque; s->poll_state.ret = bdrv_co_flush(s->bs); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_flush(BlockDriverState *bs) { if (qemu_in_coroutine()) { return bdrv_co_flush(bs); } else { BdrvCoFlush s = { .poll_state.bs = bs, .poll_state.in_progress = true, .bs = bs, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_flush_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_pdiscard */ typedef struct BdrvCoPdiscard { BdrvPollCo poll_state; BdrvChild *child; int64_t offset; int64_t bytes; } BdrvCoPdiscard; static void coroutine_fn bdrv_co_pdiscard_entry(void *opaque) { BdrvCoPdiscard *s = opaque; s->poll_state.ret = bdrv_co_pdiscard(s->child, s->offset, s->bytes); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes) { if (qemu_in_coroutine()) { return bdrv_co_pdiscard(child, offset, bytes); } else { BdrvCoPdiscard s = { .poll_state.bs = child->bs, .poll_state.in_progress = true, .child = child, .offset = offset, .bytes = bytes, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_pdiscard_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_readv_vmstate */ typedef struct BdrvCoReadvVmstate { BdrvPollCo poll_state; BlockDriverState *bs; QEMUIOVector *qiov; int64_t pos; } BdrvCoReadvVmstate; static void coroutine_fn bdrv_co_readv_vmstate_entry(void *opaque) { BdrvCoReadvVmstate *s = opaque; s->poll_state.ret = bdrv_co_readv_vmstate(s->bs, s->qiov, s->pos); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { if (qemu_in_coroutine()) { return bdrv_co_readv_vmstate(bs, qiov, pos); } else { BdrvCoReadvVmstate s = { .poll_state.bs = bs, .poll_state.in_progress = true, .bs = bs, .qiov = qiov, .pos = pos, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_readv_vmstate_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_writev_vmstate */ typedef struct BdrvCoWritevVmstate { BdrvPollCo poll_state; BlockDriverState *bs; QEMUIOVector *qiov; int64_t pos; } BdrvCoWritevVmstate; static void coroutine_fn bdrv_co_writev_vmstate_entry(void *opaque) { BdrvCoWritevVmstate *s = opaque; s->poll_state.ret = bdrv_co_writev_vmstate(s->bs, s->qiov, s->pos); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { if (qemu_in_coroutine()) { return bdrv_co_writev_vmstate(bs, qiov, pos); } else { BdrvCoWritevVmstate s = { .poll_state.bs = bs, .poll_state.in_progress = true, .bs = bs, .qiov = qiov, .pos = pos, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_writev_vmstate_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_preadv */ typedef struct BdrvCoPreadv { BdrvPollCo poll_state; BdrvChild *child; int64_t offset; unsigned int bytes; QEMUIOVector *qiov; BdrvRequestFlags flags; } BdrvCoPreadv; static void coroutine_fn bdrv_co_preadv_entry(void *opaque) { BdrvCoPreadv *s = opaque; s->poll_state.ret = bdrv_co_preadv(s->child, s->offset, s->bytes, s->qiov, s->flags); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_preadv(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { if (qemu_in_coroutine()) { return bdrv_co_preadv(child, offset, bytes, qiov, flags); } else { BdrvCoPreadv s = { .poll_state.bs = child->bs, .poll_state.in_progress = true, .child = child, .offset = offset, .bytes = bytes, .qiov = qiov, .flags = flags, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_preadv_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_pwritev */ typedef struct BdrvCoPwritev { BdrvPollCo poll_state; BdrvChild *child; int64_t offset; unsigned int bytes; QEMUIOVector *qiov; BdrvRequestFlags flags; } BdrvCoPwritev; static void coroutine_fn bdrv_co_pwritev_entry(void *opaque) { BdrvCoPwritev *s = opaque; s->poll_state.ret = bdrv_co_pwritev(s->child, s->offset, s->bytes, s->qiov, s->flags); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_pwritev(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { if (qemu_in_coroutine()) { return bdrv_co_pwritev(child, offset, bytes, qiov, flags); } else { BdrvCoPwritev s = { .poll_state.bs = child->bs, .poll_state.in_progress = true, .child = child, .offset = offset, .bytes = bytes, .qiov = qiov, .flags = flags, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_pwritev_entry, &s); return bdrv_poll_co(&s.poll_state); } } /* * Wrappers for bdrv_co_common_block_status_above */ typedef struct BdrvCoCommonBlockStatusAbove { BdrvPollCo poll_state; BlockDriverState *bs; BlockDriverState *base; bool want_zero; int64_t offset; int64_t bytes; int64_t *pnum; int64_t *map; BlockDriverState **file; } BdrvCoCommonBlockStatusAbove; static void coroutine_fn bdrv_co_common_block_status_above_entry(void *opaque) { BdrvCoCommonBlockStatusAbove *s = opaque; s->poll_state.ret = bdrv_co_common_block_status_above( s->bs, s->base, s->want_zero, s->offset, s->bytes, s->pnum, s->map, s->file); s->poll_state.in_progress = false; bdrv_poll_co__on_exit(); } int bdrv_common_block_status_above(BlockDriverState *bs, BlockDriverState *base, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { if (qemu_in_coroutine()) { return bdrv_co_common_block_status_above(bs, base, want_zero, offset, bytes, pnum, map, file); } else { BdrvCoCommonBlockStatusAbove s = { .poll_state.bs = bs, .poll_state.in_progress = true, .bs = bs, .base = base, .want_zero = want_zero, .offset = offset, .bytes = bytes, .pnum = pnum, .map = map, .file = file, }; s.poll_state.co = qemu_coroutine_create(bdrv_co_common_block_status_above_entry, &s); return bdrv_poll_co(&s.poll_state); } } ======================================== -- 2.21.0
Patchew URL: https://patchew.org/QEMU/20200527203733.16129-1-vsementsov@virtuozzo.com/ Hi, This series failed the docker-quick@centos7 build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. === TEST SCRIPT BEGIN === #!/bin/bash make docker-image-centos7 V=1 NETWORK=1 time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 === TEST SCRIPT END === TypeError: __init__() got an unexpected keyword argument 'capture_output' CC /tmp/qemu-test/build/slirp/src/bootp.o GEN ui/input-keymap-usb-to-qcode.c make: *** [block/block-gen.c] Error 1 make: *** Deleting file `block/block-gen.c' make: *** Waiting for unfinished jobs.... GEN ui/input-keymap-win32-to-qcode.c --- raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=7a4c9c87bb7b4b61ae99142b8ccd4c12', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-vw5w7k6z/src/docker-src.2020-05-27-17.44.40.573:/var/tmp/qemu:z,ro', 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2. filter=--filter=label=com.qemu.instance.uuid=7a4c9c87bb7b4b61ae99142b8ccd4c12 make[1]: *** [docker-run] Error 1 make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-vw5w7k6z/src' make: *** [docker-run-test-quick@centos7] Error 2 real 1m57.906s user 0m8.475s The full log is available at http://patchew.org/logs/20200527203733.16129-1-vsementsov@virtuozzo.com/testing.docker-quick@centos7/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-devel@redhat.com
On 5/27/20 4:46 PM, no-reply@patchew.org wrote: > Patchew URL: https://patchew.org/QEMU/20200527203733.16129-1-vsementsov@virtuozzo.com/ > > > > Hi, > > This series failed the docker-quick@centos7 build test. Please find the testing commands and > their output below. If you have Docker installed, you can probably reproduce it > locally. > > === TEST SCRIPT BEGIN === > #!/bin/bash > make docker-image-centos7 V=1 NETWORK=1 > time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 > === TEST SCRIPT END === > > TypeError: __init__() got an unexpected keyword argument 'capture_output' > CC /tmp/qemu-test/build/slirp/src/bootp.o > GEN ui/input-keymap-usb-to-qcode.c > make: *** [block/block-gen.c] Error 1 > make: *** Deleting file `block/block-gen.c' > make: *** Waiting for unfinished jobs.... > GEN ui/input-keymap-win32-to-qcode.c The more interesting part of the failure: File "/tmp/qemu-test/src/scripts/coroutine-wrapper.py", line 173, in <module> print(gen_wrappers_file(sys.stdin.read())) File "/tmp/qemu-test/src/scripts/coroutine-wrapper.py", line 169, in gen_wrappers_file return prettify(res) # prettify to wrap long lines File "/tmp/qemu-test/src/scripts/coroutine-wrapper.py", line 40, in prettify encoding='utf-8', input=code, capture_output=True) File "/usr/lib64/python3.6/subprocess.py", line 423, in run with Popen(*popenargs, **kwargs) as process: TypeError: __init__() got an unexpected keyword argument 'capture_output' which indeed looks like a bug in the patch. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
28.05.2020 00:57, Eric Blake wrote: > On 5/27/20 4:46 PM, no-reply@patchew.org wrote: >> Patchew URL: https://patchew.org/QEMU/20200527203733.16129-1-vsementsov@virtuozzo.com/ >> >> >> >> Hi, >> >> This series failed the docker-quick@centos7 build test. Please find the testing commands and >> their output below. If you have Docker installed, you can probably reproduce it >> locally. >> >> === TEST SCRIPT BEGIN === >> #!/bin/bash >> make docker-image-centos7 V=1 NETWORK=1 >> time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 >> === TEST SCRIPT END === >> >> TypeError: __init__() got an unexpected keyword argument 'capture_output' >> CC /tmp/qemu-test/build/slirp/src/bootp.o >> GEN ui/input-keymap-usb-to-qcode.c >> make: *** [block/block-gen.c] Error 1 >> make: *** Deleting file `block/block-gen.c' >> make: *** Waiting for unfinished jobs.... >> GEN ui/input-keymap-win32-to-qcode.c > > The more interesting part of the failure: > > File "/tmp/qemu-test/src/scripts/coroutine-wrapper.py", line 173, in <module> > print(gen_wrappers_file(sys.stdin.read())) > File "/tmp/qemu-test/src/scripts/coroutine-wrapper.py", line 169, in gen_wrappers_file > return prettify(res) # prettify to wrap long lines > File "/tmp/qemu-test/src/scripts/coroutine-wrapper.py", line 40, in prettify > encoding='utf-8', input=code, capture_output=True) > File "/usr/lib64/python3.6/subprocess.py", line 423, in run > with Popen(*popenargs, **kwargs) as process: > TypeError: __init__() got an unexpected keyword argument 'capture_output' > > which indeed looks like a bug in the patch. > Ah, yes, capture_output is since python 3.7. So, s/capture_output=True/stdout=subprocess.PIPE/ . -- Best regards, Vladimir
Patchew URL: https://patchew.org/QEMU/20200527203733.16129-1-vsementsov@virtuozzo.com/ Hi, This series failed the docker-quick@centos7 build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. === TEST SCRIPT BEGIN === #!/bin/bash make docker-image-centos7 V=1 NETWORK=1 time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 === TEST SCRIPT END === with Popen(*popenargs, **kwargs) as process: TypeError: __init__() got an unexpected keyword argument 'capture_output' CC /tmp/qemu-test/build/slirp/src/arp_table.o make: *** [block/block-gen.c] Error 1 make: *** Deleting file `block/block-gen.c' CC /tmp/qemu-test/build/slirp/src/util.o make: *** Waiting for unfinished jobs.... --- raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=e9801db6c81946b8b7007cd3179a6d18', '-u', '1003', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew2/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-eja8hzsv/src/docker-src.2020-05-27-18.23.44.9751:/var/tmp/qemu:z,ro', 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2. filter=--filter=label=com.qemu.instance.uuid=e9801db6c81946b8b7007cd3179a6d18 make[1]: *** [docker-run] Error 1 make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-eja8hzsv/src' make: *** [docker-run-test-quick@centos7] Error 2 real 2m1.393s user 0m7.847s The full log is available at http://patchew.org/logs/20200527203733.16129-1-vsementsov@virtuozzo.com/testing.docker-quick@centos7/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-devel@redhat.com
© 2016 - 2024 Red Hat, Inc.