From patchwork Mon Aug 16 14:58:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 12438759 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 025ACC4338F for ; Mon, 16 Aug 2021 15:00:46 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A46B160C3F for ; Mon, 16 Aug 2021 15:00:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org A46B160C3F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:57096 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mFe6W-0001x1-RM for qemu-devel@archiver.kernel.org; Mon, 16 Aug 2021 11:00:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39852) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4d-0007Dy-LB for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:58:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:37215) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4b-0004FO-Ft for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:58:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629125924; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4lBP7OItPj97GmmCHX07BUF4/qvGLs2zCDqDf3BibLU=; b=TJ+QiKAdqYZiWUh0qwVoq0N9OQGNGgp1lEwP72bBJq47Lj/QQaup3E9IMGZdD91Ne80XRF gY0M7heRhqWY6yODNHmw1t53sU1gc4YuPdmS0OEXUTyy4IRir56LEiEthYi41wHY+wTO1P p3Hx4oxMuS9wwp4ffBlA6OwxBmBZcyM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-139-t-CPusJNMYCw2oN7hPz0Yw-1; Mon, 16 Aug 2021 10:58:43 -0400 X-MC-Unique: t-CPusJNMYCw2oN7hPz0Yw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4D06B871807; Mon, 16 Aug 2021 14:58:42 +0000 (UTC) Received: from thinkpad.redhat.com (unknown [10.39.194.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 18C5F6E6E1; Mon, 16 Aug 2021 14:58:39 +0000 (UTC) From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [RFC PATCH 1/6] qdev: add an Error parameter to the DeviceListener hide_device() function Date: Mon, 16 Aug 2021 16:58:19 +0200 Message-Id: <20210816145824.15825-2-lvivier@redhat.com> In-Reply-To: <20210816145824.15825-1-lvivier@redhat.com> References: <20210816145824.15825-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lvivier@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.698, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , "Michael S. Tsirkin" , Jason Wang , Juan Quintela , Alex Williamson , Paolo Bonzini , Jens Freimann Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This allows an error to be reported to the caller of qdev_device_add() Signed-off-by: Laurent Vivier --- include/hw/qdev-core.h | 6 ++++-- hw/core/qdev.c | 4 ++-- hw/net/virtio-net.c | 2 +- softmmu/qdev-monitor.c | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index bafc311bfa1b..e23b23a2f8d6 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -202,7 +202,8 @@ struct DeviceListener { * hide a failover device depending for example on the device * opts. */ - bool (*hide_device)(DeviceListener *listener, QemuOpts *device_opts); + bool (*hide_device)(DeviceListener *listener, QemuOpts *device_opts, + Error **errp); QTAILQ_ENTRY(DeviceListener) link; }; @@ -804,12 +805,13 @@ void device_listener_unregister(DeviceListener *listener); /** * @qdev_should_hide_device: * @opts: QemuOpts as passed on cmdline. + * @errp: pointer to error object * * Check if a device should be added. * When a device is added via qdev_device_add() this will be called, * and return if the device should be added now or not. */ -bool qdev_should_hide_device(QemuOpts *opts); +bool qdev_should_hide_device(QemuOpts *opts, Error **errp); typedef enum MachineInitPhase { /* current_machine is NULL. */ diff --git a/hw/core/qdev.c b/hw/core/qdev.c index cefc5eaa0a92..13f4c1e696bf 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -211,13 +211,13 @@ void device_listener_unregister(DeviceListener *listener) QTAILQ_REMOVE(&device_listeners, listener, link); } -bool qdev_should_hide_device(QemuOpts *opts) +bool qdev_should_hide_device(QemuOpts *opts, Error **errp) { DeviceListener *listener; QTAILQ_FOREACH(listener, &device_listeners, link) { if (listener->hide_device) { - if (listener->hide_device(listener, opts)) { + if (listener->hide_device(listener, opts, errp)) { return true; } } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 16d20cdee52a..542f9e167eb4 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3279,7 +3279,7 @@ static void virtio_net_migration_state_notifier(Notifier *notifier, void *data) } static bool failover_hide_primary_device(DeviceListener *listener, - QemuOpts *device_opts) + QemuOpts *device_opts, Error **errp) { VirtIONet *n = container_of(listener, VirtIONet, primary_listener); const char *standby_id; diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 721dec2d8200..7adf0d22beb1 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -627,8 +627,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) error_setg(errp, "Device with failover_pair_id don't have id"); return NULL; } - if (qdev_should_hide_device(opts)) { - if (bus && !qbus_is_hotpluggable(bus)) { + if (qdev_should_hide_device(opts, errp)) { + if (errp && !*errp && bus && !qbus_is_hotpluggable(bus)) { error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); } return NULL; From patchwork Mon Aug 16 14:58:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 12438763 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2256EC4338F for ; Mon, 16 Aug 2021 15:03:14 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C702B61038 for ; Mon, 16 Aug 2021 15:03:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C702B61038 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:35338 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mFe8v-0006RZ-04 for qemu-devel@archiver.kernel.org; Mon, 16 Aug 2021 11:03:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39866) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4j-0007IG-Ah for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:58:54 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:29492) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4g-0004Io-2U for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:58:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629125929; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fcYNrRcabklWXiefBQ5jnoeP/vl7VaBO52IHwHBjbRM=; b=fK6RMZZT1XZjToROFHyhCuS3p+5wfBn4qlmYQeTjIXic36Xw4cqPKZstUaza9cYBhQ0mal C1vqDdgmYytXC+6nXmt+l0B6nbCp3VBwRXJDQKRxSBkHJj2msBmXb8gVCydMq3+scgQdRy q4drMSu41z6QB6aIEH1jB0YC9ZXPDuE= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-553-MITD6lc0MyGJH0WJjxKBnw-1; Mon, 16 Aug 2021 10:58:46 -0400 X-MC-Unique: MITD6lc0MyGJH0WJjxKBnw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F0516871803; Mon, 16 Aug 2021 14:58:44 +0000 (UTC) Received: from thinkpad.redhat.com (unknown [10.39.194.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9F957620DE; Mon, 16 Aug 2021 14:58:42 +0000 (UTC) From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [RFC PATCH 2/6] qdev/qbus: remove failover specific code Date: Mon, 16 Aug 2021 16:58:20 +0200 Message-Id: <20210816145824.15825-3-lvivier@redhat.com> In-Reply-To: <20210816145824.15825-1-lvivier@redhat.com> References: <20210816145824.15825-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lvivier@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.698, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , "Michael S. Tsirkin" , Jason Wang , Juan Quintela , Alex Williamson , Paolo Bonzini , Jens Freimann Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Commit f3a850565693 ("qdev/qbus: add hidden device support") has introduced a generic way to hide a device but it has modified qdev_device_add() to check a specific option of the failover device, "failover_pair_id", before calling the generic mechanism. It's not needed (and not generic) to do that in qdev_device_add() because this is also checked by the failover_hide_primary_device() function that uses the generic mechanism to hide the device. Cc: Jens Freimann Signed-off-by: Laurent Vivier --- hw/net/virtio-net.c | 7 +++++++ softmmu/qdev-monitor.c | 14 ++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 542f9e167eb4..0c5ec930356b 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3288,6 +3288,13 @@ static bool failover_hide_primary_device(DeviceListener *listener, return false; } standby_id = qemu_opt_get(device_opts, "failover_pair_id"); + if (standby_id == NULL) { + return false; + } + if (device_opts->id == NULL) { + error_setg(errp, "Device with failover_pair_id don't have id"); + return true; + } if (g_strcmp0(standby_id, n->netclient_name) != 0) { return false; } diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 7adf0d22beb1..5c92dbed3139 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -622,17 +622,11 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) } } - if (qemu_opt_get(opts, "failover_pair_id")) { - if (!opts->id) { - error_setg(errp, "Device with failover_pair_id don't have id"); - return NULL; - } - if (qdev_should_hide_device(opts, errp)) { - if (errp && !*errp && bus && !qbus_is_hotpluggable(bus)) { - error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); - } - return NULL; + if (qdev_should_hide_device(opts, errp)) { + if (errp && !*errp && bus && !qbus_is_hotpluggable(bus)) { + error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); } + return NULL; } if (phase_check(PHASE_MACHINE_READY) && bus && !qbus_is_hotpluggable(bus)) { From patchwork Mon Aug 16 14:58:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 12438757 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF10EC4338F for ; Mon, 16 Aug 2021 15:00:36 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4065660EBD for ; Mon, 16 Aug 2021 15:00:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4065660EBD Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:56352 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mFe6N-0001SB-Cj for qemu-devel@archiver.kernel.org; Mon, 16 Aug 2021 11:00:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39946) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4t-0007OA-8I for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:03 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:54858) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4r-0004QR-JM for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629125941; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VDKpyxF0omOTPJyzF1Kn+LcSkX87I17Qwo22m0DJb/M=; b=JZAtJmbfRrL2S/EnmLz6O4qMCcSRAkq3Ykt3I0s60QQ8JIozJVDsdFJ7yrcoHFE9DJqxiW GdyMDdF0jtLZxuYrSLgalLJ2DO75l1DMtxmpVDS0ib2SOSkjUdyM0lGqDAnAe5P/OzgZ19 +VUeaUBxVbRfwAoccMBngzGi0SyOZP4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-238-8vAFv0-lOlK-Wq9diz6qUQ-1; Mon, 16 Aug 2021 10:58:59 -0400 X-MC-Unique: 8vAFv0-lOlK-Wq9diz6qUQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 15189801B3D; Mon, 16 Aug 2021 14:58:59 +0000 (UTC) Received: from thinkpad.redhat.com (unknown [10.39.194.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4C5966E0B6; Mon, 16 Aug 2021 14:58:45 +0000 (UTC) From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [RFC PATCH 3/6] failover: virtio-net: remove failover_primary_hidden flag Date: Mon, 16 Aug 2021 16:58:21 +0200 Message-Id: <20210816145824.15825-4-lvivier@redhat.com> In-Reply-To: <20210816145824.15825-1-lvivier@redhat.com> References: <20210816145824.15825-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lvivier@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=170.10.133.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.698, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , "Michael S. Tsirkin" , Jason Wang , Juan Quintela , Alex Williamson , Paolo Bonzini , Jens Freimann Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" We dont't need a flag to know if the primary device must be hidden, we can rely on the machine state: Device is hidden if the machine is in prelaunch state (src) or in inmigrate state with migration status set to none (dst). We don't need to check the flag in virtio_net_handle_migration_primary() because this function is only registered if the failover is enabled and the flag also set to false. This function also sets it back to true after a successful unplug during the migration but we don't need to know it is hidden because nothing will try to plug it back after the migration (except in case of error but the flag is set back to false). Signed-off-by: Laurent Vivier --- include/hw/virtio/virtio-net.h | 2 -- hw/net/virtio-net.c | 25 +++++++++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 824a69c23f06..21d8c3aa5f3a 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -205,8 +205,6 @@ struct VirtIONet { AnnounceTimer announce_timer; bool needs_vnet_hdr_swap; bool mtu_bypass_backend; - /* primary failover device is hidden*/ - bool failover_primary_hidden; bool failover; DeviceListener primary_listener; Notifier migration_state; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 0c5ec930356b..c81466f6efb7 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -36,8 +36,10 @@ #include "qapi/qapi-types-migration.h" #include "qapi/qapi-events-migration.h" #include "hw/virtio/virtio-access.h" +#include "migration/migration.h" #include "migration/misc.h" #include "standard-headers/linux/ethtool.h" +#include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "trace.h" #include "monitor/qdev.h" @@ -937,7 +939,6 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { qapi_event_send_failover_negotiated(n->netclient_name); - qatomic_set(&n->failover_primary_hidden, false); failover_add_primary(n, &err); if (err) { warn_report_err(err); @@ -3225,7 +3226,6 @@ static bool failover_replug_primary(VirtIONet *n, DeviceState *dev, return false; } qdev_set_parent_bus(dev, primary_bus, &error_abort); - qatomic_set(&n->failover_primary_hidden, false); hotplug_ctrl = qdev_get_hotplug_handler(dev); if (hotplug_ctrl) { hotplug_handler_pre_plug(hotplug_ctrl, dev, &err); @@ -3243,7 +3243,6 @@ out: static void virtio_net_handle_migration_primary(VirtIONet *n, MigrationState *s) { - bool should_be_hidden; Error *err = NULL; DeviceState *dev = failover_find_primary_device(n); @@ -3251,13 +3250,10 @@ static void virtio_net_handle_migration_primary(VirtIONet *n, MigrationState *s) return; } - should_be_hidden = qatomic_read(&n->failover_primary_hidden); - - if (migration_in_setup(s) && !should_be_hidden) { + if (migration_in_setup(s)) { if (failover_unplug_primary(n, dev)) { vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); qapi_event_send_unplug_primary(dev->id); - qatomic_set(&n->failover_primary_hidden, true); } else { warn_report("couldn't unplug primary device"); } @@ -3299,8 +3295,18 @@ static bool failover_hide_primary_device(DeviceListener *listener, return false; } - /* failover_primary_hidden is set during feature negotiation */ - return qatomic_read(&n->failover_primary_hidden); + if (runstate_check(RUN_STATE_PRELAUNCH)) { + /* hide the failover primary on src on startup */ + return true; + } + + if (runstate_check(RUN_STATE_INMIGRATE) && + migration_incoming_get_current()->state == MIGRATION_STATUS_NONE) { + /* hide the failover primary on dest on startup */ + return true; + } + + return false; } static void virtio_net_device_realize(DeviceState *dev, Error **errp) @@ -3338,7 +3344,6 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) if (n->failover) { n->primary_listener.hide_device = failover_hide_primary_device; - qatomic_set(&n->failover_primary_hidden, true); device_listener_register(&n->primary_listener); n->migration_state.notify = virtio_net_migration_state_notifier; add_migration_state_change_notifier(&n->migration_state); From patchwork Mon Aug 16 14:58:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 12438765 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC689C4338F for ; Mon, 16 Aug 2021 15:04:42 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5DC8360F39 for ; Mon, 16 Aug 2021 15:04:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5DC8360F39 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:39398 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mFeAL-0000hX-F2 for qemu-devel@archiver.kernel.org; Mon, 16 Aug 2021 11:04:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39960) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4x-0007Yy-6h for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:07 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:55012) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4u-0004SN-Ke for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629125944; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=V6SySTLoG1DNk5qAoPB1PExu68iFG/H55ERAE+KjVb0=; b=LrY8DjqCm9Qfgjww0DLums7xtlVsmYkMtkhQwHfUOEao6EqOO9yoTPqAmnMh1F7+F1NDkx M65P6Gh6FU9CyVw72X0PpEsKVMtW6gg9+X4m+hO97mm74A6I0hz99w6iS4UYuLxOyLnYj7 rHl+/mRhPIadWMpO9IPvW+wu7VvXUaA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-470-iMbaUN1OMzKTdh9I6TmzGw-1; Mon, 16 Aug 2021 10:59:02 -0400 X-MC-Unique: iMbaUN1OMzKTdh9I6TmzGw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 07E21100E422; Mon, 16 Aug 2021 14:59:02 +0000 (UTC) Received: from thinkpad.redhat.com (unknown [10.39.194.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 728596E0B6; Mon, 16 Aug 2021 14:58:59 +0000 (UTC) From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [RFC PATCH 4/6] failover: pci: move failover hotplug/unplug code into pci subsystem Date: Mon, 16 Aug 2021 16:58:22 +0200 Message-Id: <20210816145824.15825-5-lvivier@redhat.com> In-Reply-To: <20210816145824.15825-1-lvivier@redhat.com> References: <20210816145824.15825-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lvivier@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=170.10.133.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.698, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , "Michael S. Tsirkin" , Jason Wang , Juan Quintela , Alex Williamson , Paolo Bonzini , Jens Freimann Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" failover allows a VFIO device to be unplugged on migration to switch to the standby device, a virtio-net device. Failover relies on PCI ability to hotplug/unplug a card (the VFIO one) but all the code is implemented in virtio-net device that is not a PCI device (even not in virtio-net-pci that is the bridge between the PCI bus and the virtio-net device) This patch moves all the failover PCI related code to the PCI sub-system and keeps only in virtio-net the code related to the failover (that is implemented in the virtio-net driver in the kernel) There are several parts involved in the PCI device hotplug/unplug: - the migration state notifier originally virtio_net_handle_migration_primary(), moved to hw/pci/pci.c as pci_dev_handle_migration(). On source, this function unplugs the card on migration setup and plugs it back in case of failure. (helpers are pci_dev_migration_unplug() and pci_dev_migration_replug(), previously failover_unplug_primary() and failover_replug_primary()). - the hide device listener originally failover_hide_primary_device(), moved to hw/pci/pci.c as pci_dev_hide_device(). This function is called by qdev_device_add() to know if a device must be hidden or not. To do that, the function checks the command line, if the device doesn't have a "failover_pair_id" it is not hidden. Otherwise it is hidden at startup on source and destination and it is only plugged by a compatible virtio-net device). - the unplug pending checking functions originally primary_unplug_pending() and dev_unplug_pending(), moved to hw/pci/pci.c as bus_unplug_pending() and pci_device_unplug_pending() bus_unplug_pending() is called during the migration to check if the PCI device has been unplugged before starting to migrate data. It has been moved from vmstate_virtio_net to vmstate_pcibus. We can't move it to vmstate_pci_device because the device vmstate is removed before to start the migration (we don't migrate the device we unplug). pci_device_unplug_pending() is called by bus_unplug_pending() to check if an unplug is pending for a given device (this is a class function) of the bus. For a given PCI bus, bus_unplug_pending() will call pci_device_unplug_pending() for each available bus slot. Signed-off-by: Laurent Vivier --- include/hw/pci/pci.h | 4 + include/hw/virtio/virtio-net.h | 2 - include/hw/virtio/virtio.h | 1 - hw/net/virtio-net.c | 156 ------------------------------ hw/pci/pci.c | 170 ++++++++++++++++++++++++++++++++- 5 files changed, 173 insertions(+), 160 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index d0f4266e3725..d35214144d1b 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -241,6 +241,9 @@ struct PCIDeviceClass { /* rom bar */ const char *romfile; + + DeviceListener listener; + bool (*dev_unplug_pending)(void *opaque); }; typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev); @@ -359,6 +362,7 @@ struct PCIDevice { /* ID of standby device in net_failover pair */ char *failover_pair_id; + Notifier migration_state; uint32_t acpi_index; }; diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 21d8c3aa5f3a..d8161b61cc9e 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -206,8 +206,6 @@ struct VirtIONet { bool needs_vnet_hdr_swap; bool mtu_bypass_backend; bool failover; - DeviceListener primary_listener; - Notifier migration_state; VirtioNetRssData rss_data; struct NetRxPkt *rx_pkt; struct EBPFRSSContext ebpf_rss; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 8bab9cfb7507..c9d26d5daa43 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -159,7 +159,6 @@ struct VirtioDeviceClass { */ int (*post_load)(VirtIODevice *vdev); const VMStateDescription *vmsd; - bool (*primary_unplug_pending)(void *opaque); }; void virtio_instance_init_common(Object *proxy_obj, void *data, diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index c81466f6efb7..35e3d024f8d6 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -36,10 +36,8 @@ #include "qapi/qapi-types-migration.h" #include "qapi/qapi-events-migration.h" #include "hw/virtio/virtio-access.h" -#include "migration/migration.h" #include "migration/misc.h" #include "standard-headers/linux/ethtool.h" -#include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "trace.h" #include "monitor/qdev.h" @@ -3188,127 +3186,6 @@ void virtio_net_set_netclient_name(VirtIONet *n, const char *name, n->netclient_type = g_strdup(type); } -static bool failover_unplug_primary(VirtIONet *n, DeviceState *dev) -{ - HotplugHandler *hotplug_ctrl; - PCIDevice *pci_dev; - Error *err = NULL; - - hotplug_ctrl = qdev_get_hotplug_handler(dev); - if (hotplug_ctrl) { - pci_dev = PCI_DEVICE(dev); - pci_dev->partially_hotplugged = true; - hotplug_handler_unplug_request(hotplug_ctrl, dev, &err); - if (err) { - error_report_err(err); - return false; - } - } else { - return false; - } - return true; -} - -static bool failover_replug_primary(VirtIONet *n, DeviceState *dev, - Error **errp) -{ - Error *err = NULL; - HotplugHandler *hotplug_ctrl; - PCIDevice *pdev = PCI_DEVICE(dev); - BusState *primary_bus; - - if (!pdev->partially_hotplugged) { - return true; - } - primary_bus = dev->parent_bus; - if (!primary_bus) { - error_setg(errp, "virtio_net: couldn't find primary bus"); - return false; - } - qdev_set_parent_bus(dev, primary_bus, &error_abort); - hotplug_ctrl = qdev_get_hotplug_handler(dev); - if (hotplug_ctrl) { - hotplug_handler_pre_plug(hotplug_ctrl, dev, &err); - if (err) { - goto out; - } - hotplug_handler_plug(hotplug_ctrl, dev, &err); - } - pdev->partially_hotplugged = false; - -out: - error_propagate(errp, err); - return !err; -} - -static void virtio_net_handle_migration_primary(VirtIONet *n, MigrationState *s) -{ - Error *err = NULL; - DeviceState *dev = failover_find_primary_device(n); - - if (!dev) { - return; - } - - if (migration_in_setup(s)) { - if (failover_unplug_primary(n, dev)) { - vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); - qapi_event_send_unplug_primary(dev->id); - } else { - warn_report("couldn't unplug primary device"); - } - } else if (migration_has_failed(s)) { - /* We already unplugged the device let's plug it back */ - if (!failover_replug_primary(n, dev, &err)) { - if (err) { - error_report_err(err); - } - } - } -} - -static void virtio_net_migration_state_notifier(Notifier *notifier, void *data) -{ - MigrationState *s = data; - VirtIONet *n = container_of(notifier, VirtIONet, migration_state); - virtio_net_handle_migration_primary(n, s); -} - -static bool failover_hide_primary_device(DeviceListener *listener, - QemuOpts *device_opts, Error **errp) -{ - VirtIONet *n = container_of(listener, VirtIONet, primary_listener); - const char *standby_id; - - if (!device_opts) { - return false; - } - standby_id = qemu_opt_get(device_opts, "failover_pair_id"); - if (standby_id == NULL) { - return false; - } - if (device_opts->id == NULL) { - error_setg(errp, "Device with failover_pair_id don't have id"); - return true; - } - if (g_strcmp0(standby_id, n->netclient_name) != 0) { - return false; - } - - if (runstate_check(RUN_STATE_PRELAUNCH)) { - /* hide the failover primary on src on startup */ - return true; - } - - if (runstate_check(RUN_STATE_INMIGRATE) && - migration_incoming_get_current()->state == MIGRATION_STATUS_NONE) { - /* hide the failover primary on dest on startup */ - return true; - } - - return false; -} - static void virtio_net_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ -3343,10 +3220,6 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) } if (n->failover) { - n->primary_listener.hide_device = failover_hide_primary_device; - device_listener_register(&n->primary_listener); - n->migration_state.notify = virtio_net_migration_state_notifier; - add_migration_state_change_notifier(&n->migration_state); n->host_features |= (1ULL << VIRTIO_NET_F_STANDBY); } @@ -3492,11 +3365,6 @@ static void virtio_net_device_unrealize(DeviceState *dev) g_free(n->mac_table.macs); g_free(n->vlans); - if (n->failover) { - device_listener_unregister(&n->primary_listener); - remove_migration_state_change_notifier(&n->migration_state); - } - max_queues = n->multiqueue ? n->max_queues : 1; for (i = 0; i < max_queues; i++) { virtio_net_del_queue(n, i); @@ -3539,28 +3407,6 @@ static int virtio_net_pre_save(void *opaque) return 0; } -static bool primary_unplug_pending(void *opaque) -{ - DeviceState *dev = opaque; - DeviceState *primary; - VirtIODevice *vdev = VIRTIO_DEVICE(dev); - VirtIONet *n = VIRTIO_NET(vdev); - - if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_STANDBY)) { - return false; - } - primary = failover_find_primary_device(n); - return primary ? primary->pending_deleted_event : false; -} - -static bool dev_unplug_pending(void *opaque) -{ - DeviceState *dev = opaque; - VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev); - - return vdc->primary_unplug_pending(dev); -} - static const VMStateDescription vmstate_virtio_net = { .name = "virtio-net", .minimum_version_id = VIRTIO_NET_VM_VERSION, @@ -3570,7 +3416,6 @@ static const VMStateDescription vmstate_virtio_net = { VMSTATE_END_OF_LIST() }, .pre_save = virtio_net_pre_save, - .dev_unplug_pending = dev_unplug_pending, }; static Property virtio_net_properties[] = { @@ -3662,7 +3507,6 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO); vdc->post_load = virtio_net_post_load_virtio; vdc->vmsd = &vmstate_virtio_net_device; - vdc->primary_unplug_pending = primary_unplug_pending; } static const TypeInfo virtio_net_info = { diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 23d2ae2ab232..e88686b45976 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -33,11 +33,15 @@ #include "hw/pci/pci_host.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" +#include "migration/migration.h" +#include "migration/misc.h" #include "migration/qemu-file-types.h" #include "migration/vmstate.h" #include "monitor/monitor.h" +#include "monitor/qdev.h" #include "net/net.h" #include "sysemu/numa.h" +#include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "hw/loader.h" #include "qemu/error-report.h" @@ -47,8 +51,10 @@ #include "hw/pci/msix.h" #include "hw/hotplug.h" #include "hw/boards.h" +#include "hw/virtio/virtio-net.h" /* for failover */ #include "qapi/error.h" #include "qapi/qapi-commands-pci.h" +#include "qapi/qapi-events-migration.h" #include "qemu/cutils.h" //#define DEBUG_PCI @@ -82,6 +88,28 @@ static Property pci_props[] = { DEFINE_PROP_END_OF_LIST() }; +static bool bus_unplug_pending(void *opaque) +{ + DeviceState *dev = opaque; + PCIBus *bus = PCI_BUS(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { + PCIDeviceClass *pc; + + if (bus->devices[i] == NULL) { + continue; + } + + pc = PCI_DEVICE_GET_CLASS(bus->devices[i]); + if (pc->dev_unplug_pending && + pc->dev_unplug_pending(DEVICE(bus->devices[i]))) { + return true; + } + } + return false; +} + static const VMStateDescription vmstate_pcibus = { .name = "PCIBUS", .version_id = 1, @@ -92,7 +120,8 @@ static const VMStateDescription vmstate_pcibus = { nirq, 0, vmstate_info_int32, int32_t), VMSTATE_END_OF_LIST() - } + }, + .dev_unplug_pending = bus_unplug_pending, }; static void pci_init_bus_master(PCIDevice *pci_dev) @@ -1171,6 +1200,10 @@ static void pci_qdev_unrealize(DeviceState *dev) PCIDevice *pci_dev = PCI_DEVICE(dev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); + if (pci_dev->failover_pair_id) { + remove_migration_state_change_notifier(&pci_dev->migration_state); + } + pci_unregister_io_regions(pci_dev); pci_del_option_rom(pci_dev); @@ -2116,6 +2149,127 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) return bus->devices[devfn]; } +static bool pci_dev_migration_unplug(PCIDevice *pci_dev) +{ + HotplugHandler *hotplug_ctrl; + DeviceState *dev = &pci_dev->qdev; + Error *err = NULL; + + hotplug_ctrl = qdev_get_hotplug_handler(dev); + if (hotplug_ctrl) { + pci_dev->partially_hotplugged = true; + hotplug_handler_unplug_request(hotplug_ctrl, dev, &err); + if (err) { + error_report_err(err); + return false; + } + } else { + return false; + } + return true; +} + +static bool pci_dev_migration_replug(PCIDevice *pci_dev, Error **errp) +{ + Error *err = NULL; + HotplugHandler *hotplug_ctrl; + DeviceState *dev = &pci_dev->qdev; + BusState *primary_bus; + + if (!pci_dev->partially_hotplugged) { + return true; + } + primary_bus = dev->parent_bus; + if (!primary_bus) { + error_setg(errp, "virtio_net: couldn't find primary bus"); + return false; + } + qdev_set_parent_bus(dev, primary_bus, &error_abort); + hotplug_ctrl = qdev_get_hotplug_handler(dev); + if (hotplug_ctrl) { + hotplug_handler_pre_plug(hotplug_ctrl, dev, &err); + if (err) { + goto out; + } + hotplug_handler_plug(hotplug_ctrl, dev, &err); + } + pci_dev->partially_hotplugged = false; + +out: + error_propagate(errp, err); + return !err; +} + +static void pci_dev_handle_migration(PCIDevice *pci_dev, MigrationState *s) +{ + Error *err = NULL; + DeviceState *dev = &pci_dev->qdev; + + if (migration_in_setup(s)) { + if (pci_dev_migration_unplug(pci_dev)) { + vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); + qapi_event_send_unplug_primary(dev->id); + } else { + warn_report("couldn't unplug primary device"); + } + } else if (migration_has_failed(s)) { + /* We already unplugged the device let's plug it back */ + if (!pci_dev_migration_replug(pci_dev, &err)) { + if (err) { + error_report_err(err); + } + } + } +} + +static void pci_dev_migration_state_notifier(Notifier *notifier, void *data) +{ + MigrationState *s = data; + PCIDevice *pci_dev = container_of(notifier, PCIDevice, migration_state); + pci_dev_handle_migration(pci_dev, s); +} + +static bool pci_dev_hide_device(DeviceListener *listener, + QemuOpts *device_opts, Error **errp) +{ + const char *opt; + DeviceState *d; + + if (!device_opts) { + return false; + } + + opt = qemu_opt_get(device_opts, "failover_pair_id"); + if (opt) { + if (device_opts->id == NULL) { + error_setg(errp, "Device with failover_pair_id don't have id"); + return true; + } + d = qdev_find_recursive(sysbus_get_default(), opt); + if (d == NULL) { + /* + * if the the virtio-net device is not plugged it can be + * plugged later, and this device will be added to the failover + */ + return false; + } + + if (runstate_check(RUN_STATE_PRELAUNCH)) { + /* hide the failover primary on src on startup */ + return true; + } + + if (runstate_check(RUN_STATE_INMIGRATE) && + migration_incoming_get_current()->state == MIGRATION_STATUS_NONE) { + /* hide the failover primary on dest on startup */ + return true; + } + return false; + } + + return false; +} + static void pci_qdev_realize(DeviceState *qdev, Error **errp) { PCIDevice *pci_dev = (PCIDevice *)qdev; @@ -2175,6 +2329,8 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) return; } qdev->allow_unplug_during_migration = true; + pci_dev->migration_state.notify = pci_dev_migration_state_notifier; + add_migration_state_change_notifier(&pci_dev->migration_state); } /* rom loading */ @@ -2684,14 +2840,26 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev) return pci_get_bus(dev)->address_space_io; } +static bool pci_device_unplug_pending(void *opaque) +{ + DeviceState *dev = opaque; + + return dev->pending_deleted_event; +} + static void pci_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); k->realize = pci_qdev_realize; k->unrealize = pci_qdev_unrealize; k->bus_type = TYPE_PCI_BUS; device_class_set_props(k, pci_props); + pc->dev_unplug_pending = pci_device_unplug_pending; + + pc->listener.hide_device = pci_dev_hide_device; + device_listener_register(&pc->listener); } static void pci_device_class_base_init(ObjectClass *klass, void *data) From patchwork Mon Aug 16 14:58:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 12438767 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5EB7C4338F for ; Mon, 16 Aug 2021 15:04:51 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 65A896103A for ; Mon, 16 Aug 2021 15:04:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 65A896103A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:39866 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mFeAU-00010v-KE for qemu-devel@archiver.kernel.org; Mon, 16 Aug 2021 11:04:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39972) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe50-0007jL-SV for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:10 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:43879) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe4z-0004Us-8O for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629125948; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Qi23dmt01KJNQG8eZ4xEC+sizAYJWaYwVUK86jnSOns=; b=D4bzn7OnaYMYthdHD9ch4ZVar1onXXqqtKx/q7zx0NjsvoSuTo5ObuWYvgXEcT9xiznUGI B8zk8+ZByFILXGWTQS/X5C7mK0iK9p2VJaQJFmKSGZTNICZbhHn30LWKf88QJXDB5iLVI7 buG1zgxErZ5Nog8DnFsJpetXiIgKuFg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-49-eR3jHfUlPDi-2vi844w7ew-1; Mon, 16 Aug 2021 10:59:05 -0400 X-MC-Unique: eR3jHfUlPDi-2vi844w7ew-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 91F66100E420; Mon, 16 Aug 2021 14:59:04 +0000 (UTC) Received: from thinkpad.redhat.com (unknown [10.39.194.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5E2946E0B6; Mon, 16 Aug 2021 14:59:02 +0000 (UTC) From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [RFC PATCH 5/6] failover: pci: unregister ROM on unplug Date: Mon, 16 Aug 2021 16:58:23 +0200 Message-Id: <20210816145824.15825-6-lvivier@redhat.com> In-Reply-To: <20210816145824.15825-1-lvivier@redhat.com> References: <20210816145824.15825-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lvivier@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.698, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , "Michael S. Tsirkin" , Jason Wang , Juan Quintela , Alex Williamson , Paolo Bonzini , Jens Freimann Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" The intend of failover is to allow a VM with a VFIO networking card to be migrated without disrupting the network operation by switching to a virtio-net device during the migration. This simple change allows a simulated device like e1000e to be tested rather than a vfio device, even if it's useless in real life it can help to debug failover. This is interesting to developers that want to test failover on a system with no vfio device. Moreover it simplifies host networking configuration as we can use the same bridge for virtio-net and the other failover networking device. Without this change the migration of a system configured with failover fails with: ... -device virtio-net-pci,id=virtionet0,failover=on,... \ -device e1000,failover_pair_id=virtionet0,... \ ... (qemu) migrate ... Unknown ramblock "0000:00:01.1:00.0/e1000e.rom", cannot accept migration error while loading state for instance 0x0 of device 'ram' load of migration failed: Invalid argument This happens because QEMU correctly unregisters the interface vmstate but not the ROM one. This patch fixes that. Signed-off-by: Laurent Vivier --- hw/pci/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index e88686b45976..7cb140940a84 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2208,6 +2208,7 @@ static void pci_dev_handle_migration(PCIDevice *pci_dev, MigrationState *s) if (migration_in_setup(s)) { if (pci_dev_migration_unplug(pci_dev)) { vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); + pci_del_option_rom(pci_dev); qapi_event_send_unplug_primary(dev->id); } else { warn_report("couldn't unplug primary device"); From patchwork Mon Aug 16 14:58:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 12438769 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A5C6C4338F for ; Mon, 16 Aug 2021 15:06:39 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1B4A960E97 for ; Mon, 16 Aug 2021 15:06:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1B4A960E97 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:44118 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mFeCE-0003qY-AY for qemu-devel@archiver.kernel.org; Mon, 16 Aug 2021 11:06:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40034) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe59-0008Ag-Ea for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:19 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:45961) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFe57-0004aA-Ky for qemu-devel@nongnu.org; Mon, 16 Aug 2021 10:59:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629125957; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NZHVkQFhMeVwNMuwblNyslAVMeW9xi1A392tyaO0Q68=; b=FN2ElOSI/5RXUCnxJx91C0IZO4RMjSPE8CWDIzVsVjBM+WGlxz2AH1lumIIinq6I8vUs4E mkkW9qoBTLXSUTHNiwyzdKD5mEZ9+yv3TQ2CcvYIShd6xJpKlCyXrm3haCdf4u38+X0PGK LS5MGHS3VAlnv2ORAk/Io+F4a4uZz0o= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-565-uE6jZGrIO128lqVK6gQGkg-1; Mon, 16 Aug 2021 10:59:15 -0400 X-MC-Unique: uE6jZGrIO128lqVK6gQGkg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 80A17CC622; Mon, 16 Aug 2021 14:59:14 +0000 (UTC) Received: from thinkpad.redhat.com (unknown [10.39.194.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id F138F421F; Mon, 16 Aug 2021 14:59:04 +0000 (UTC) From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [RFC PATCH 6/6] pci: automatically unplug a PCI card before migration Date: Mon, 16 Aug 2021 16:58:24 +0200 Message-Id: <20210816145824.15825-7-lvivier@redhat.com> In-Reply-To: <20210816145824.15825-1-lvivier@redhat.com> References: <20210816145824.15825-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lvivier@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.698, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , "Michael S. Tsirkin" , Jason Wang , Juan Quintela , Alex Williamson , Paolo Bonzini , Jens Freimann Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" We have moved all the functions needed by failover to unplug a card to the PCI subsystem. A side effect of this change is we can implement automatic hotplug/unplug of any PCI card during migration without using a failover virtio-net card. For that, we need to introduce a new PCI device property, "unplug-on-migration", we can set to "true" or "on" if we want QEMU unplugs the card before the migration and plugs it back on the destination side after the migration. We modify the pci_dev_hide_device() function to check for the "unplug-on-migration" property on the command line. If it is present, the device is hidden on startup only on the destination side and it will be unplugged before the migration. To implement the "unplug-on-migration" property, we add a post_load function in vmstate_pcibus to hotplug the card after the migration (bus_post_load() and pci_dev_replug_on_migration()). This is not needed with virtio-net failover because the device is plugged back by the virtio-net device during the features migration (VIRTIO_NET_F_STANDBY) Signed-off-by: Laurent Vivier --- include/hw/pci/pci.h | 1 + hw/pci/pci.c | 76 ++++++++++++++++++++++++++++++++++++++------ hw/vfio/pci.c | 2 +- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index d35214144d1b..e02d965c064f 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -362,6 +362,7 @@ struct PCIDevice { /* ID of standby device in net_failover pair */ char *failover_pair_id; + bool unplug_on_migration; Notifier migration_state; uint32_t acpi_index; }; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 7cb140940a84..dc8f80241fa4 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -82,6 +82,8 @@ static Property pci_props[] = { QEMU_PCIE_LNKSTA_DLLLA_BITNR, true), DEFINE_PROP_BIT("x-pcie-extcap-init", PCIDevice, cap_present, QEMU_PCIE_EXTCAP_INIT_BITNR, true), + DEFINE_PROP_BOOL("unplug-on-migration", PCIDevice, + unplug_on_migration, false), DEFINE_PROP_STRING("failover_pair_id", PCIDevice, failover_pair_id), DEFINE_PROP_UINT32("acpi-index", PCIDevice, acpi_index, 0), @@ -110,6 +112,45 @@ static bool bus_unplug_pending(void *opaque) return false; } +static int pci_dev_replug_on_migration(void *opaque, QemuOpts *opts, + Error **errp) +{ + Error *err = NULL; + const char *bus_name = opaque; + const char *opt; + DeviceState *dev; + + if (g_strcmp0(qemu_opt_get(opts, "bus"), bus_name)) { + return 0; + } + + opt = qemu_opt_get(opts, "unplug-on-migration"); + if (g_strcmp0(opt, "on") && g_strcmp0(opt, "true")) { + return 0; + } + dev = qdev_device_add(opts, &err); + if (err) { + error_propagate(errp, err); + return 1; + } + object_unref(OBJECT(dev)); + return 0; +} + +static int bus_post_load(void *opaque, int version_id) +{ + Error *err = NULL; + PCIBus *bus = opaque; + + if (qemu_opts_foreach(qemu_find_opts("device"), + pci_dev_replug_on_migration, bus->qbus.name, &err)) { + error_report_err(err); + return -EINVAL; + } + + return 0; +} + static const VMStateDescription vmstate_pcibus = { .name = "PCIBUS", .version_id = 1, @@ -122,6 +163,7 @@ static const VMStateDescription vmstate_pcibus = { VMSTATE_END_OF_LIST() }, .dev_unplug_pending = bus_unplug_pending, + .post_load = bus_post_load, }; static void pci_init_bus_master(PCIDevice *pci_dev) @@ -1200,7 +1242,7 @@ static void pci_qdev_unrealize(DeviceState *dev) PCIDevice *pci_dev = PCI_DEVICE(dev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); - if (pci_dev->failover_pair_id) { + if (pci_dev->unplug_on_migration) { remove_migration_state_change_notifier(&pci_dev->migration_state); } @@ -2268,6 +2310,15 @@ static bool pci_dev_hide_device(DeviceListener *listener, return false; } + opt = qemu_opt_get(device_opts, "unplug-on-migration"); + if (g_strcmp0(opt, "on") == 0 || g_strcmp0(opt, "true") == 0) { + if (runstate_check(RUN_STATE_INMIGRATE)) { + return migration_incoming_get_current()->state != + MIGRATION_STATUS_ACTIVE; + } + return false; + } + return false; } @@ -2293,6 +2344,10 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS; } + if (pci_dev->failover_pair_id) { + pci_dev->unplug_on_migration = true; + } + pci_dev = do_pci_register_device(pci_dev, object_get_typename(OBJECT(qdev)), pci_dev->devfn, errp); @@ -2309,12 +2364,6 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) } if (pci_dev->failover_pair_id) { - if (!pci_bus_is_express(pci_get_bus(pci_dev))) { - error_setg(errp, "failover primary device must be on " - "PCIExpress bus"); - pci_qdev_unrealize(DEVICE(pci_dev)); - return; - } class_id = pci_get_word(pci_dev->config + PCI_CLASS_DEVICE); if (class_id != PCI_CLASS_NETWORK_ETHERNET) { error_setg(errp, "failover primary device is not an " @@ -2322,10 +2371,19 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) pci_qdev_unrealize(DEVICE(pci_dev)); return; } + } + + if (pci_dev->unplug_on_migration) { + if (!pci_bus_is_express(pci_get_bus(pci_dev))) { + error_setg(errp, "Unplugged device on migration must be on " + "PCIExpress bus"); + pci_qdev_unrealize(DEVICE(pci_dev)); + return; + } if ((pci_dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) || (PCI_FUNC(pci_dev->devfn) != 0)) { - error_setg(errp, "failover: primary device must be in its own " - "PCI slot"); + error_setg(errp, "Unplugged device on migration must be in its " + "own PCI slot"); pci_qdev_unrealize(DEVICE(pci_dev)); return; } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index e1ea1d8a23b5..187e1b58a4d9 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -3080,7 +3080,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) } } - if (!pdev->failover_pair_id) { + if (!pdev->unplug_on_migration) { ret = vfio_migration_probe(&vdev->vbasedev, errp); if (ret) { error_report("%s: Migration disabled", vdev->vbasedev.name);