@@ -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();
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(-)