From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
To: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>,
qemu-block@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>,
John Snow <jsnow@redhat.com>, Eric Blake <eblake@redhat.com>,
Fam Zheng <fam@euphon.net>,
qemu-devel@nongnu.org, Stefan Hajnoczi <stefanha@redhat.com>,
Alberto Faria <afaria@redhat.com>,
Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [PATCH v2 2/9] block-copy: add missing coroutine_fn annotations
Date: Wed, 9 Nov 2022 13:23:54 +0100 [thread overview]
Message-ID: <460d096e-c642-166c-a4fd-77f953bfe33a@redhat.com> (raw)
In-Reply-To: <711f6d68-888e-bca0-972e-a05503a039c5@yandex-team.ru>
Am 08/11/2022 um 17:19 schrieb Vladimir Sementsov-Ogievskiy:
> [add Stefan]
>
>
> On 11/8/22 18:09, Emanuele Giuseppe Esposito wrote:
>>
>>
>> Am 08/11/2022 um 15:48 schrieb Vladimir Sementsov-Ogievskiy:
>>> On 11/4/22 12:56, Emanuele Giuseppe Esposito wrote:
>>>> These functions end up calling bdrv_common_block_status_above(), a
>>>> generated_co_wrapper function.
>>>
>>> generated_co_wrapper is not a coroutine_fn. Сonversely it's a function
>>> that do a class coroutine wrapping - start a coroutine and do POLL to
>>> wait for the coroutine to finish.
>>>
>>>> In addition, they also happen to be always called in coroutine context,
>>>> meaning all callers are coroutine_fn.
>>>
>>> That's also not a reason for marking them coroutine_fn. "coroutine_fn"
>>> means that the function can be called only from coroutine context.
>>>
>>>> This means that the g_c_w function will enter the qemu_in_coroutine()
>>>> case and eventually suspend (or in other words call
>>>> qemu_coroutine_yield()).
>>>> Therefore we need to mark such functions coroutine_fn too.
>>>
>>> I don't think so. Moreover, this breaks the concept, as your new
>>> coroutine_fn functions will call generated_co_wrapper functions which
>>> are not marked coroutine_fn and never was.
>>
>> Theoretically not,
>
> Agree, I was wrong in this point
>
>> because marking it coroutine_fn we know that we are
>> going in the if(qemu_in_coroutine()) branch of the g_c_w, so we could
>> directly replace it with the actual function. Because it's a pain to do
>> it with hand, and at some point I/someone should use Alberto static
>> analyzer to get rid of that, I decided to leave g_c_w there.
>>
>> As I understand it, it seems that you and Paolo have a different
>> understanding on what coroutine_fn means and where it should be used.
>
> Looks so...
>
> But we have a documentation in coroutine.h, let's check:
>
> * Mark a function that executes in coroutine context
> *
> * Functions that execute in coroutine context cannot be called directly
> from
> * normal functions. In the future it would be nice to enable compiler or
> * static checker support for catching such errors. This annotation
> might make
> * it possible and in the meantime it serves as documentation.
>
> Not very clear, but still it say:
>
> coroutine_fn = "function that executes in coroutine context"
> "functions that execute in coroutine context" = "cannot be called
> directly from normal functions"
>
> So, IMHO that corresponds to my point of view: we shouldn't mark by
> coroutine_fn functions that can be called from both coroutine context
> and not.
Yes and the point is that these functions are not called by
non-coroutine context.
>
> If we want to change the concept, we should start with rewriting this
> documentation.
>
>> Honestly I don't understand your point, as you said
>>
>>> "coroutine_fn"
>>> means that the function can be called only from coroutine context.
>>
>> which is the case for these functions. So could you please clarify?
>>
>> What I do know is that it's extremely confusing to understand if a
>> function that is *not* marked as coroutine_fn is actually being called
>> also from coroutines or not.
>>
>> Which complicates A LOT whatever change or operation I want to perform
>> on the BlockDriver callbacks or any other function in the block layer,
>> because in the current approach for the AioContext lock removal (which
>> you are not aware of, I understand) we need to distinguish between
>> functions running in coroutine context and not, and throwing g_c_w
>> functions everywhere makes my work much harder that it already is.
>
> OK, I understand the problem.
>
> Hmm. Formally marking by "coroutine_fn" a function that theoretically
> can be called from any context doesn't break things. We just say that
> since that moment we don't allow to call this function from
> non-coroutine context.
>
> OK, I tend to agree that you are on the right way, sorry for my skepticism)
>
> PS: you recently introduced a lot of IO_CODE() / GLOBAL_STATE_CODE()
> marks, which (will be/already) turned into assertions.
>
> This is a lot better than our "coroutine_fn" sign, which actually do no
> check (and can't do). Don't you plan to swap a "coroutine_fn" noop
> marker with more meaningful IN_COROUTINE(); (or something like this,
> which just do assert(qemu_in_coroutine())) at start of the function? It
> would be a lot safer.
CCing also Alberto and Paolo
So basically I think what we need is something that scans the whole
block layer code and puts the right coroutine_fn annotations (or
assertions, if you want) in the right places.
The rule should be (anyone please correct me if I am wrong):
- if a function is only called by coroutine_fn functions, then it's a
coroutine_fn. Theoretically all these functions should eventually end up
calling qemu_coroutine_yield or similar.
- if it's called only from non-coroutine, then leave it as it is.
Probably asserting is a good idea.
- if it's used by both, then it's a case-by-case decision: I think for
simple functions, we can use a special annotation and document that they
should always consider that they could run in both cases.
If it's a big function like the g_c_w, call only the _co_ version in
coroutine_fn, and create a coroutine or call the non-coroutine
counterpart if we are not in coroutine context.
Which is also what I am trying to do with g_c_w_simple.
However, it would be nice to assign this to someone and do this
automatically, not doing it by hand. I am not sure if Alberto static
analyzer is currently capable of doing that.
What do you all think?
Thank you,
Emanuele
>
>
>>
>> Thank you,
>> Emanuele
>>
>>>
>>>>
>>>> Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
>>>> ---
>>>> block/block-copy.c | 15 +++++++++------
>>>> 1 file changed, 9 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/block/block-copy.c b/block/block-copy.c
>>>> index bb947afdda..f33ab1d0b6 100644
>>>> --- a/block/block-copy.c
>>>> +++ b/block/block-copy.c
>>>> @@ -577,8 +577,9 @@ static coroutine_fn int
>>>> block_copy_task_entry(AioTask *task)
>>>> return ret;
>>>> }
>>>> -static int block_copy_block_status(BlockCopyState *s, int64_t
>>>> offset,
>>>> - int64_t bytes, int64_t *pnum)
>>>> +static coroutine_fn int block_copy_block_status(BlockCopyState *s,
>>>> + int64_t offset,
>>>> + int64_t bytes,
>>>> int64_t *pnum)
>>>> {
>>>> int64_t num;
>>>> BlockDriverState *base;
>>>> @@ -613,8 +614,9 @@ static int block_copy_block_status(BlockCopyState
>>>> *s, int64_t offset,
>>>> * Check if the cluster starting at offset is allocated or not.
>>>> * return via pnum the number of contiguous clusters sharing this
>>>> allocation.
>>>> */
>>>> -static int block_copy_is_cluster_allocated(BlockCopyState *s, int64_t
>>>> offset,
>>>> - int64_t *pnum)
>>>> +static int coroutine_fn
>>>> block_copy_is_cluster_allocated(BlockCopyState *s,
>>>> + int64_t
>>>> offset,
>>>> + int64_t *pnum)
>>>> {
>>>> BlockDriverState *bs = s->source->bs;
>>>> int64_t count, total_count = 0;
>>>> @@ -669,8 +671,9 @@ void block_copy_reset(BlockCopyState *s, int64_t
>>>> offset, int64_t bytes)
>>>> * @return 0 when the cluster at @offset was unallocated,
>>>> * 1 otherwise, and -ret on error.
>>>> */
>>>> -int64_t block_copy_reset_unallocated(BlockCopyState *s,
>>>> - int64_t offset, int64_t *count)
>>>> +int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
>>>> + int64_t offset,
>>>> + int64_t *count)
>>>> {
>>>> int ret;
>>>> int64_t clusters, bytes;
>>>
>>
>
next prev parent reply other threads:[~2022-11-09 12:24 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-04 9:56 [PATCH v2 0/9] Still more coroutine and various fixes in block layer Emanuele Giuseppe Esposito
2022-11-04 9:56 ` [PATCH v2 1/9] block: call bdrv_co_drain_begin in a coroutine Emanuele Giuseppe Esposito
2022-11-08 14:33 ` Vladimir Sementsov-Ogievskiy
2022-11-08 15:13 ` Emanuele Giuseppe Esposito
2022-11-08 15:52 ` Vladimir Sementsov-Ogievskiy
2022-11-08 16:06 ` Emanuele Giuseppe Esposito
2022-11-08 15:20 ` Kevin Wolf
2022-11-04 9:56 ` [PATCH v2 2/9] block-copy: add missing coroutine_fn annotations Emanuele Giuseppe Esposito
2022-11-08 14:48 ` Vladimir Sementsov-Ogievskiy
2022-11-08 15:09 ` Emanuele Giuseppe Esposito
2022-11-08 16:19 ` Vladimir Sementsov-Ogievskiy
2022-11-08 16:30 ` Vladimir Sementsov-Ogievskiy
2022-11-09 12:23 ` Emanuele Giuseppe Esposito [this message]
2022-11-09 23:52 ` Alberto Faria
2022-11-10 10:52 ` Paolo Bonzini
2022-11-15 15:41 ` Emanuele Giuseppe Esposito
2022-11-16 16:40 ` Paolo Bonzini
2022-11-04 9:56 ` [PATCH v2 3/9] nbd/server.c: " Emanuele Giuseppe Esposito
2022-11-08 14:54 ` Vladimir Sementsov-Ogievskiy
2022-11-04 9:56 ` [PATCH v2 4/9] block-backend: replace bdrv_*_above with blk_*_above Emanuele Giuseppe Esposito
2022-11-04 9:56 ` [PATCH v2 5/9] block: distinguish between bdrv_create running in coroutine and not Emanuele Giuseppe Esposito
2022-11-08 14:59 ` Vladimir Sementsov-Ogievskiy
2022-11-04 9:56 ` [PATCH v2 6/9] block/vmdk: add missing coroutine_fn annotations Emanuele Giuseppe Esposito
2022-11-04 9:56 ` [PATCH v2 7/9] block: bdrv_create_file is a coroutine_fn Emanuele Giuseppe Esposito
2022-11-04 9:56 ` [PATCH v2 8/9] block: bdrv_create is never called in non-coroutine context Emanuele Giuseppe Esposito
2022-11-08 15:23 ` Kevin Wolf
2022-11-04 9:57 ` [PATCH v2 9/9] block/dirty-bitmap: remove unnecessary qemu_in_coroutine() case Emanuele Giuseppe Esposito
2022-11-04 13:16 ` [PATCH v2 0/9] Still more coroutine and various fixes in block layer Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=460d096e-c642-166c-a4fd-77f953bfe33a@redhat.com \
--to=eesposit@redhat.com \
--cc=afaria@redhat.com \
--cc=eblake@redhat.com \
--cc=fam@euphon.net \
--cc=hreitz@redhat.com \
--cc=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=vsementsov@yandex-team.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).