]> xenbits.xensource.com Git - people/pauldu/qemu.git/commit
mirror: Confirm we're quiesced only if the job is paused or cancelled
authorSergio Lopez <slp@redhat.com>
Fri, 8 Mar 2019 15:48:53 +0000 (16:48 +0100)
committerKevin Wolf <kwolf@redhat.com>
Tue, 19 Mar 2019 14:49:29 +0000 (15:49 +0100)
commit5e771752a1ffba3a99d7d75b6d492b4a86b59e1b
tree53cce2c5d3125724611c97870dc5f2b8c4f9e4ae
parentb98a66201dbc7cf3b962f4bb260f66100cc75578
mirror: Confirm we're quiesced only if the job is paused or cancelled

While child_job_drained_begin() calls to job_pause(), the job doesn't
actually transition between states until it runs again and reaches a
pause point. This means bdrv_drained_begin() may return with some jobs
using the node still having 'busy == true'.

As a consequence, block_job_detach_aio_context() may get into a
deadlock, waiting for the job to be actually paused, while the coroutine
servicing the job is yielding and doesn't get the opportunity to get
scheduled again. This situation can be reproduced by issuing a
'block-commit' immediately followed by a 'device_del'.

To ensure bdrv_drained_begin() only returns when the jobs have been
paused, we change mirror_drained_poll() to only confirm it's quiesced
when job->paused == true and there aren't any in-flight requests, except
if we reached that point by a drained section initiated by the
mirror/commit job itself.

The other block jobs shouldn't need any changes, as the default
drained_poll() behavior is to only confirm it's quiesced if the job is
not busy or completed.

Signed-off-by: Sergio Lopez <slp@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
block/mirror.c