From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56951) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZQCDS-0002hG-JT for qemu-devel@nongnu.org; Fri, 14 Aug 2015 06:28:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZQCDR-0006hw-Dx for qemu-devel@nongnu.org; Fri, 14 Aug 2015 06:28:02 -0400 Date: Fri, 14 Aug 2015 11:27:53 +0100 From: Stefan Hajnoczi Message-ID: <20150814102753.GD18914@stefanha-thinkpad.redhat.com> References: <1439455310-11263-1-git-send-email-kwolf@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="9UV9rz0O2dU/yYYn" Content-Disposition: inline In-Reply-To: <1439455310-11263-1-git-send-email-kwolf@redhat.com> Subject: Re: [Qemu-devel] [PATCH] mirror: Fix coroutine reentrance List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Kevin Wolf Cc: famz@redhat.com, qemu-block@nongnu.org, jcody@redhat.com, qemu-stable@nongnu.org, qemu-devel@nongnu.org, pbonzini@redhat.com --9UV9rz0O2dU/yYYn Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, Aug 13, 2015 at 10:41:50AM +0200, Kevin Wolf wrote: > This fixes a regression introduced by commit dcfb3beb ("mirror: Do zero > write on target if sectors not allocated"), which was reported to cause > aborts with the message "Co-routine re-entered recursively". >=20 > The cause for this bug is the following code in mirror_iteration_done(): >=20 > if (s->common.busy) { > qemu_coroutine_enter(s->common.co, NULL); > } >=20 > This has always been ugly because - unlike most places that reenter - it > doesn't have a specific yield that it pairs with, but is more > uncontrolled. What we really mean here is "reenter the coroutine if > it's in one of the four explicit yields in mirror.c". >=20 > This used to be equivalent with s->common.busy because neither > mirror_run() nor mirror_iteration() call any function that could yield. > However since commit dcfb3beb this doesn't hold true any more: > bdrv_get_block_status_above() can yield. >=20 > So what happens is that bdrv_get_block_status_above() wants to take a > lock that is already held, so it adds itself to the queue of waiting > coroutines and yields. Instead of being woken up by the unlock function, > however, it gets woken up by mirror_iteration_done(), which is obviously > wrong. >=20 > In most cases the code actually happens to cope fairly well with such > cases, but in this specific case, the unlock must already have scheduled > the coroutine for wakeup when mirror_iteration_done() reentered it. And > then the coroutine happened to process the scheduled restarts and tried > to reenter itself recursively. >=20 > This patch fixes the problem by pairing the reenter in > mirror_iteration_done() with specific yields instead of abusing > s->common.busy. >=20 > Cc: qemu-stable@nongnu.org > Signed-off-by: Kevin Wolf > --- > block/mirror.c | 15 ++++++++++----- > 1 file changed, 10 insertions(+), 5 deletions(-) Reviewed-by: Stefan Hajnoczi --9UV9rz0O2dU/yYYn Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJVzcKpAAoJEJykq7OBq3PIqNcIAJTxXYxfA8Cg+0MFeVUtz1zQ hALXJWiI7CEWvJEcTso2PM/qIAi2P0Rhf7U9FfJ3NyTUdO6MGykTs8zUb5ka/Lv+ aXjsT+TbzKJ9wSheK2oDQb0qkQLzUt+1weKW+juYWUGVtFbduXKOFzWXaF2vf5q6 49LvcauMWdU0zGa51MgWVnWRDk4BHHNujRDdRiKTmAE5rey3AVylgtxN8Cbww++A QDgR64bLQG45o5Xcn7G6oe7FZEV4CjAVj7a2J1sbA/JjNjPcAI23U/OUmyzMewwN vjzPgI1fHQhR7SjI0hI1PYOmC3UnSeC/a66210mNUeBoZR27f2j5g8kCY3A3P7o= =/guI -----END PGP SIGNATURE----- --9UV9rz0O2dU/yYYn--