From nobody Fri May 3 13:41:27 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559144989; cv=none; d=zoho.com; s=zohoarc; b=UQ09fiKpGy8U6npOS7Mrty7TwvrTLOAP/bJ3ODKXdsVvqU0OPFHnWatJOqpnid3AY7PGRvQiSi29Z8aByET5TfjtrLT2q3Z4+2Yq0zU+zj/bCzz+4ZZywdZJ7g/UVmxo3tPpeAGYFn+RUGyKTh3POfHLzxLPksJ2IKcOjwomwiA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559144989; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=n0gqO42z6k+lf2VyaGVfR4DS9heUxIiEC4OmZatpPo4=; b=hUl94iJJhK19BhX7UU1aUk7nH82Ca+wOTKaP3TT1dgNUOplwKlSJXSTopHu8mCSDHliC7iELRn625kDFFTLYhsv/mi3pEawXLf2S05tw8zG9CVbkKNFaXsKuQfxs95MNnTJYhuAJmVonURaskgC7P5vsVwKum6fJ+fx4XPVvKYs= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559144989240952.2048018092333; Wed, 29 May 2019 08:49:49 -0700 (PDT) Received: from localhost ([127.0.0.1]:56884 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0pe-0005qq-QF for importer@patchew.org; Wed, 29 May 2019 11:49:38 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54885) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0n9-0004V8-2u for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW0n7-00053L-RU for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:03 -0400 Received: from relay.sw.ru ([185.231.240.75]:43116) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hW0n7-00051u-JR; Wed, 29 May 2019 11:47:01 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hW0n1-0004iP-Qs; Wed, 29 May 2019 18:46:55 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 29 May 2019 18:46:48 +0300 Message-Id: <20190529154654.95870-2-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190529154654.95870-1-vsementsov@virtuozzo.com> References: <20190529154654.95870-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v8 1/7] block: teach bdrv_debug_breakpoint skip filters with backing X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Teach bdrv_debug_breakpoint and bdrv_debug_remove_breakpoint skip filters with backing. This is needed to implement and use in backup job it's own backup_top filter driver (like mirror already has one), and without this improvement, breakpoint removal will fail at least in 55 iotest. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index 1a73e310c1..e6e9770704 100644 --- a/block.c +++ b/block.c @@ -4982,14 +4982,35 @@ void bdrv_debug_event(BlockDriverState *bs, Blkdebu= gEvent event) bs->drv->bdrv_debug_event(bs, event); } =20 -int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event, - const char *tag) +static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs) { while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) { - bs =3D bs->file ? bs->file->bs : NULL; + if (bs->file) { + bs =3D bs->file->bs; + continue; + } + + if (bs->drv->is_filter && bs->backing) { + bs =3D bs->backing->bs; + continue; + } + + break; } =20 if (bs && bs->drv && bs->drv->bdrv_debug_breakpoint) { + assert(bs->drv->bdrv_debug_remove_breakpoint); + return bs; + } + + return NULL; +} + +int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event, + const char *tag) +{ + bs =3D bdrv_find_debug_node(bs); + if (bs) { return bs->drv->bdrv_debug_breakpoint(bs, event, tag); } =20 @@ -4998,11 +5019,8 @@ int bdrv_debug_breakpoint(BlockDriverState *bs, cons= t char *event, =20 int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag) { - while (bs && bs->drv && !bs->drv->bdrv_debug_remove_breakpoint) { - bs =3D bs->file ? bs->file->bs : NULL; - } - - if (bs && bs->drv && bs->drv->bdrv_debug_remove_breakpoint) { + bs =3D bdrv_find_debug_node(bs); + if (bs) { return bs->drv->bdrv_debug_remove_breakpoint(bs, tag); } =20 --=20 2.18.0 From nobody Fri May 3 13:41:27 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559144979; cv=none; d=zoho.com; s=zohoarc; b=mdYB5fuA4Px5EG6I9h2DIBWsd5Rokgywr9quanv9hfbLEEdYRkW5sKJbQMbwsvdkTxmmz4ceBjswH00b4F2jwTxC5Tt6vxPEnRje02AEkM+kHYrcEHrHMFg58WnEmwYg+GpHGTfNqEy2Qk4s+AC3bif0/7sHikUVLMMx0dabEGY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559144979; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=h16YniulhqgXnsOXklN7xooWCPpJLPoYdl+ebYaFAHg=; b=LtYqUOsAVn1cCZucwjQe2/UZHQYWgNIY9AacvTdd5r0oor6q/oL/kIhtNkLyL73P6PWcHkqAo/qVtjTEnMbEdmTUH2LikdeYI0lhMKl3eZLX+iQDNbqKImIH9Z5qOJw+bukLDz+186eiSGRkAmQumAIDAhdOuyOod4xmKdHTOfU= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 15591449795265.499245217949692; Wed, 29 May 2019 08:49:39 -0700 (PDT) Received: from localhost ([127.0.0.1]:56878 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0pY-0005lZ-Mz for importer@patchew.org; Wed, 29 May 2019 11:49:32 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54880) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0n8-0004V6-W0 for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW0n7-000537-Qt for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:02 -0400 Received: from relay.sw.ru ([185.231.240.75]:43136) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hW0n7-00051s-I0; Wed, 29 May 2019 11:47:01 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hW0n2-0004iP-2z; Wed, 29 May 2019 18:46:56 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 29 May 2019 18:46:49 +0300 Message-Id: <20190529154654.95870-3-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190529154654.95870-1-vsementsov@virtuozzo.com> References: <20190529154654.95870-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v8 2/7] block: swap operation order in bdrv_append X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" bs_top parents may conflict with bs_new backing child permissions, so let's do bdrv_replace_node first, it covers more possible cases. It is needed for further implementation of backup-top filter, which don't want to share write permission on its backing child. Side effect is that we may set backing hd when device name is already available, so 085 iotest output is changed. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block.c | 11 ++++++++--- tests/qemu-iotests/085.out | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index e6e9770704..57216f4115 100644 --- a/block.c +++ b/block.c @@ -4088,22 +4088,27 @@ void bdrv_append(BlockDriverState *bs_new, BlockDri= verState *bs_top, { Error *local_err =3D NULL; =20 - bdrv_set_backing_hd(bs_new, bs_top, &local_err); + bdrv_ref(bs_top); + + bdrv_replace_node(bs_top, bs_new, &local_err); if (local_err) { error_propagate(errp, local_err); + error_prepend(errp, "Failed to replace node: "); goto out; } =20 - bdrv_replace_node(bs_top, bs_new, &local_err); + bdrv_set_backing_hd(bs_new, bs_top, &local_err); if (local_err) { + bdrv_replace_node(bs_new, bs_top, &error_abort); error_propagate(errp, local_err); - bdrv_set_backing_hd(bs_new, NULL, &error_abort); + error_prepend(errp, "Failed to set backing: "); goto out; } =20 /* bs_new is now referenced by its new parents, we don't need the * additional reference any more. */ out: + bdrv_unref(bs_top); bdrv_unref(bs_new); } =20 diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out index 6edf107f55..e5a2645bf5 100644 --- a/tests/qemu-iotests/085.out +++ b/tests/qemu-iotests/085.out @@ -74,7 +74,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D13421= 7728 backing_file=3DTEST_DIR/ =20 =3D=3D=3D Invalid command - snapshot node used as backing hd =3D=3D=3D =20 -{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node = is used as backing hd of 'snap_12'"}} +{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node = is used as backing hd of 'virtio0'"}} =20 =3D=3D=3D Invalid command - snapshot node has a backing image =3D=3D=3D =20 --=20 2.18.0 From nobody Fri May 3 13:41:27 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559144984; cv=none; d=zoho.com; s=zohoarc; b=V0k3jP7fbC/mePgWxFWzX0uoIZPFnBwdHiIdE6J3r9XpV6+woNqBNWBLE7uLAYnHM6vI9VbAhGxKSF7ZsoGhy0k0sezY8Q4bsnq4D5jkSTsf4uhWeGBjwiZq4uwnIWobcQF2KznFcaJseb1qrmjPN8UKjLsqoO8JhTnDVhlOVY4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559144984; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=HOajXc7kGd5NDgrSSsMnOo3ldsI/Ii1xm0S92qjmAm0=; b=MhyYumqCgf2fsJnK8F4JE/hU2dj+WHIeMrnUo3wKYYyuEECn6ub0jAREsojPGUZB7rv58q5mlO3ZhlP4IO1ZiaGjD/E0B0fP6clXVi2bZKJ6h2Rutvqi2LlE9NdpWCnJ7f8eRrIml8gVLGtkH2X/15QaUncgySKaN90vlVp5RD4= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559144983899766.8044255962135; Wed, 29 May 2019 08:49:43 -0700 (PDT) Received: from localhost ([127.0.0.1]:56880 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0pa-0005n9-SL for importer@patchew.org; Wed, 29 May 2019 11:49:34 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54878) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0n8-0004V5-Vo for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW0n7-00053R-Rh for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:02 -0400 Received: from relay.sw.ru ([185.231.240.75]:43146) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hW0n7-00051w-IO; Wed, 29 May 2019 11:47:01 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hW0n2-0004iP-7J; Wed, 29 May 2019 18:46:56 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 29 May 2019 18:46:50 +0300 Message-Id: <20190529154654.95870-4-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190529154654.95870-1-vsementsov@virtuozzo.com> References: <20190529154654.95870-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v8 3/7] block: allow not one child for implicit node X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Upcoming backup-top filter wants to operate like usual implicit filter node with fall-through to backing child. But also needs additional target child, let's support that. On the other hand, after backup completion (before job dismiss) filter is still attached to job blk, but don't have any children. Support this too. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz --- block.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 57216f4115..3f4de3ae32 100644 --- a/block.c +++ b/block.c @@ -6200,9 +6200,20 @@ void bdrv_refresh_filename(BlockDriverState *bs) } =20 if (bs->implicit) { - /* For implicit nodes, just copy everything from the single child = */ + /* + * For implicit nodes, just copy everything from the single child = or + * from backing, if there are several children. + * If there are no children for some reason (filter is still attac= hed + * to block-job blk, but already removed from backing chain of dev= ice) + * do nothing. + */ child =3D QLIST_FIRST(&bs->children); - assert(QLIST_NEXT(child, next) =3D=3D NULL); + if (!child) { + return; + } else if (QLIST_NEXT(child, next)) { + assert(bs->backing); + child =3D bs->backing; + } =20 pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), child->bs->exact_filename); --=20 2.18.0 From nobody Fri May 3 13:41:27 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559145295; cv=none; d=zoho.com; s=zohoarc; b=g9XM8lrWxh5p8BDDO6xnYR5OPJFaAdoofjye8ElJSit7JE6Fef+K4TOXtZZ7vz0Y3jJxj93+wOUuvX2v4jxg1Jt5q42btlRV2J2vSqePshNZQ3LWXCrqB/MA3CRVIb+j3k4oz6G1tcJqehUNxL2VC1Zv2+IV9rlHpn1P8HzpBOc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559145295; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=U2VW4F1ZzafAocfzw+Afk0vY+RgbElOOqR8URHYa3cw=; b=ifqLAalp4g8GnmCyPczXwGUR0WvpRdes/juLOgBuDq2azgkCuWRvqkZNthqdZE06KuGgA5n76x3k+pT8wvCoavAzcEUiXLobncI4E9RPRZHjLu2DhnQmtU3cL8mRcc3Q4dUArXEGkyW51oJtMc9E7oiGy4KKXuvR0hyicx0aNjA= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559145295365839.2903712310324; Wed, 29 May 2019 08:54:55 -0700 (PDT) Received: from localhost ([127.0.0.1]:56967 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0uK-0001Tv-DB for importer@patchew.org; Wed, 29 May 2019 11:54:28 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54922) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0nA-0004VP-7c for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW0n7-00053i-V9 for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:04 -0400 Received: from relay.sw.ru ([185.231.240.75]:43122) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hW0n7-00051q-Hy; Wed, 29 May 2019 11:47:01 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hW0n2-0004iP-DV; Wed, 29 May 2019 18:46:56 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 29 May 2019 18:46:51 +0300 Message-Id: <20190529154654.95870-5-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190529154654.95870-1-vsementsov@virtuozzo.com> References: <20190529154654.95870-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v8 4/7] block: introduce backup-top filter driver X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Backup-top filter does copy-before-write operation. It should be inserted above active disk and has a target node for CBW, like the following: +-------+ | Guest | +-------+ |r,w v +------------+ target +---------------+ | backup_top |---------->| target(qcow2) | +------------+ CBW +---------------+ | backing |r,w v +-------------+ | Active disk | +-------------+ The driver will be used in backup instead of write-notifiers. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup-top.h | 64 +++++++++ block/backup-top.c | 322 ++++++++++++++++++++++++++++++++++++++++++++ block/Makefile.objs | 2 + 3 files changed, 388 insertions(+) create mode 100644 block/backup-top.h create mode 100644 block/backup-top.c diff --git a/block/backup-top.h b/block/backup-top.h new file mode 100644 index 0000000000..788e18c358 --- /dev/null +++ b/block/backup-top.h @@ -0,0 +1,64 @@ +/* + * backup-top filter driver + * + * The driver performs Copy-Before-Write (CBW) operation: it is injected a= bove + * some node, and before each write it copies _old_ data to the target nod= e. + * + * Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved. + * + * Author: + * Sementsov-Ogievskiy Vladimir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BACKUP_TOP_H +#define BACKUP_TOP_H + +#include "qemu/osdep.h" + +#include "block/block_int.h" + +typedef void (*BackupTopProgressCallback)(uint64_t done, void *opaque); +typedef struct BDRVBackupTopState { + HBitmap *copy_bitmap; /* what should be copied to @target on guest wri= te. */ + BdrvChild *target; + + BackupTopProgressCallback progress_cb; + void *progress_opaque; +} BDRVBackupTopState; + +/* + * bdrv_backup_top_append + * + * Append backup_top filter node above @source node. @target node will rec= eive + * the data backed up during CBE operations. New filter together with @tar= get + * node are attached to @source aio context. + * + * The resulting filter node is implicit. + * + * @copy_bitmap selects regions which needs CBW. Furthermore, backup_top w= ill + * use exactly this bitmap, so it may be used to control backup_top behavi= or + * dynamically. Caller should not release @copy_bitmap during life-time of + * backup_top. Progress is tracked by calling @progress_cb function. + */ +BlockDriverState *bdrv_backup_top_append( + BlockDriverState *source, BlockDriverState *target, + HBitmap *copy_bitmap, Error **errp); +void bdrv_backup_top_set_progress_callback( + BlockDriverState *bs, BackupTopProgressCallback progress_cb, + void *progress_opaque); +void bdrv_backup_top_drop(BlockDriverState *bs); + +#endif /* BACKUP_TOP_H */ diff --git a/block/backup-top.c b/block/backup-top.c new file mode 100644 index 0000000000..1daa02f539 --- /dev/null +++ b/block/backup-top.c @@ -0,0 +1,322 @@ +/* + * backup-top filter driver + * + * The driver performs Copy-Before-Write (CBW) operation: it is injected a= bove + * some node, and before each write it copies _old_ data to the target nod= e. + * + * Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved. + * + * Author: + * Sementsov-Ogievskiy Vladimir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "qemu/osdep.h" + +#include "qemu/cutils.h" +#include "qapi/error.h" +#include "block/block_int.h" +#include "block/qdict.h" + +#include "block/backup-top.h" + +static coroutine_fn int backup_top_co_preadv( + BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) +{ + /* + * Features to be implemented: + * F1. COR. save read data to fleecing target for fast access + * (to reduce reads). This possibly may be done with use of copy-o= n-read + * filter, but we need an ability to make COR requests optional: f= or + * example, if target is a ram-cache, and if it is full now, we sh= ould + * skip doing COR request, as it is actually not necessary. + * + * F2. Feature for guest: read from fleecing target if data is in ram-= cache + * and is unchanged + */ + + return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags); +} + +static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offs= et, + uint64_t bytes) +{ + int ret =3D 0; + BDRVBackupTopState *s =3D bs->opaque; + uint64_t gran =3D 1UL << hbitmap_granularity(s->copy_bitmap); + uint64_t end =3D QEMU_ALIGN_UP(offset + bytes, gran); + uint64_t off =3D QEMU_ALIGN_DOWN(offset, gran), len; + void *buf =3D qemu_blockalign(bs, end - off); + + /* + * Features to be implemented: + * F3. parallelize copying loop + * F4. detect zeroes ? or, otherwise, drop detect zeroes from backup c= ode + * and just enable zeroes detecting on target + * F5. use block_status ? + * F6. don't copy clusters which are already cached by COR [see F1] + * F7. if target is ram-cache and it is full, there should be a possib= ility + * to drop not necessary data (cached by COR [see F1]) to handle C= BW + * fast. + */ + + len =3D end - off; + while (hbitmap_next_dirty_area(s->copy_bitmap, &off, &len)) { + hbitmap_reset(s->copy_bitmap, off, len); + + ret =3D bdrv_co_pread(bs->backing, off, len, buf, + BDRV_REQ_NO_SERIALISING); + if (ret < 0) { + hbitmap_set(s->copy_bitmap, off, len); + goto out; + } + + ret =3D bdrv_co_pwrite(s->target, off, len, buf, BDRV_REQ_SERIALIS= ING); + if (ret < 0) { + hbitmap_set(s->copy_bitmap, off, len); + goto out; + } + + if (s->progress_cb) { + s->progress_cb(len, s->progress_opaque); + } + off +=3D len; + if (off >=3D end) { + break; + } + len =3D end - off; + } + +out: + qemu_vfree(buf); + + /* + * F8. we fail guest request in case of error. We can alter it by + * possibility to fail copying process instead, or retry several times= , or + * may be guest pause, etc. + */ + return ret; +} + +static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs, + int64_t offset, int bytes) +{ + int ret =3D backup_top_cbw(bs, offset, bytes); + if (ret < 0) { + return ret; + } + + /* + * Features to be implemented: + * F9. possibility of lazy discard: just defer the discard after fleec= ing + * completion. If write (or new discard) occurs to the same area, = just + * drop deferred discard. + */ + + return bdrv_co_pdiscard(bs->backing, offset, bytes); +} + +static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs, + int64_t offset, int bytes, BdrvRequestFlags flags) +{ + int ret =3D backup_top_cbw(bs, offset, bytes); + if (ret < 0) { + return ret; + } + + return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags); +} + +static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs, + uint64_t offset, + uint64_t bytes, + QEMUIOVector *qiov, int flag= s) +{ + if (!(flags & BDRV_REQ_WRITE_UNCHANGED)) { + int ret =3D backup_top_cbw(bs, offset, bytes); + if (ret < 0) { + return ret; + } + } + + return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags); +} + +static int coroutine_fn backup_top_co_flush(BlockDriverState *bs) +{ + if (!bs->backing) { + return 0; + } + + return bdrv_co_flush(bs->backing->bs); +} + +static void backup_top_refresh_filename(BlockDriverState *bs) +{ + if (bs->backing =3D=3D NULL) { + /* + * we can be here after failed bdrv_attach_child in + * bdrv_set_backing_hd + */ + return; + } + bdrv_refresh_filename(bs->backing->bs); + pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), + bs->backing->bs->filename); +} + +static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildRole *role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +{ + /* + * We have HBitmap in the state, its size is fixed, so we never allow + * resize. + */ + uint64_t rw =3D BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | + BLK_PERM_WRITE; + + bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared, + nperm, nshared); + + *nperm =3D *nperm & rw; + *nshared =3D *nshared & rw; + + if (role =3D=3D &child_file) { + /* + * Target child + * + * Share write to target (child_file), to not interfere + * with guest writes to its disk which may be in target backing ch= ain. + */ + if (perm & BLK_PERM_WRITE) { + *nshared =3D *nshared | BLK_PERM_WRITE; + } + } else { + /* Source child */ + if (perm & BLK_PERM_WRITE) { + *nperm =3D *nperm | BLK_PERM_CONSISTENT_READ; + } + *nshared =3D + *nshared & (BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGE= D); + } +} + +BlockDriver bdrv_backup_top_filter =3D { + .format_name =3D "backup-top", + .instance_size =3D sizeof(BDRVBackupTopState), + + .bdrv_co_preadv =3D backup_top_co_preadv, + .bdrv_co_pwritev =3D backup_top_co_pwritev, + .bdrv_co_pwrite_zeroes =3D backup_top_co_pwrite_zeroes, + .bdrv_co_pdiscard =3D backup_top_co_pdiscard, + .bdrv_co_flush =3D backup_top_co_flush, + + .bdrv_co_block_status =3D bdrv_co_block_status_from_backing, + + .bdrv_refresh_filename =3D backup_top_refresh_filename, + + .bdrv_child_perm =3D backup_top_child_perm, + + .is_filter =3D true, +}; + +BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, + BlockDriverState *target, + HBitmap *copy_bitmap, + Error **errp) +{ + Error *local_err =3D NULL; + BDRVBackupTopState *state; + BlockDriverState *top =3D bdrv_new_open_driver(&bdrv_backup_top_filter, + NULL, BDRV_O_RDWR, errp); + + if (!top) { + return NULL; + } + + top->implicit =3D true; + top->total_sectors =3D source->total_sectors; + top->bl.opt_mem_alignment =3D MAX(bdrv_opt_mem_align(source), + bdrv_opt_mem_align(target)); + top->opaque =3D state =3D g_new0(BDRVBackupTopState, 1); + state->copy_bitmap =3D copy_bitmap; + + bdrv_ref(target); + state->target =3D bdrv_attach_child(top, target, "target", &child_file= , errp); + if (!state->target) { + bdrv_unref(target); + bdrv_unref(top); + return NULL; + } + + bdrv_set_aio_context(top, bdrv_get_aio_context(source)); + bdrv_set_aio_context(target, bdrv_get_aio_context(source)); + + bdrv_drained_begin(source); + + bdrv_ref(top); + bdrv_append(top, source, &local_err); + if (local_err) { + error_prepend(&local_err, "Cannot append backup-top filter: "); + } + + bdrv_drained_end(source); + + if (local_err) { + bdrv_unref_child(top, state->target); + bdrv_unref(top); + error_propagate(errp, local_err); + return NULL; + } + + return top; +} + +void bdrv_backup_top_set_progress_callback( + BlockDriverState *bs, BackupTopProgressCallback progress_cb, + void *progress_opaque) +{ + BDRVBackupTopState *s =3D bs->opaque; + + s->progress_cb =3D progress_cb; + s->progress_opaque =3D progress_opaque; +} + +void bdrv_backup_top_drop(BlockDriverState *bs) +{ + BDRVBackupTopState *s =3D bs->opaque; + AioContext *aio_context =3D bdrv_get_aio_context(bs); + + aio_context_acquire(aio_context); + + bdrv_drained_begin(bs); + + bdrv_child_try_set_perm(bs->backing, 0, BLK_PERM_ALL, &error_abort); + bdrv_replace_node(bs, backing_bs(bs), &error_abort); + bdrv_set_backing_hd(bs, NULL, &error_abort); + + bdrv_drained_end(bs); + + if (s->target) { + bdrv_unref_child(bs, s->target); + } + bdrv_unref(bs); + + aio_context_release(aio_context); +} diff --git a/block/Makefile.objs b/block/Makefile.objs index ae11605c9f..dfbdfe6ab4 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -40,6 +40,8 @@ block-obj-y +=3D throttle.o copy-on-read.o =20 block-obj-y +=3D crypto.o =20 +block-obj-y +=3D backup-top.o + common-obj-y +=3D stream.o =20 nfs.o-libs :=3D $(LIBNFS_LIBS) --=20 2.18.0 From nobody Fri May 3 13:41:27 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559144987; cv=none; d=zoho.com; s=zohoarc; b=TNHRIj6YFJPTWAaIPCi8j86tC0YZ9T+BJeiN4VNPGEUA8hz1vWbiBJAn4kvgkM2yiKfHj8YO4UT3ESrcp9Ay+4xAKuXepdl/5YsUt6u9MEb9DVCG4uCy/rUtCd1iLF+jwvO61VtBA6QP+EGN/7vSRzmJkdy/pdcTentvAem204c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559144987; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=8XlCREkeauM/5cS8ywQOMV2Tl+1a1OTc/h7AMK55owQ=; b=NdXnphxRosDWK8KZWC8WZN3FWYHlBBK5NI9CJ4kznVGwzwgBd+yJ15K2BwIEyZITKYm3zmCqsLGcpReSZ+FVQF3WhevjSx5CTW8ITvQJCyqjG0WmrmiY7pz7OUUtlo9w4cHRRa2Jh9Q5T/CLL8M5+SqEiBuWY0Go9msiNIFUTsg= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 155914498751253.15887676261741; Wed, 29 May 2019 08:49:47 -0700 (PDT) Received: from localhost ([127.0.0.1]:56882 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0pb-0005or-Ff for importer@patchew.org; Wed, 29 May 2019 11:49:35 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54875) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0n8-0004V3-Sb for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW0n7-00053Q-RW for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:02 -0400 Received: from relay.sw.ru ([185.231.240.75]:43132) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hW0n7-00051r-JQ; Wed, 29 May 2019 11:47:01 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hW0n2-0004iP-KH; Wed, 29 May 2019 18:46:56 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 29 May 2019 18:46:52 +0300 Message-Id: <20190529154654.95870-6-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190529154654.95870-1-vsementsov@virtuozzo.com> References: <20190529154654.95870-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v8 5/7] block/io: refactor wait_serialising_requests X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Split out do_wait_serialising_requests with additional possibility to not actually wait but just check, that there is something to wait for. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz --- block/io.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/block/io.c b/block/io.c index 3134a60a48..c347f90722 100644 --- a/block/io.c +++ b/block/io.c @@ -720,12 +720,13 @@ void bdrv_dec_in_flight(BlockDriverState *bs) bdrv_wakeup(bs); } =20 -static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *sel= f) +static bool coroutine_fn do_wait_serialising_requests(BdrvTrackedRequest *= self, + bool wait) { BlockDriverState *bs =3D self->bs; BdrvTrackedRequest *req; bool retry; - bool waited =3D false; + bool found =3D false; =20 if (!atomic_read(&bs->serialising_in_flight)) { return false; @@ -751,11 +752,13 @@ static bool coroutine_fn wait_serialising_requests(Bd= rvTrackedRequest *self) * will wait for us as soon as it wakes up, then just go on * (instead of producing a deadlock in the former case). */ if (!req->waiting_for) { - self->waiting_for =3D req; - qemu_co_queue_wait(&req->wait_queue, &bs->reqs_lock); - self->waiting_for =3D NULL; - retry =3D true; - waited =3D true; + found =3D true; + if (wait) { + self->waiting_for =3D req; + qemu_co_queue_wait(&req->wait_queue, &bs->reqs_loc= k); + self->waiting_for =3D NULL; + retry =3D true; + } break; } } @@ -763,7 +766,12 @@ static bool coroutine_fn wait_serialising_requests(Bdr= vTrackedRequest *self) qemu_co_mutex_unlock(&bs->reqs_lock); } while (retry); =20 - return waited; + return found; +} + +static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *sel= f) +{ + return do_wait_serialising_requests(self, true); } =20 static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset, --=20 2.18.0 From nobody Fri May 3 13:41:27 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559145157; cv=none; d=zoho.com; s=zohoarc; b=QbpeDBWN2vbMqXkavrg0SOPVe6stdrenex6Y2a2ujQ6S334v/qlnE9mI1m6rj1DfJ136ZCWRL2HKWHy3AF9FmsH3tndSJpCbkDm1p//XoKie5dt1tY5vE2NWYODLQHF90wRWXz5HhWdUZUNhuVvR3BVXtY6vrKp8iVUEAK0Spz0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559145157; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=zbvaQdxwc+IK9z1AL+AVyvYsa8LRUv6Kf8sdysAZLts=; b=abJgRBwtZTHW/pE53k9TreL+K39ixLGTagkjEJh0QCWyhFlk1/pK6K/Bp1q9k4SD8rq2YfJpgPJGSNcltAg4xObIA09+ZN7QMm8EQqpK/4jXtt8FQTLhJOJWtvBLNO3UyuyAMNROZIpruXIL7u2QHsyrSR7xB5u76CQNZuGyDFo= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 155914515726698.83055049200755; Wed, 29 May 2019 08:52:37 -0700 (PDT) Received: from localhost ([127.0.0.1]:56939 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0sQ-0008Qk-9a for importer@patchew.org; Wed, 29 May 2019 11:52:30 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54883) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0n9-0004V7-0V for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW0n7-00053F-RP for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:02 -0400 Received: from relay.sw.ru ([185.231.240.75]:43142) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hW0n7-00051x-IO; Wed, 29 May 2019 11:47:01 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hW0n2-0004iP-Pv; Wed, 29 May 2019 18:46:56 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 29 May 2019 18:46:53 +0300 Message-Id: <20190529154654.95870-7-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190529154654.95870-1-vsementsov@virtuozzo.com> References: <20190529154654.95870-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v8 6/7] block: add lock/unlock range functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Vladimir Sementsov-Ogievskiy Introduce lock/unlock range functionality, based on serialized requests. This is needed to refactor backup, dropping local tracked-request-like synchronization. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz --- include/block/block_int.h | 4 ++++ block/io.c | 44 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/block/block_int.h b/include/block/block_int.h index 1eebc7c8f3..9d9d4346e9 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -66,6 +66,7 @@ enum BdrvTrackedRequestType { BDRV_TRACKED_WRITE, BDRV_TRACKED_DISCARD, BDRV_TRACKED_TRUNCATE, + BDRV_TRACKED_LOCK, }; =20 typedef struct BdrvTrackedRequest { @@ -928,6 +929,9 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, int coroutine_fn bdrv_co_pwritev(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); +void *coroutine_fn bdrv_co_try_lock(BlockDriverState *bs, + int64_t offset, unsigned int bytes); +void coroutine_fn bdrv_co_unlock(void *opaque); =20 static inline int coroutine_fn bdrv_co_pread(BdrvChild *child, int64_t offset, unsigned int bytes, void *buf, BdrvRequestFlags flags) diff --git a/block/io.c b/block/io.c index c347f90722..488e01e0a1 100644 --- a/block/io.c +++ b/block/io.c @@ -720,6 +720,15 @@ void bdrv_dec_in_flight(BlockDriverState *bs) bdrv_wakeup(bs); } =20 +static bool ignore_intersection(BdrvTrackedRequest *a, BdrvTrackedRequest = *b) +{ + return a =3D=3D b || (!a->serialising && !b->serialising) || + (a->type =3D=3D BDRV_TRACKED_LOCK && b->type =3D=3D BDRV_TRACKED_R= EAD && + !b->serialising) || + (b->type =3D=3D BDRV_TRACKED_LOCK && a->type =3D=3D BDRV_TRACKED_R= EAD && + !a->serialising); +} + static bool coroutine_fn do_wait_serialising_requests(BdrvTrackedRequest *= self, bool wait) { @@ -736,7 +745,7 @@ static bool coroutine_fn do_wait_serialising_requests(B= drvTrackedRequest *self, retry =3D false; qemu_co_mutex_lock(&bs->reqs_lock); QLIST_FOREACH(req, &bs->tracked_requests, list) { - if (req =3D=3D self || (!req->serialising && !self->serialisin= g)) { + if (ignore_intersection(self, req)) { continue; } if (tracked_request_overlaps(req, self->overlap_offset, @@ -774,6 +783,12 @@ static bool coroutine_fn wait_serialising_requests(Bdr= vTrackedRequest *self) return do_wait_serialising_requests(self, true); } =20 +static bool coroutine_fn should_wait_serialising_requests( + BdrvTrackedRequest *self) +{ + return do_wait_serialising_requests(self, false); +} + static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset, size_t size) { @@ -3184,3 +3199,30 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, = PreallocMode prealloc, =20 return tco.ret; } + +void *coroutine_fn bdrv_co_try_lock(BlockDriverState *bs, + int64_t offset, unsigned int bytes) +{ + BdrvTrackedRequest *req =3D g_new(BdrvTrackedRequest, 1); + + tracked_request_begin(req, bs, offset, bytes, BDRV_TRACKED_LOCK); + mark_request_serialising(req, bdrv_get_cluster_size(bs)); + + if (should_wait_serialising_requests(req)) { + tracked_request_end(req); + g_free(req); + return NULL; + } + + return req; +} + +void coroutine_fn bdrv_co_unlock(void *opaque) +{ + BdrvTrackedRequest *req =3D opaque; + + assert(req->type =3D=3D BDRV_TRACKED_LOCK); + + tracked_request_end(req); + g_free(req); +} --=20 2.18.0 From nobody Fri May 3 13:41:27 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559145160; cv=none; d=zoho.com; s=zohoarc; b=orpqYiF/defQiiljGwiW48MC1AKDniad53nu5N37KUSpIjMynJTHD4vQO24Og7JjSuPJPDjDkJS6TjAWzx4tVD5i6SsJYFlGFcMyJHfgbSnNekTaFdo+tJr9Wff2Nj3ywLJNWNv40sESk0GuZlWWP0fIx3RyROb0cjeCuo/zP2o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559145160; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=VDGXOK2Rb9MQmOaq1EuM3SzEJEM7hnkJtFymomf7ujE=; b=lD05CeMJPQZZNKMyoVpWEGyefYV/W9QZD8BSn833u5oMttwOUo0uH9tdkJvaLcnj2LM+wwo87f/GtkABzUksPsM2ySC3O6VT1RiAKWNNgCNofOWM2N4p9iPYPscjK7OgbhdWnSMkXmalvc5upCoYfhCRqDERViB4vw4tWCxINQg= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559145160639660.7770749741122; Wed, 29 May 2019 08:52:40 -0700 (PDT) Received: from localhost ([127.0.0.1]:56943 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0sW-0008VK-GT for importer@patchew.org; Wed, 29 May 2019 11:52:36 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54926) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW0nA-0004VV-BR for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW0n7-00053n-VO for qemu-devel@nongnu.org; Wed, 29 May 2019 11:47:04 -0400 Received: from relay.sw.ru ([185.231.240.75]:43144) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hW0n7-00051v-I2; Wed, 29 May 2019 11:47:01 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hW0n3-0004iP-0I; Wed, 29 May 2019 18:46:57 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 29 May 2019 18:46:54 +0300 Message-Id: <20190529154654.95870-8-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190529154654.95870-1-vsementsov@virtuozzo.com> References: <20190529154654.95870-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v8 7/7] block/backup: use backup-top instead of write notifiers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Drop write notifiers and use filter node instead. Changes: 1. copy-before-writes now handled by filter node, so, drop all is_write_notifier arguments. 2. we don't have intersecting requests, so their handling is dropped. Instead, synchronization works as follows: when backup or backup-top starts copying of some area it firstly clears copy-bitmap bits, and nobody touches areas, not marked with dirty bits in copy-bitmap, so there is no intersection. Also, backup job copy operations are surrounded by bdrv region lock, which is actually serializing request, to not interfere with guest writes and not read changed data from source (before reading we clear corresponding bit in copy-bitmap, so, this area is not more handled by backup-top). 3. To sync with in-flight requests at job finish we now have drained removing of the filter, we don't need rw-lock. =3D=3D RFC part =3D=3D iotests changed: 56: op-blocker doesn't shot now, as we set it on source, but then check on filter, when trying to start second backup... Should I workaround it somehow? 129: Hmm, now it is not busy at this moment.. But it's illegal to check busy, as job has pause-points and set busy to false in these points. Why we assert it in this test? 141: Obvious, as drv0 is not root node now, but backing of the filter, when we try to remove it. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 171 ++++++++++++++----------------------- tests/qemu-iotests/056 | 2 +- tests/qemu-iotests/129 | 1 - tests/qemu-iotests/141.out | 2 +- 4 files changed, 68 insertions(+), 108 deletions(-) diff --git a/block/backup.c b/block/backup.c index 00f4f8af53..a5b8e04c9c 100644 --- a/block/backup.c +++ b/block/backup.c @@ -2,6 +2,7 @@ * QEMU backup * * Copyright (C) 2013 Proxmox Server Solutions + * Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved. * * Authors: * Dietmar Maurer (dietmar@proxmox.com) @@ -26,14 +27,9 @@ #include "qemu/bitmap.h" #include "qemu/error-report.h" =20 -#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16) +#include "block/backup-top.h" =20 -typedef struct CowRequest { - int64_t start_byte; - int64_t end_byte; - QLIST_ENTRY(CowRequest) list; - CoQueue wait_queue; /* coroutines blocked on this request */ -} CowRequest; +#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16) =20 typedef struct BackupBlockJob { BlockJob common; @@ -43,13 +39,10 @@ typedef struct BackupBlockJob { MirrorSyncMode sync_mode; BlockdevOnError on_source_error; BlockdevOnError on_target_error; - CoRwlock flush_rwlock; uint64_t len; uint64_t bytes_read; int64_t cluster_size; bool compress; - NotifierWithReturn before_write; - QLIST_HEAD(, CowRequest) inflight_reqs; =20 HBitmap *copy_bitmap; bool use_copy_range; @@ -60,56 +53,17 @@ typedef struct BackupBlockJob { =20 static const BlockJobDriver backup_job_driver; =20 -/* See if in-flight requests overlap and wait for them to complete */ -static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job, - int64_t start, - int64_t end) -{ - CowRequest *req; - bool retry; - - do { - retry =3D false; - QLIST_FOREACH(req, &job->inflight_reqs, list) { - if (end > req->start_byte && start < req->end_byte) { - qemu_co_queue_wait(&req->wait_queue, NULL); - retry =3D true; - break; - } - } - } while (retry); -} - -/* Keep track of an in-flight request */ -static void cow_request_begin(CowRequest *req, BackupBlockJob *job, - int64_t start, int64_t end) -{ - req->start_byte =3D start; - req->end_byte =3D end; - qemu_co_queue_init(&req->wait_queue); - QLIST_INSERT_HEAD(&job->inflight_reqs, req, list); -} - -/* Forget about a completed request */ -static void cow_request_end(CowRequest *req) -{ - QLIST_REMOVE(req, list); - qemu_co_queue_restart_all(&req->wait_queue); -} - /* Copy range to target with a bounce buffer and return the bytes copied. = If * error occurred, return a negative error number */ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job, int64_t start, int64_t end, - bool is_write_notifi= er, bool *error_is_read, void **bounce_buffer) { int ret; BlockBackend *blk =3D job->common.blk; int nbytes; - int read_flags =3D is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0; int write_flags =3D job->serialize_target_writes ? BDRV_REQ_SERIALISIN= G : 0; =20 assert(QEMU_IS_ALIGNED(start, job->cluster_size)); @@ -119,7 +73,7 @@ static int coroutine_fn backup_cow_with_bounce_buffer(Ba= ckupBlockJob *job, *bounce_buffer =3D blk_blockalign(blk, job->cluster_size); } =20 - ret =3D blk_co_pread(blk, start, nbytes, *bounce_buffer, read_flags); + ret =3D blk_co_pread(blk, start, nbytes, *bounce_buffer, 0); if (ret < 0) { trace_backup_do_cow_read_fail(job, start, ret); if (error_is_read) { @@ -154,15 +108,12 @@ fail: /* Copy range to target and return the bytes copied. If error occurred, re= turn a * negative error number. */ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job, - int64_t start, - int64_t end, - bool is_write_notifier) + int64_t start, int64_t end) { int ret; int nr_clusters; BlockBackend *blk =3D job->common.blk; int nbytes; - int read_flags =3D is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0; int write_flags =3D job->serialize_target_writes ? BDRV_REQ_SERIALISIN= G : 0; =20 assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size)); @@ -171,7 +122,7 @@ static int coroutine_fn backup_cow_with_offload(BackupB= lockJob *job, nr_clusters =3D DIV_ROUND_UP(nbytes, job->cluster_size); hbitmap_reset(job->copy_bitmap, start, job->cluster_size * nr_clusters= ); ret =3D blk_co_copy_range(blk, start, job->target, start, nbytes, - read_flags, write_flags); + 0, write_flags); if (ret < 0) { trace_backup_do_cow_copy_range_fail(job, start, ret); hbitmap_set(job->copy_bitmap, start, job->cluster_size * nr_cluste= rs); @@ -183,24 +134,17 @@ static int coroutine_fn backup_cow_with_offload(Backu= pBlockJob *job, =20 static int coroutine_fn backup_do_cow(BackupBlockJob *job, int64_t offset, uint64_t bytes, - bool *error_is_read, - bool is_write_notifier) + bool *error_is_read) { - CowRequest cow_request; int ret =3D 0; int64_t start, end; /* bytes */ void *bounce_buffer =3D NULL; =20 - qemu_co_rwlock_rdlock(&job->flush_rwlock); - start =3D QEMU_ALIGN_DOWN(offset, job->cluster_size); end =3D QEMU_ALIGN_UP(bytes + offset, job->cluster_size); =20 trace_backup_do_cow_enter(job, start, offset, bytes); =20 - wait_for_overlapping_requests(job, start, end); - cow_request_begin(&cow_request, job, start, end); - while (start < end) { if (!hbitmap_get(job->copy_bitmap, start)) { trace_backup_do_cow_skip(job, start); @@ -211,13 +155,13 @@ static int coroutine_fn backup_do_cow(BackupBlockJob = *job, trace_backup_do_cow_process(job, start); =20 if (job->use_copy_range) { - ret =3D backup_cow_with_offload(job, start, end, is_write_noti= fier); + ret =3D backup_cow_with_offload(job, start, end); if (ret < 0) { job->use_copy_range =3D false; } } if (!job->use_copy_range) { - ret =3D backup_cow_with_bounce_buffer(job, start, end, is_writ= e_notifier, + ret =3D backup_cow_with_bounce_buffer(job, start, end, error_is_read, &bounce_buf= fer); } if (ret < 0) { @@ -237,29 +181,11 @@ static int coroutine_fn backup_do_cow(BackupBlockJob = *job, qemu_vfree(bounce_buffer); } =20 - cow_request_end(&cow_request); - trace_backup_do_cow_return(job, offset, bytes, ret); =20 - qemu_co_rwlock_unlock(&job->flush_rwlock); - return ret; } =20 -static int coroutine_fn backup_before_write_notify( - NotifierWithReturn *notifier, - void *opaque) -{ - BackupBlockJob *job =3D container_of(notifier, BackupBlockJob, before_= write); - BdrvTrackedRequest *req =3D opaque; - - assert(req->bs =3D=3D blk_bs(job->common.blk)); - assert(QEMU_IS_ALIGNED(req->offset, BDRV_SECTOR_SIZE)); - assert(QEMU_IS_ALIGNED(req->bytes, BDRV_SECTOR_SIZE)); - - return backup_do_cow(job, req->offset, req->bytes, NULL, true); -} - static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret) { BdrvDirtyBitmap *bm; @@ -295,14 +221,30 @@ static void backup_abort(Job *job) static void backup_clean(Job *job) { BackupBlockJob *s =3D container_of(job, BackupBlockJob, common.job); + BlockJob *bjob =3D &s->common; + BlockDriverState *backup_top =3D blk_bs(s->common.blk); + BlockDriverState *src =3D backup_top->backing->bs; + assert(s->target); blk_unref(s->target); s->target =3D NULL; =20 + bdrv_ref(backup_top); + bdrv_ref(src); + if (s->copy_bitmap) { hbitmap_free(s->copy_bitmap); s->copy_bitmap =3D NULL; } + + bdrv_backup_top_drop(backup_top); + + blk_remove_bs(bjob->blk); + blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort); + blk_insert_bs(bjob->blk, backup_top, &error_abort); + + bdrv_unref(src); + bdrv_unref(backup_top); } =20 void backup_do_checkpoint(BlockJob *job, Error **errp) @@ -391,28 +333,41 @@ static int coroutine_fn backup_loop(BackupBlockJob *j= ob) int64_t offset; HBitmapIter hbi; BlockDriverState *bs =3D blk_bs(job->common.blk); + void *lock; =20 hbitmap_iter_init(&hbi, job->copy_bitmap, 0); while ((offset =3D hbitmap_iter_next(&hbi)) !=3D -1) { + lock =3D bdrv_co_try_lock(backing_bs(blk_bs(job->common.blk)), off= set, + job->cluster_size); + /* + * Dirty bit is set, which means that there are no in-flight + * write requests on this area. We must succeed. + */ + assert(lock); + if (job->sync_mode =3D=3D MIRROR_SYNC_MODE_TOP && bdrv_is_unallocated_range(bs, offset, job->cluster_size)) { hbitmap_reset(job->copy_bitmap, offset, job->cluster_size); + bdrv_co_unlock(lock); continue; } =20 do { if (yield_and_check(job)) { + bdrv_co_unlock(lock); return 0; } - ret =3D backup_do_cow(job, offset, - job->cluster_size, &error_is_read, false); + ret =3D backup_do_cow(job, offset, job->cluster_size, &error_i= s_read); if (ret < 0 && backup_error_action(job, error_is_read, -ret) = =3D=3D BLOCK_ERROR_ACTION_REPORT) { + bdrv_co_unlock(lock); return ret; } } while (ret < 0); + + bdrv_co_unlock(lock); } =20 return 0; @@ -444,12 +399,8 @@ static void backup_incremental_init_copy_bitmap(Backup= BlockJob *job) static int coroutine_fn backup_run(Job *job, Error **errp) { BackupBlockJob *s =3D container_of(job, BackupBlockJob, common.job); - BlockDriverState *bs =3D blk_bs(s->common.blk); int ret =3D 0; =20 - QLIST_INIT(&s->inflight_reqs); - qemu_co_rwlock_init(&s->flush_rwlock); - job_progress_set_remaining(job, s->len); =20 if (s->sync_mode =3D=3D MIRROR_SYNC_MODE_INCREMENTAL) { @@ -458,27 +409,20 @@ static int coroutine_fn backup_run(Job *job, Error **= errp) hbitmap_set(s->copy_bitmap, 0, s->len); } =20 - s->before_write.notify =3D backup_before_write_notify; - bdrv_add_before_write_notifier(bs, &s->before_write); - if (s->sync_mode =3D=3D MIRROR_SYNC_MODE_NONE) { /* All bits are set in copy_bitmap to allow any cluster to be copi= ed. * This does not actually require them to be copied. */ while (!job_is_cancelled(job)) { - /* Yield until the job is cancelled. We just let our before_w= rite - * notify callback service CoW requests. */ + /* + * Yield until the job is cancelled. We just let our backup-t= op + * filter driver service CbW requests. + */ job_yield(job); } } else { ret =3D backup_loop(s); } =20 - notifier_with_return_remove(&s->before_write); - - /* wait until pending backup_do_cow() calls have completed */ - qemu_co_rwlock_wrlock(&s->flush_rwlock); - qemu_co_rwlock_unlock(&s->flush_rwlock); - return ret; } =20 @@ -533,6 +477,11 @@ static int64_t backup_calculate_cluster_size(BlockDriv= erState *target, return MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size); } =20 +static void backup_top_progress(uint64_t done, void *opaque) +{ + job_progress_update((Job *)opaque, done); +} + BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, BlockDriverState *target, int64_t speed, MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap, @@ -548,6 +497,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDr= iverState *bs, int ret; int64_t cluster_size; HBitmap *copy_bitmap =3D NULL; + BlockDriverState *backup_top =3D NULL; =20 assert(bs); assert(target); @@ -616,8 +566,13 @@ BlockJob *backup_job_create(const char *job_id, BlockD= riverState *bs, =20 copy_bitmap =3D hbitmap_alloc(len, ctz32(cluster_size)); =20 + backup_top =3D bdrv_backup_top_append(bs, target, copy_bitmap, errp); + if (!backup_top) { + goto error; + } + /* job->len is fixed, so we can't allow resize */ - job =3D block_job_create(job_id, &backup_job_driver, txn, bs, + job =3D block_job_create(job_id, &backup_job_driver, txn, backup_top, BLK_PERM_CONSISTENT_READ, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD, @@ -626,6 +581,9 @@ BlockJob *backup_job_create(const char *job_id, BlockDr= iverState *bs, goto error; } =20 + bdrv_backup_top_set_progress_callback(backup_top, backup_top_progress, + &job->common.job); + /* The target must match the source in size, so no resize here either = */ job->target =3D blk_new(BLK_PERM_WRITE, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | @@ -662,10 +620,6 @@ BlockJob *backup_job_create(const char *job_id, BlockD= riverState *bs, return &job->common; =20 error: - if (copy_bitmap) { - assert(!job || !job->copy_bitmap); - hbitmap_free(copy_bitmap); - } if (sync_bitmap) { bdrv_reclaim_dirty_bitmap(bs, sync_bitmap, NULL); } @@ -673,6 +627,13 @@ BlockJob *backup_job_create(const char *job_id, BlockD= riverState *bs, backup_clean(&job->common.job); job_early_fail(&job->common.job); } + if (backup_top) { + bdrv_backup_top_drop(backup_top); + } + if (copy_bitmap) { + assert(!job || !job->copy_bitmap); + hbitmap_free(copy_bitmap); + } =20 return NULL; } diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056 index f40fc11a09..d3e6fe4b11 100755 --- a/tests/qemu-iotests/056 +++ b/tests/qemu-iotests/056 @@ -214,7 +214,7 @@ class BackupTest(iotests.QMPTestCase): res =3D self.vm.qmp('query-block-jobs') self.assert_qmp(res, 'return[0]/status', 'concluded') # Leave zombie job un-dismissed, observe a failure: - res =3D self.qmp_backup_and_wait(serror=3D"Node 'drive0' is busy: = block device is in use by block job: backup", + res =3D self.qmp_backup_and_wait(serror=3D'Failed to get "write" l= ock', device=3D'drive0', format=3Diotests= .imgfmt, sync=3D'full', target=3Dself.dest_i= mg, auto_dismiss=3DFalse) diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129 index 9e87e1c8d9..d719492deb 100755 --- a/tests/qemu-iotests/129 +++ b/tests/qemu-iotests/129 @@ -66,7 +66,6 @@ class TestStopWithBlockJob(iotests.QMPTestCase): result =3D self.vm.qmp("stop") self.assert_qmp(result, 'return', {}) result =3D self.vm.qmp("query-block-jobs") - self.assert_qmp(result, 'return[0]/busy', True) self.assert_qmp(result, 'return[0]/ready', False) =20 def test_drive_mirror(self): diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out index 41c7291258..a2645bea1a 100644 --- a/tests/qemu-iotests/141.out +++ b/tests/qemu-iotests/141.out @@ -11,7 +11,7 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=3DIMGFMT size=3D10485= 76 backing_file=3DTEST_DIR/t. {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} {"return": {}} -{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}} +{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is = used as backing hd of 'NODE_NAME'"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset= ": 0, "speed": 0, "type": "backup"}} --=20 2.18.0