From nobody Mon Apr 29 08:56:22 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543327781404246.70460853265706; Tue, 27 Nov 2018 06:09:41 -0800 (PST) Received: from localhost ([::1]:42613 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRe3T-000113-Db for importer@patchew.org; Tue, 27 Nov 2018 09:09:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55624) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRe1C-0008BS-4e for qemu-devel@nongnu.org; Tue, 27 Nov 2018 09:07:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gRe1A-0007H7-37 for qemu-devel@nongnu.org; Tue, 27 Nov 2018 09:07:14 -0500 Received: from mx1.redhat.com ([209.132.183.28]:35990) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gRe12-00063r-AX; Tue, 27 Nov 2018 09:07:06 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D5ECA308FB86; Tue, 27 Nov 2018 14:07:01 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-233.ams2.redhat.com [10.36.116.233]) by smtp.corp.redhat.com (Postfix) with ESMTP id B9A4860A35; Tue, 27 Nov 2018 14:07:00 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 27 Nov 2018 15:06:38 +0100 Message-Id: <20181127140640.24830-2-kwolf@redhat.com> In-Reply-To: <20181127140640.24830-1-kwolf@redhat.com> References: <20181127140640.24830-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Tue, 27 Nov 2018 14:07:01 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 1/3] block: Don't inactivate children before parents 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: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" bdrv_child_cb_inactivate() asserts that parents are already inactive when children get inactivated. This precondition is necessary because parents could still issue requests in their inactivation code. When block nodes are created individually with -blockdev, all of them are monitor owned and will be returned by bdrv_next() in an undefined order (in practice, in the order of their creation, which is usually children before parents), which obviously fails the assertion: qemu: block.c:899: bdrv_child_cb_inactivate: Assertion `bs->open_flags & BD= RV_O_INACTIVE' failed. This patch fixes the ordering by skipping nodes with still active parents in bdrv_inactivate_recurse() because we know that they will be covered by recursion when the last active parent becomes inactive. With the correct parents-before-children ordering, we also got rid of the reason why commit aad0b7a0bfb introduced two passes, so we can go back to a single-pass recursion. This is necessary so we can rely on the BDRV_O_INACTIVE flag to skip nodes with active parents (the flag used to be set only in pass 2, so we would always skip non-root nodes in pass 1 because all parents would still be considered active; setting the flag in pass 1 would mean, that we never skip anything in pass 2 because all parents are already considered inactive). Because of the change to single pass, this patch is best reviewed with whitespace changes ignored. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz --- block.c | 84 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/block.c b/block.c index 5ba3435f8f..811239ca23 100644 --- a/block.c +++ b/block.c @@ -4612,45 +4612,68 @@ void bdrv_invalidate_cache_all(Error **errp) } } =20 -static int bdrv_inactivate_recurse(BlockDriverState *bs, - bool setting_flag) +static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active) +{ + BdrvChild *parent; + + QLIST_FOREACH(parent, &bs->parents, next_parent) { + if (parent->role->parent_is_bds) { + BlockDriverState *parent_bs =3D parent->opaque; + if (!only_active || !(parent_bs->open_flags & BDRV_O_INACTIVE)= ) { + return true; + } + } + } + + return false; +} + +static int bdrv_inactivate_recurse(BlockDriverState *bs) { BdrvChild *child, *parent; + uint64_t perm, shared_perm; int ret; =20 if (!bs->drv) { return -ENOMEDIUM; } =20 - if (!setting_flag && bs->drv->bdrv_inactivate) { + /* Make sure that we don't inactivate a child before its parent. + * It will be covered by recursion from the yet active parent. */ + if (bdrv_has_bds_parent(bs, true)) { + return 0; + } + + assert(!(bs->open_flags & BDRV_O_INACTIVE)); + + /* Inactivate this node */ + if (bs->drv->bdrv_inactivate) { ret =3D bs->drv->bdrv_inactivate(bs); if (ret < 0) { return ret; } } =20 - if (setting_flag && !(bs->open_flags & BDRV_O_INACTIVE)) { - uint64_t perm, shared_perm; - - QLIST_FOREACH(parent, &bs->parents, next_parent) { - if (parent->role->inactivate) { - ret =3D parent->role->inactivate(parent); - if (ret < 0) { - return ret; - } + QLIST_FOREACH(parent, &bs->parents, next_parent) { + if (parent->role->inactivate) { + ret =3D parent->role->inactivate(parent); + if (ret < 0) { + return ret; } } + } =20 - bs->open_flags |=3D BDRV_O_INACTIVE; + bs->open_flags |=3D BDRV_O_INACTIVE; + + /* Update permissions, they may differ for inactive nodes */ + bdrv_get_cumulative_perm(bs, &perm, &shared_perm); + bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &error_abort); + bdrv_set_perm(bs, perm, shared_perm); =20 - /* Update permissions, they may differ for inactive nodes */ - bdrv_get_cumulative_perm(bs, &perm, &shared_perm); - bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &error_abort); - bdrv_set_perm(bs, perm, shared_perm); - } =20 + /* Recursively inactivate children */ QLIST_FOREACH(child, &bs->children, next) { - ret =3D bdrv_inactivate_recurse(child->bs, setting_flag); + ret =3D bdrv_inactivate_recurse(child->bs); if (ret < 0) { return ret; } @@ -4664,7 +4687,6 @@ int bdrv_inactivate_all(void) BlockDriverState *bs =3D NULL; BdrvNextIterator it; int ret =3D 0; - int pass; GSList *aio_ctxs =3D NULL, *ctx; =20 for (bs =3D bdrv_first(&it); bs; bs =3D bdrv_next(&it)) { @@ -4676,17 +4698,17 @@ int bdrv_inactivate_all(void) } } =20 - /* We do two passes of inactivation. The first pass calls to drivers' - * .bdrv_inactivate callbacks recursively so all cache is flushed to d= isk; - * the second pass sets the BDRV_O_INACTIVE flag so that no further wr= ite - * is allowed. */ - for (pass =3D 0; pass < 2; pass++) { - for (bs =3D bdrv_first(&it); bs; bs =3D bdrv_next(&it)) { - ret =3D bdrv_inactivate_recurse(bs, pass); - if (ret < 0) { - bdrv_next_cleanup(&it); - goto out; - } + for (bs =3D bdrv_first(&it); bs; bs =3D bdrv_next(&it)) { + /* Nodes with BDS parents are covered by recursion from the last + * parent that gets inactivated. Don't inactivate them a second + * time if that has already happened. */ + if (bdrv_has_bds_parent(bs, false)) { + continue; + } + ret =3D bdrv_inactivate_recurse(bs); + if (ret < 0) { + bdrv_next_cleanup(&it); + goto out; } } =20 --=20 2.19.1 From nobody Mon Apr 29 08:56:22 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543328376902785.2585374089931; Tue, 27 Nov 2018 06:19:36 -0800 (PST) Received: from localhost ([::1]:42686 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gReD4-0002mL-G4 for importer@patchew.org; Tue, 27 Nov 2018 09:19:30 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55673) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRe1L-0008IA-E8 for qemu-devel@nongnu.org; Tue, 27 Nov 2018 09:07:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gRe1I-0008F1-VF for qemu-devel@nongnu.org; Tue, 27 Nov 2018 09:07:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42368) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gRe14-0006Dz-3j; Tue, 27 Nov 2018 09:07:08 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 47E633082E66; Tue, 27 Nov 2018 14:07:03 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-233.ams2.redhat.com [10.36.116.233]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2A521608C3; Tue, 27 Nov 2018 14:07:01 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 27 Nov 2018 15:06:39 +0100 Message-Id: <20181127140640.24830-3-kwolf@redhat.com> In-Reply-To: <20181127140640.24830-1-kwolf@redhat.com> References: <20181127140640.24830-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Tue, 27 Nov 2018 14:07:03 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 2/3] iotests: Test migration with -blockdev 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: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Check that block node activation and inactivation works with a block graph that is built with individually created nodes. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz --- tests/qemu-iotests/234 | 121 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/234.out | 30 +++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 152 insertions(+) create mode 100755 tests/qemu-iotests/234 create mode 100644 tests/qemu-iotests/234.out diff --git a/tests/qemu-iotests/234 b/tests/qemu-iotests/234 new file mode 100755 index 0000000000..a8185b4360 --- /dev/null +++ b/tests/qemu-iotests/234 @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Red Hat, Inc. +# +# 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 . +# +# Creator/Owner: Kevin Wolf +# +# Check that block node activation and inactivation works with a block gra= ph +# that is built with individually created nodes + +import iotests +import os + +iotests.verify_image_format(supported_fmts=3D['qcow2']) +iotests.verify_platform(['linux']) + +with iotests.FilePath('img') as img_path, \ + iotests.FilePath('backing') as backing_path, \ + iotests.FilePath('mig_fifo_a') as fifo_a, \ + iotests.FilePath('mig_fifo_b') as fifo_b, \ + iotests.VM(path_suffix=3D'a') as vm_a, \ + iotests.VM(path_suffix=3D'b') as vm_b: + + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, backing_path, '6= 4M') + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, img_path, '64M') + + os.mkfifo(fifo_a) + os.mkfifo(fifo_b) + + iotests.log('Launching source VM...') + (vm_a.add_blockdev('file,filename=3D%s,node-name=3Ddrive0-file' % (img= _path)) + .add_blockdev('%s,file=3Ddrive0-file,node-name=3Ddrive0' % (iotes= ts.imgfmt)) + .add_blockdev('file,filename=3D%s,node-name=3Ddrive0-backing-file= ' % (backing_path)) + .add_blockdev('%s,file=3Ddrive0-backing-file,node-name=3Ddrive0-b= acking' % (iotests.imgfmt)) + .launch()) + + iotests.log('Launching destination VM...') + (vm_b.add_blockdev('file,filename=3D%s,node-name=3Ddrive0-file' % (img= _path)) + .add_blockdev('%s,file=3Ddrive0-file,node-name=3Ddrive0' % (iotes= ts.imgfmt)) + .add_blockdev('file,filename=3D%s,node-name=3Ddrive0-backing-file= ' % (backing_path)) + .add_blockdev('%s,file=3Ddrive0-backing-file,node-name=3Ddrive0-b= acking' % (iotests.imgfmt)) + .add_incoming("exec: cat '%s'" % (fifo_a)) + .launch()) + + # Add a child node that was created after the parent node. The reverse= case + # is covered by the -blockdev options above. + iotests.log(vm_a.qmp('blockdev-snapshot', node=3D'drive0-backing', + overlay=3D'drive0')) + iotests.log(vm_b.qmp('blockdev-snapshot', node=3D'drive0-backing', + overlay=3D'drive0')) + + iotests.log('Enabling migration QMP events on A...') + iotests.log(vm_a.qmp('migrate-set-capabilities', capabilities=3D[ + { + 'capability': 'events', + 'state': True + } + ])) + + iotests.log('Starting migration to B...') + iotests.log(vm_a.qmp('migrate', uri=3D'exec:cat >%s' % (fifo_a))) + with iotests.Timeout(3, 'Migration does not complete'): + while True: + event =3D vm_a.event_wait('MIGRATION') + iotests.log(event, filters=3D[iotests.filter_qmp_event]) + if event['data']['status'] =3D=3D 'completed': + break + + iotests.log(vm_a.qmp('query-migrate')['return']['status']) + iotests.log(vm_b.qmp('query-migrate')['return']['status']) + + iotests.log(vm_a.qmp('query-status')) + iotests.log(vm_b.qmp('query-status')) + + iotests.log('Add a second parent to drive0-file...') + iotests.log(vm_b.qmp('blockdev-add', driver=3D'raw', file=3D'drive0-fi= le', + node_name=3D'drive0-raw')) + + iotests.log('Restart A with -incoming and second parent...') + vm_a.shutdown() + (vm_a.add_blockdev('raw,file=3Ddrive0-file,node-name=3Ddrive0-raw') + .add_incoming("exec: cat '%s'" % (fifo_b)) + .launch()) + + iotests.log(vm_a.qmp('blockdev-snapshot', node=3D'drive0-backing', + overlay=3D'drive0')) + + iotests.log('Enabling migration QMP events on B...') + iotests.log(vm_b.qmp('migrate-set-capabilities', capabilities=3D[ + { + 'capability': 'events', + 'state': True + } + ])) + + iotests.log('Starting migration back to A...') + iotests.log(vm_b.qmp('migrate', uri=3D'exec:cat >%s' % (fifo_b))) + with iotests.Timeout(3, 'Migration does not complete'): + while True: + event =3D vm_b.event_wait('MIGRATION') + iotests.log(event, filters=3D[iotests.filter_qmp_event]) + if event['data']['status'] =3D=3D 'completed': + break + + iotests.log(vm_a.qmp('query-migrate')['return']['status']) + iotests.log(vm_b.qmp('query-migrate')['return']['status']) + + iotests.log(vm_a.qmp('query-status')) + iotests.log(vm_b.qmp('query-status')) diff --git a/tests/qemu-iotests/234.out b/tests/qemu-iotests/234.out new file mode 100644 index 0000000000..b9ed910b1a --- /dev/null +++ b/tests/qemu-iotests/234.out @@ -0,0 +1,30 @@ +Launching source VM... +Launching destination VM... +{"return": {}} +{"return": {}} +Enabling migration QMP events on A... +{"return": {}} +Starting migration to B... +{"return": {}} +{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microse= conds": "USECS", "seconds": "SECS"}} +{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"micros= econds": "USECS", "seconds": "SECS"}} +{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"mic= roseconds": "USECS", "seconds": "SECS"}} +completed +completed +{"return": {"running": false, "singlestep": false, "status": "postmigrate"= }} +{"return": {"running": true, "singlestep": false, "status": "running"}} +Add a second parent to drive0-file... +{"return": {}} +Restart A with -incoming and second parent... +{"return": {}} +Enabling migration QMP events on B... +{"return": {}} +Starting migration back to A... +{"return": {}} +{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microse= conds": "USECS", "seconds": "SECS"}} +{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"micros= econds": "USECS", "seconds": "SECS"}} +{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"mic= roseconds": "USECS", "seconds": "SECS"}} +completed +completed +{"return": {"running": true, "singlestep": false, "status": "running"}} +{"return": {"running": false, "singlestep": false, "status": "postmigrate"= }} diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index ddf1a5b549..8c56a0ad11 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -231,3 +231,4 @@ 231 auto quick 232 auto quick 233 auto quick +234 auto quick migration --=20 2.19.1 From nobody Mon Apr 29 08:56:22 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543327935696839.9243317396381; Tue, 27 Nov 2018 06:12:15 -0800 (PST) Received: from localhost ([::1]:42646 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRe61-00032Z-SJ for importer@patchew.org; Tue, 27 Nov 2018 09:12:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55660) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRe1I-0008Gk-Lq for qemu-devel@nongnu.org; Tue, 27 Nov 2018 09:07:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gRe1C-0007Xo-Sy for qemu-devel@nongnu.org; Tue, 27 Nov 2018 09:07:20 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36976) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gRe14-0006Qe-7T; Tue, 27 Nov 2018 09:07:08 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0A2903981; Tue, 27 Nov 2018 14:07:05 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-233.ams2.redhat.com [10.36.116.233]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8F389608C3; Tue, 27 Nov 2018 14:07:03 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 27 Nov 2018 15:06:40 +0100 Message-Id: <20181127140640.24830-4-kwolf@redhat.com> In-Reply-To: <20181127140640.24830-1-kwolf@redhat.com> References: <20181127140640.24830-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Tue, 27 Nov 2018 14:07:05 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 3/3] nvme: Fix spurious interrupts 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: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" From: Keith Busch The code had asserted an interrupt every time it was requested to check for new completion queue entries.This can result in spurious interrupts seen by the guest OS. Fix this by asserting an interrupt only if there are un-acknowledged completion queue entries available. Reported-by: Guenter Roeck Signed-off-by: Keith Busch Tested-by: Guenter Roeck Signed-off-by: Kevin Wolf --- hw/block/nvme.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 9fbe5673cb..7c8c63e8f5 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -272,7 +272,9 @@ static void nvme_post_cqes(void *opaque) sizeof(req->cqe)); QTAILQ_INSERT_TAIL(&sq->req_list, req, entry); } - nvme_irq_assert(n, cq); + if (cq->tail !=3D cq->head) { + nvme_irq_assert(n, cq); + } } =20 static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req) --=20 2.19.1