From: Jamie Lokier <jamie@shareable.org>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] QEMU/KVM SCSI lock up
Date: Thu, 3 Apr 2008 12:31:29 +0100 [thread overview]
Message-ID: <20080403113128.GA17900@shareable.org> (raw)
In-Reply-To: <47F49770.1010906@qumranet.com>
Avi Kivity wrote:
> > bdrv_aio_read()
> > r->sector += n;
> > r->sector_count -= n;
> >
> >For reasons that I do not fully understand, bdrv_aio_read() does
> >not return immediately, but instead it calls scsi_read_data()
> >recursively.
>
> What happens (I think) is that bdrv_aio_read() completes immediately,
> calls the completion callback, which starts a read for the next batch of
> sectors.
>
> Long term we want to replace the recursion by queuing.
Ah yes. Reminds me of a bug in a program of mine with asynchronous
sockets, which sometimes completes immediately. My async connection
function took a callback argument. The callback was called
immediately if the connect returned success immediately, otherwise was
queued.
Then I wrote some code like this:
// some stuff
my_obj->connector = async_connection (address, my_obj_connect_cb, my_obj);
// some more stuff
void my_obj_connect_cb (void * arg)
{
MyObj * my_obj = arg;
do_stuff_with (my_obj->connector);
}
That worked for several months flawlessly, the code was deployed on
500 units around the country, then one day an async connect happened
to complete fast enough that the callback was called recursively, and
a core dump followed.
I learned a few lessons about async callbacks:
1. Queue them, even when the async operation completes immediately.
It's really not worth the "optimisation" of immediate callback,
especially if the code for queuing is already there.
Even when immediate callback is documented, mistakes are too
easy to make when calling it, because the async call pattern
_looks_ safe, and may work most of the time or always with some
configurations.
2. If you really must have recursion, e.g. perhaps the synchronous
path is common and a hot path, beware that this is prone to
mistakes in usage. Check that it's worth the optimisation.
Then document with words like "warning" the need for special
care.
3. If there is immediate callback possible, sometimes it's useful
API to have a flag argument to enable that, so that always
queueing is an option, and so the programmer has to think
about consequences if they set the flag. E.g.:
async_id = async_func (args, callback, cb_arg, CB_ALWAYS_QUEUED);
async_id = async_func (args, callback, cb_arg, CB_MAYBE_IMMEDIATE);
3. The code pattern "async_id = async_func (args, callback,
callback_arg)" looks very natural, but it doesn't work when
there is immediate callback.
Callback is called before the id can be stored anywhere. If
the async_id is still meaningful at the point of callback, the
API is fundamentally broken.
Just a few notes on async callback API pitfalls I've had...
-- Jamie
prev parent reply other threads:[~2008-04-03 11:31 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-03 0:41 [Qemu-devel] QEMU/KVM SCSI lock up Matteo Frigo
2008-04-03 8:38 ` Avi Kivity
2008-04-03 11:18 ` Matteo Frigo
2008-04-03 11:49 ` Avi Kivity
2008-04-03 11:31 ` Jamie Lokier [this message]
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=20080403113128.GA17900@shareable.org \
--to=jamie@shareable.org \
--cc=qemu-devel@nongnu.org \
/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).