Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-24 Thread Vladimir Sementsov-Ogievskiy

24.09.2020 20:56, Eric Blake wrote:

On 9/15/20 11:44 AM, Vladimir Sementsov-Ogievskiy wrote:

We have a very frequent pattern of creating coroutine from function
with several arguments:




+++ b/docs/devel/block-coroutine-wrapper.rst
@@ -0,0 +1,54 @@
+===
+block-coroutine-wrapper
+===
+
+A lot of functions in QEMJ block layer (see ``block/*``) can by called


My editor italicized everhting after block/*...


+only in coroutine context. Such functions are normally marked by
+coroutine_fn specifier. Still, sometimes we need to call them from
+non-coroutine context, for this we need to start a coroutine, run the
+needed function from it and wait for coroutine finish in
+BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
+void* argument. So for each coroutine_fn function, which needs


...through void*.  I wonder if you need to use \* to let .rst know that these 
are literal *, and not markup for a different font style. Although I did not 
check the actual generated docs to see how they look.



Intuitively, `` should have greater priority than *.

I now check ./build/docs/devel/block-coroutine-wrapper.html , it looks OK:

   A lot of functions in QEMU block layer (see block/*) can only be

--
Best regards,
Vladimir



Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-24 Thread Eric Blake

On 9/15/20 11:44 AM, Vladimir Sementsov-Ogievskiy wrote:

We have a very frequent pattern of creating coroutine from function
with several arguments:




+++ b/docs/devel/block-coroutine-wrapper.rst
@@ -0,0 +1,54 @@
+===
+block-coroutine-wrapper
+===
+
+A lot of functions in QEMJ block layer (see ``block/*``) can by called


My editor italicized everhting after block/*...


+only in coroutine context. Such functions are normally marked by
+coroutine_fn specifier. Still, sometimes we need to call them from
+non-coroutine context, for this we need to start a coroutine, run the
+needed function from it and wait for coroutine finish in
+BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
+void* argument. So for each coroutine_fn function, which needs


...through void*.  I wonder if you need to use \* to let .rst know that 
these are literal *, and not markup for a different font style. 
Although I did not check the actual generated docs to see how they look.


--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-24 Thread John Snow

On 9/23/20 8:00 PM, Eric Blake wrote:



There's enough grammar fixes, and the fact that John is working on 
python cleanups, to make me wonder if we need a v9, or if I should just 
stage it where it is with any other cleanups as followups.  But I'm 
liking the reduced maintenance burden once it is in, and don't want to 
drag it out to the point that it needs more rebasing as other things 
land first.


Don't worry about it too much. I'd rather we have a helpful script 
sooner than later than worry about Python style purity before I have the 
CI mechanisms for it fully established.


(I eyeballed it and it looks like you already use type hints, so I have 
faith it won't need much cleanup.)


Thanks!

--js




Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-24 Thread Stefan Hajnoczi
On Tue, Sep 15, 2020 at 07:44:08PM +0300, Vladimir Sementsov-Ogievskiy wrote:
>  create mode 100755 scripts/block-coroutine-wrapper.py

Please see docs/devel/build-system.rst "Support scripts" for the
preferred way of adding Python scripts to the build system. Mode should
be 644 and the interpreter line should be "#! /usr/bin/env python3"
(with the space). That way meson will run it under the configured
--python= interpreter.

> 
> diff --git a/docs/devel/block-coroutine-wrapper.rst 
> b/docs/devel/block-coroutine-wrapper.rst
> new file mode 100644
> index 00..f7050bbc8f
> --- /dev/null
> +++ b/docs/devel/block-coroutine-wrapper.rst
> @@ -0,0 +1,54 @@
> +===
> +block-coroutine-wrapper
> +===
> +
> +A lot of functions in QEMJ block layer (see ``block/*``) can by called

s/QEMJ/QEMU/

> +only in coroutine context. Such functions are normally marked by
> +coroutine_fn specifier. Still, sometimes we need to call them from
> +non-coroutine context, for this we need to start a coroutine, run the
> +needed function from it and wait for coroutine finish in
> +BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
> +void* argument. So for each coroutine_fn function, which needs
> +non-coroutine interface, we should define a structure to pack the
> +parameters, define a separate function to unpack the parameters and
> +call the original function and finally define a new interface function
> +with same list of arguments as original one, which will pack the
> +parameters into a struct, create a coroutine, run it and wait in
> +BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand, so
> +we have a script to generate them.
> +
> +Usage
> +=
> +
> +Assume we have defined ``coroutine_fn`` function
> +``bdrv_co_foo()`` and need a non-coroutine interface for it,
> +called ``bdrv_foo()``. In this case the script can help. To
> +trigger the generation:
> +
> +1. You need ``bdrv_foo`` declaration somewhere (for example in
> +   ``block/coroutines.h`` with ``generated_co_wrapper`` mark,
> +   like this:
> +
> +.. code-block:: c
> +
> +int generated_co_wrapper bdrv_foor();

s/foor/foo/


signature.asc
Description: PGP signature


Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-24 Thread Vladimir Sementsov-Ogievskiy

24.09.2020 04:20, Eric Blake wrote:

On 9/23/20 7:00 PM, Eric Blake wrote:



Tested-by: Eric Blake 

There's enough grammar fixes, and the fact that John is working on python 
cleanups, to make me wonder if we need a v9, or if I should just stage it where 
it is with any other cleanups as followups.  But I'm liking the reduced 
maintenance burden once it is in, and don't want to drag it out to the point 
that it needs more rebasing as other things land first.



Here's what I've squashed in and temporarily pushed to my tree if you want to 
double-check my rebase work:
https://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/master

diff --git a/docs/devel/block-coroutine-wrapper.rst 
b/docs/devel/block-coroutine-wrapper.rst
index f7050bbc8fa6..d09fff2cc539 100644
--- a/docs/devel/block-coroutine-wrapper.rst
+++ b/docs/devel/block-coroutine-wrapper.rst
@@ -2,43 +2,43 @@
  block-coroutine-wrapper
  ===

-A lot of functions in QEMJ block layer (see ``block/*``) can by called
-only in coroutine context. Such functions are normally marked by
+A lot of functions in QEMU block layer (see ``block/*``) can only be
+called in coroutine context. Such functions are normally marked by the
  coroutine_fn specifier. Still, sometimes we need to call them from
-non-coroutine context, for this we need to start a coroutine, run the
+non-coroutine context; for this we need to start a coroutine, run the
  needed function from it and wait for coroutine finish in
  BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
-void* argument. So for each coroutine_fn function, which needs
+void* argument. So for each coroutine_fn function which needs a
  non-coroutine interface, we should define a structure to pack the
  parameters, define a separate function to unpack the parameters and
  call the original function and finally define a new interface function
  with same list of arguments as original one, which will pack the
  parameters into a struct, create a coroutine, run it and wait in
-BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand, so
-we have a script to generate them.
+BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand,
+so we have a script to generate them.

  Usage
  =

-Assume we have defined ``coroutine_fn`` function
+Assume we have defined the ``coroutine_fn`` function
  ``bdrv_co_foo()`` and need a non-coroutine interface for it,
  called ``bdrv_foo()``. In this case the script can help. To
  trigger the generation:

-1. You need ``bdrv_foo`` declaration somewhere (for example in
-   ``block/coroutines.h`` with ``generated_co_wrapper`` mark,
+1. You need ``bdrv_foo`` declaration somewhere (for example, in
+   ``block/coroutines.h``) with the ``generated_co_wrapper`` mark,
     like this:

  .. code-block:: c

-    int generated_co_wrapper bdrv_foor();
+    int generated_co_wrapper bdrv_foo();

  2. You need to feed this declaration to block-coroutine-wrapper script.
-   For this, add .h (or .c) file with the declaration to
+   For this, add the .h (or .c) file with the declaration to the
     ``input: files(...)`` list of ``block_gen_c`` target declaration in
     ``block/meson.build``

-You are done. On build, coroutine wrappers will be generated in
+You are done. During the build, coroutine wrappers will be generated in
  ``/block/block-gen.c``.

  Links
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 04773ce076b3..cb0abe1e6988 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -31,3 +31,4 @@ Contents:
     reset
     s390-dasd-ipl
     clocks
+   block-coroutine-wrapper
diff --git a/scripts/block-coroutine-wrapper.py 
b/scripts/block-coroutine-wrapper.py
index d859c07a5f55..8c0a08d9b020 100755
--- a/scripts/block-coroutine-wrapper.py
+++ b/scripts/block-coroutine-wrapper.py
@@ -2,7 +2,7 @@
  """Generate coroutine wrappers for block subsystem.

  The program parses one or several concatenated c files from stdin,
-searches for functions with 'generated_co_wrapper' specifier
+searches for functions with the 'generated_co_wrapper' specifier
  and generates corresponding wrappers on stdout.

  Usage: block-coroutine-wrapper.py generated-file.c FILE.[ch]...
@@ -39,7 +39,7 @@ def prettify(code: str) -> str:
  'BraceWrapping': {'AfterFunction': True},
  'BreakBeforeBraces': 'Custom',
  'SortIncludes': False,
-    'MaxEmptyLinesToKeep': 2
+    'MaxEmptyLinesToKeep': 2,
  })
  p = subprocess.run(['clang-format', f'-style={style}'], check=True,
     encoding='utf-8', input=code,
@@ -168,7 +168,7 @@ int {func.name}({ func.gen_list('{decl}') })


  def gen_wrappers_file(input_code: str) -> str:
-    res = gen_header()
+    res = ''
  for func in func_decl_iter(input_code):
  res += '\n\n\n'
  res += gen_wrapper(func)
@@ -181,6 +181,7 @@ if __name__ == '__main__':
  exit(f'Usage: {sys.argv[0]} OUT_FILE.c 

Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-24 Thread Vladimir Sementsov-Ogievskiy

24.09.2020 03:18, Eric Blake wrote:

On 9/15/20 11:44 AM, Vladimir Sementsov-Ogievskiy wrote:

We have a very frequent pattern of creating coroutine from function
with several arguments:




+++ b/scripts/block-coroutine-wrapper.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python3
+"""Generate coroutine wrappers for block subsystem.


Looking at the generated file after patch 5 is applied,...



+
+def gen_header():
+    copyright = re.sub('^.*Copyright', 'Copyright', __doc__, flags=re.DOTALL)
+    copyright = re.sub('^(?=.)', ' * ', copyright.strip(), flags=re.MULTILINE)
+    copyright = re.sub('^$', ' *', copyright, flags=re.MULTILINE)
+    return f"""\


This generated comment...



+
+
+def gen_wrappers_file(input_code: str) -> str:
+    res = gen_header()


...is getting inserted into the generated file...


+    for func in func_decl_iter(input_code):
+    res += '\n\n\n'
+    res += gen_wrapper(func)
+
+    return prettify(res)  # prettify to wrap long lines
+
+
+if __name__ == '__main__':
+    if len(sys.argv) < 3:
+    exit(f'Usage: {sys.argv[0]} OUT_FILE.c IN_FILE.[ch]...')
+
+    with open(sys.argv[1], 'w') as f_out:
+    for fname in sys.argv[2:]:
+    with open(fname) as f_in:
+    f_out.write(gen_wrappers_file(f_in.read()))


multiple times.  You'll want to hoist the call to gen_header outside the loop 
over fname in sys.argv[2:].



Right, thanks for fixing. I missed it when rebasing on meson system (and move 
to calling gen_wrappers_file() several times). Hmm, gen_wrappers_file() is now 
a bit misleading name, it would better be just gen_wrappers()

--
Best regards,
Vladimir



Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-24 Thread Vladimir Sementsov-Ogievskiy

24.09.2020 03:00, Eric Blake wrote:

On 9/15/20 3:02 PM, Vladimir Sementsov-Ogievskiy wrote:

15.09.2020 19:44, Vladimir Sementsov-Ogievskiy wrote:

We have a very frequent pattern of creating coroutine from function
with several arguments:

   - create structure to pack parameters
   - create _entry function to call original function taking parameters
 from struct
   - do different magic to handle completion: set ret to NOT_DONE or
 EINPROGRESS or use separate bool field
   - fill the struct and create coroutine from _entry function and this
 struct as a parameter
   - do coroutine enter and BDRV_POLL_WHILE loop

Let's reduce code duplication by generating coroutine wrappers.

This patch adds scripts/block-coroutine-wrapper.py together with some
friends, which will generate functions with declared prototypes marked
by 'generated_co_wrapper' specifier.





 4. add header with generated_co_wrapper declaration into
    COROUTINE_HEADERS list in Makefile


This phrase is out-of-date.  I also see 4 steps here,...



Still, no function is now marked, this work is for the following
commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy
---
  docs/devel/block-coroutine-wrapper.rst |  54 +++
  block/block-gen.h  |  49 +++
  include/block/block.h  |  10 ++
  block/meson.build  |   8 ++
  scripts/block-coroutine-wrapper.py | 187 +
  5 files changed, 308 insertions(+)
  create mode 100644 docs/devel/block-coroutine-wrapper.rst
  create mode 100644 block/block-gen.h
  create mode 100755 scripts/block-coroutine-wrapper.py



Also needed:

diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 04773ce076..cb0abe1e69 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -31,3 +31,4 @@ Contents:
 reset
 s390-dasd-ipl
 clocks
+   block-coroutine-wrapper


I've squashed that in.


+++ b/docs/devel/block-coroutine-wrapper.rst
@@ -0,0 +1,54 @@
+===
+block-coroutine-wrapper
+===
+
+A lot of functions in QEMJ block layer (see ``block/*``) can by called


QEMU

s/by called only/only be called/


+only in coroutine context. Such functions are normally marked by


by the


+coroutine_fn specifier. Still, sometimes we need to call them from
+non-coroutine context, for this we need to start a coroutine, run the



s/context,/context;/


+needed function from it and wait for coroutine finish in


in a


+BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
+void* argument. So for each coroutine_fn function, which needs


needs a


+non-coroutine interface, we should define a structure to pack the
+parameters, define a separate function to unpack the parameters and
+call the original function and finally define a new interface function
+with same list of arguments as original one, which will pack the
+parameters into a struct, create a coroutine, run it and wait in
+BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand, so
+we have a script to generate them.

+Usage
+=
+
+Assume we have defined ``coroutine_fn`` function
+``bdrv_co_foo()`` and need a non-coroutine interface for it,
+called ``bdrv_foo()``. In this case the script can help. To
+trigger the generation:
+
+1. You need ``bdrv_foo`` declaration somewhere (for example in
+   ``block/coroutines.h`` with ``generated_co_wrapper`` mark,
+   like this:


Missing a closing ).


+
+.. code-block:: c
+
+    int generated_co_wrapper bdrv_foor();


s/foor/foo/


+
+2. You need to feed this declaration to block-coroutine-wrapper script.


to the block-


+   For this, add .h (or .c) file with the declaration to
+   ``input: files(...)`` list of ``block_gen_c`` target declaration in
+   ``block/meson.build``
+
+You are done. On build, coroutine wrappers will be generated in


s/On/During the/


+``/block/block-gen.c``.


...but 2 in the .rst.  Presumably, the .rst steps belong in the commit message 
as well.


+++ b/block/block-gen.h



+++ b/include/block/block.h
@@ -10,6 +10,16 @@
 #include "block/blockjob.h"
 #include "qemu/hbitmap.h"

+/*
+ * generated_co_wrapper
+ *
+ * Function specifier, which does nothing but marking functions to be


s/marking/mark/


+ * generated by scripts/block-coroutine-wrapper.py
+ *
+ * Read more in docs/devel/block-coroutine-wrapper.rst
+ */
+#define generated_co_wrapper
+
 /* block.c */
 typedef struct BlockDriver BlockDriver;
 typedef struct BdrvChild BdrvChild;
diff --git a/block/meson.build b/block/meson.build
index a3e56b7cd1..88ad73583a 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -107,6 +107,14 @@ module_block_h = custom_target('module_block.h',
    command: [module_block_py, '@OUTPUT0@', modsrc])
 block_ss.add(module_block_h)

+wrapper_py = find_program('../scripts/block-coroutine-wrapper.py')
+block_gen_c = custom_target('block-gen.c',
+    output: 'block-gen.c',
+   

Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-23 Thread Eric Blake

On 9/23/20 7:00 PM, Eric Blake wrote:



Tested-by: Eric Blake 

There's enough grammar fixes, and the fact that John is working on 
python cleanups, to make me wonder if we need a v9, or if I should just 
stage it where it is with any other cleanups as followups.  But I'm 
liking the reduced maintenance burden once it is in, and don't want to 
drag it out to the point that it needs more rebasing as other things 
land first.




Here's what I've squashed in and temporarily pushed to my tree if you 
want to double-check my rebase work:

https://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/master

diff --git a/docs/devel/block-coroutine-wrapper.rst 
b/docs/devel/block-coroutine-wrapper.rst

index f7050bbc8fa6..d09fff2cc539 100644
--- a/docs/devel/block-coroutine-wrapper.rst
+++ b/docs/devel/block-coroutine-wrapper.rst
@@ -2,43 +2,43 @@
 block-coroutine-wrapper
 ===

-A lot of functions in QEMJ block layer (see ``block/*``) can by called
-only in coroutine context. Such functions are normally marked by
+A lot of functions in QEMU block layer (see ``block/*``) can only be
+called in coroutine context. Such functions are normally marked by the
 coroutine_fn specifier. Still, sometimes we need to call them from
-non-coroutine context, for this we need to start a coroutine, run the
+non-coroutine context; for this we need to start a coroutine, run the
 needed function from it and wait for coroutine finish in
 BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
-void* argument. So for each coroutine_fn function, which needs
+void* argument. So for each coroutine_fn function which needs a
 non-coroutine interface, we should define a structure to pack the
 parameters, define a separate function to unpack the parameters and
 call the original function and finally define a new interface function
 with same list of arguments as original one, which will pack the
 parameters into a struct, create a coroutine, run it and wait in
-BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand, so
-we have a script to generate them.
+BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand,
+so we have a script to generate them.

 Usage
 =

-Assume we have defined ``coroutine_fn`` function
+Assume we have defined the ``coroutine_fn`` function
 ``bdrv_co_foo()`` and need a non-coroutine interface for it,
 called ``bdrv_foo()``. In this case the script can help. To
 trigger the generation:

-1. You need ``bdrv_foo`` declaration somewhere (for example in
-   ``block/coroutines.h`` with ``generated_co_wrapper`` mark,
+1. You need ``bdrv_foo`` declaration somewhere (for example, in
+   ``block/coroutines.h``) with the ``generated_co_wrapper`` mark,
like this:

 .. code-block:: c

-int generated_co_wrapper bdrv_foor();
+int generated_co_wrapper bdrv_foo();

 2. You need to feed this declaration to block-coroutine-wrapper script.
-   For this, add .h (or .c) file with the declaration to
+   For this, add the .h (or .c) file with the declaration to the
``input: files(...)`` list of ``block_gen_c`` target declaration in
``block/meson.build``

-You are done. On build, coroutine wrappers will be generated in
+You are done. During the build, coroutine wrappers will be generated in
 ``/block/block-gen.c``.

 Links
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 04773ce076b3..cb0abe1e6988 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -31,3 +31,4 @@ Contents:
reset
s390-dasd-ipl
clocks
+   block-coroutine-wrapper
diff --git a/scripts/block-coroutine-wrapper.py 
b/scripts/block-coroutine-wrapper.py

index d859c07a5f55..8c0a08d9b020 100755
--- a/scripts/block-coroutine-wrapper.py
+++ b/scripts/block-coroutine-wrapper.py
@@ -2,7 +2,7 @@
 """Generate coroutine wrappers for block subsystem.

 The program parses one or several concatenated c files from stdin,
-searches for functions with 'generated_co_wrapper' specifier
+searches for functions with the 'generated_co_wrapper' specifier
 and generates corresponding wrappers on stdout.

 Usage: block-coroutine-wrapper.py generated-file.c FILE.[ch]...
@@ -39,7 +39,7 @@ def prettify(code: str) -> str:
 'BraceWrapping': {'AfterFunction': True},
 'BreakBeforeBraces': 'Custom',
 'SortIncludes': False,
-'MaxEmptyLinesToKeep': 2
+'MaxEmptyLinesToKeep': 2,
 })
 p = subprocess.run(['clang-format', f'-style={style}'], 
check=True,

encoding='utf-8', input=code,
@@ -168,7 +168,7 @@ int {func.name}({ func.gen_list('{decl}') })


 def gen_wrappers_file(input_code: str) -> str:
-res = gen_header()
+res = ''
 for func in func_decl_iter(input_code):
 res += '\n\n\n'
 res += gen_wrapper(func)
@@ -181,6 +181,7 @@ if __name__ == '__main__':
 exit(f'Usage: {sys.argv[0]} OUT_FILE.c IN_FILE.[ch]...')

 with open(sys.argv[1], 'w') as f_out:
+

Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-23 Thread Eric Blake

On 9/15/20 11:44 AM, Vladimir Sementsov-Ogievskiy wrote:

We have a very frequent pattern of creating coroutine from function
with several arguments:




+++ b/scripts/block-coroutine-wrapper.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python3
+"""Generate coroutine wrappers for block subsystem.


Looking at the generated file after patch 5 is applied,...



+
+def gen_header():
+copyright = re.sub('^.*Copyright', 'Copyright', __doc__, flags=re.DOTALL)
+copyright = re.sub('^(?=.)', ' * ', copyright.strip(), flags=re.MULTILINE)
+copyright = re.sub('^$', ' *', copyright, flags=re.MULTILINE)
+return f"""\


This generated comment...



+
+
+def gen_wrappers_file(input_code: str) -> str:
+res = gen_header()


...is getting inserted into the generated file...


+for func in func_decl_iter(input_code):
+res += '\n\n\n'
+res += gen_wrapper(func)
+
+return prettify(res)  # prettify to wrap long lines
+
+
+if __name__ == '__main__':
+if len(sys.argv) < 3:
+exit(f'Usage: {sys.argv[0]} OUT_FILE.c IN_FILE.[ch]...')
+
+with open(sys.argv[1], 'w') as f_out:
+for fname in sys.argv[2:]:
+with open(fname) as f_in:
+f_out.write(gen_wrappers_file(f_in.read()))


multiple times.  You'll want to hoist the call to gen_header outside the 
loop over fname in sys.argv[2:].


--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-23 Thread Eric Blake

On 9/15/20 3:02 PM, Vladimir Sementsov-Ogievskiy wrote:

15.09.2020 19:44, Vladimir Sementsov-Ogievskiy wrote:

We have a very frequent pattern of creating coroutine from function
with several arguments:

   - create structure to pack parameters
   - create _entry function to call original function taking parameters
 from struct
   - do different magic to handle completion: set ret to NOT_DONE or
 EINPROGRESS or use separate bool field
   - fill the struct and create coroutine from _entry function and this
 struct as a parameter
   - do coroutine enter and BDRV_POLL_WHILE loop

Let's reduce code duplication by generating coroutine wrappers.

This patch adds scripts/block-coroutine-wrapper.py together with some
friends, which will generate functions with declared prototypes marked
by 'generated_co_wrapper' specifier.





 4. add header with generated_co_wrapper declaration into
    COROUTINE_HEADERS list in Makefile


This phrase is out-of-date.  I also see 4 steps here,...



Still, no function is now marked, this work is for the following
commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy
---
  docs/devel/block-coroutine-wrapper.rst |  54 +++
  block/block-gen.h  |  49 +++
  include/block/block.h  |  10 ++
  block/meson.build  |   8 ++
  scripts/block-coroutine-wrapper.py | 187 +
  5 files changed, 308 insertions(+)
  create mode 100644 docs/devel/block-coroutine-wrapper.rst
  create mode 100644 block/block-gen.h
  create mode 100755 scripts/block-coroutine-wrapper.py



Also needed:

diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 04773ce076..cb0abe1e69 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -31,3 +31,4 @@ Contents:
     reset
     s390-dasd-ipl
     clocks
+   block-coroutine-wrapper


I've squashed that in.


+++ b/docs/devel/block-coroutine-wrapper.rst
@@ -0,0 +1,54 @@
+===
+block-coroutine-wrapper
+===
+
+A lot of functions in QEMJ block layer (see ``block/*``) can by called


QEMU

s/by called only/only be called/


+only in coroutine context. Such functions are normally marked by


by the


+coroutine_fn specifier. Still, sometimes we need to call them from
+non-coroutine context, for this we need to start a coroutine, run the



s/context,/context;/


+needed function from it and wait for coroutine finish in


in a


+BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
+void* argument. So for each coroutine_fn function, which needs


needs a


+non-coroutine interface, we should define a structure to pack the
+parameters, define a separate function to unpack the parameters and
+call the original function and finally define a new interface function
+with same list of arguments as original one, which will pack the
+parameters into a struct, create a coroutine, run it and wait in
+BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand, so
+we have a script to generate them.

+Usage
+=
+
+Assume we have defined ``coroutine_fn`` function
+``bdrv_co_foo()`` and need a non-coroutine interface for it,
+called ``bdrv_foo()``. In this case the script can help. To
+trigger the generation:
+
+1. You need ``bdrv_foo`` declaration somewhere (for example in
+   ``block/coroutines.h`` with ``generated_co_wrapper`` mark,
+   like this:


Missing a closing ).


+
+.. code-block:: c
+
+int generated_co_wrapper bdrv_foor();


s/foor/foo/


+
+2. You need to feed this declaration to block-coroutine-wrapper script.


to the block-


+   For this, add .h (or .c) file with the declaration to
+   ``input: files(...)`` list of ``block_gen_c`` target declaration in
+   ``block/meson.build``
+
+You are done. On build, coroutine wrappers will be generated in


s/On/During the/


+``/block/block-gen.c``.


...but 2 in the .rst.  Presumably, the .rst steps belong in the commit 
message as well.



+++ b/block/block-gen.h



+++ b/include/block/block.h
@@ -10,6 +10,16 @@
 #include "block/blockjob.h"
 #include "qemu/hbitmap.h"
 
+/*

+ * generated_co_wrapper
+ *
+ * Function specifier, which does nothing but marking functions to be


s/marking/mark/


+ * generated by scripts/block-coroutine-wrapper.py
+ *
+ * Read more in docs/devel/block-coroutine-wrapper.rst
+ */
+#define generated_co_wrapper
+
 /* block.c */
 typedef struct BlockDriver BlockDriver;
 typedef struct BdrvChild BdrvChild;
diff --git a/block/meson.build b/block/meson.build
index a3e56b7cd1..88ad73583a 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -107,6 +107,14 @@ module_block_h = custom_target('module_block.h',
command: [module_block_py, '@OUTPUT0@', modsrc])
 block_ss.add(module_block_h)
 
+wrapper_py = find_program('../scripts/block-coroutine-wrapper.py')

+block_gen_c = custom_target('block-gen.c',
+output: 'block-gen.c',
+input: 

Re: [PATCH v8 4/7] scripts: add block-coroutine-wrapper.py

2020-09-15 Thread Vladimir Sementsov-Ogievskiy

15.09.2020 19:44, Vladimir Sementsov-Ogievskiy wrote:

We have a very frequent pattern of creating coroutine from function
with several arguments:

   - create structure to pack parameters
   - create _entry function to call original function taking parameters
 from struct
   - do different magic to handle completion: set ret to NOT_DONE or
 EINPROGRESS or use separate bool field
   - fill the struct and create coroutine from _entry function and this
 struct as a parameter
   - do coroutine enter and BDRV_POLL_WHILE loop

Let's reduce code duplication by generating coroutine wrappers.

This patch adds scripts/block-coroutine-wrapper.py together with some
friends, which will generate functions with declared prototypes marked
by 'generated_co_wrapper' specifier.

The usage of new code generation is as follows:

 1. define somewhere

 int coroutine_fn bdrv_co_NAME(...) {...}

function

 2. declare in some header file

 int generated_co_wrapper bdrv_NAME(...);

function with same list of parameters. (you'll need to include
"block/generated-co-wrapper.h" to get the specifier)

 3. both declarations should be available through block/coroutines.h
header.

 4. add header with generated_co_wrapper declaration into
COROUTINE_HEADERS list in Makefile

Still, no function is now marked, this work is for the following
commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy
---
  docs/devel/block-coroutine-wrapper.rst |  54 +++
  block/block-gen.h  |  49 +++
  include/block/block.h  |  10 ++
  block/meson.build  |   8 ++
  scripts/block-coroutine-wrapper.py | 187 +
  5 files changed, 308 insertions(+)
  create mode 100644 docs/devel/block-coroutine-wrapper.rst
  create mode 100644 block/block-gen.h
  create mode 100755 scripts/block-coroutine-wrapper.py



Also needed:

diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 04773ce076..cb0abe1e69 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -31,3 +31,4 @@ Contents:
reset
s390-dasd-ipl
clocks
+   block-coroutine-wrapper

--
Best regards,
Vladimir