diff mbox series

[08/20] block-coroutine-wrapper.py: take the graph rdlock in bdrv_* functions

Message ID 20221116134850.3051419-9-eesposit@redhat.com (mailing list archive)
State New, archived
Headers show
Series Protect the block layer with a rwlock: part 1 | expand

Commit Message

Emanuele Giuseppe Esposito Nov. 16, 2022, 1:48 p.m. UTC
All generated_co_wrapper functions create a coroutine when
called from non-coroutine context.

The format can be one of the two:

bdrv_something()
    if(qemu_in_coroutine()):
        bdrv_co_something();
    else:
        // create coroutine that calls bdrv_co_something();

blk_something()
    if(qemu_in_coroutine()):
        blk_co_something();
    else:
        // create coroutine that calls blk_co_something();
	// blk_co_something() then eventually calls bdrv_co_something()

The bdrv_co_something functions are recursively traversing the graph,
therefore they all need to be protected with the graph rdlock.
Instead, blk_co_something() calls bdrv_co_something(), so given that and
being always called at the root of the graph (not in recursive
callbacks), they should take the graph rdlock.

The contract is simple, from now on, all bdrv_co_* functions called by g_c_w
callbacks assume that the graph rdlock is taken at the coroutine
creation, i.e. in g_c_w or in specific coroutines (right now we just
consider the g_c_w case).

All the blk_co_* are responsible of taking the rdlock (at this point is still a TBD).

Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
---
 scripts/block-coroutine-wrapper.py | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
index 21ecb3e896..05267761f0 100644
--- a/scripts/block-coroutine-wrapper.py
+++ b/scripts/block-coroutine-wrapper.py
@@ -67,8 +67,11 @@  def __init__(self, return_type: str, name: str, args: str,
         self.return_type = return_type.strip()
         self.name = name.strip()
         self.args = [ParamDecl(arg.strip()) for arg in args.split(',')]
+        self.lock = True
         self.create_only_co = False
 
+        if variant == '_blk':
+            self.lock = False
         if variant == '_simple':
             self.create_only_co = True
 
@@ -86,7 +89,6 @@  def gen_block(self, format: str) -> str:
                           r'(?P<wrapper_name>[a-z][a-z0-9_]*)'
                           r'\((?P<args>[^)]*)\);$', re.MULTILINE)
 
-
 def func_decl_iter(text: str) -> Iterator:
     for m in func_decl_re.finditer(text):
         yield FuncDecl(return_type=m.group('return_type'),
@@ -160,6 +162,13 @@  def gen_wrapper(func: FuncDecl) -> str:
     func.co_name = f'{subsystem}_co_{subname}'
     name = func.co_name
 
+    graph_lock=''
+    graph_unlock=''
+    if func.lock:
+        graph_lock='    bdrv_graph_co_rdlock();'
+        graph_unlock='    bdrv_graph_co_rdunlock();'
+
+
     t = func.args[0].type
     if t == 'BlockDriverState *':
         bs = 'bs'
@@ -192,7 +201,9 @@  def gen_wrapper(func: FuncDecl) -> str:
 {{
     {struct_name} *s = opaque;
 
+{graph_lock}
     s->ret = {name}({ func.gen_list('s->{name}') });
+{graph_unlock}
     s->poll_state.in_progress = false;
 
     aio_wait_kick();