From patchwork Fri Mar 22 13:44:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Freimann X-Patchwork-Id: 10865765 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DC9DB17EF for ; Fri, 22 Mar 2019 13:49:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BBD002A6F8 for ; Fri, 22 Mar 2019 13:49:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AAD1C2A707; Fri, 22 Mar 2019 13:49:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1CD2E2A6F8 for ; Fri, 22 Mar 2019 13:49:39 +0000 (UTC) Received: from localhost ([127.0.0.1]:57686 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h7KYE-0008Bt-F5 for patchwork-qemu-devel@patchwork.kernel.org; Fri, 22 Mar 2019 09:49:38 -0400 Received: from eggs.gnu.org ([209.51.188.92]:32986) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h7KTl-0004TW-Kg for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h7KTj-0003OG-Rk for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50884) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1h7KTj-0003LB-DG for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:44:59 -0400 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 8B5167D7BB; Fri, 22 Mar 2019 13:44:58 +0000 (UTC) Received: from localhost (ovpn-117-44.ams2.redhat.com [10.36.117.44]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CDA1A608A5; Fri, 22 Mar 2019 13:44:53 +0000 (UTC) From: Jens Freimann To: qemu-devel@nongnu.org Date: Fri, 22 Mar 2019 14:44:46 +0100 Message-Id: <20190322134447.14831-2-jfreimann@redhat.com> In-Reply-To: <20190322134447.14831-1-jfreimann@redhat.com> References: <20190322134447.14831-1-jfreimann@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.27]); Fri, 22 Mar 2019 13:44:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH 1/2] qdev/qbus: Add hidden device support 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: pkrempa@redhat.com, ehabkost@redhat.com, mst@redhat.com, mdroth@linux.vnet.ibm.com, liran.alon@oracle.com, laine@redhat.com, ogerlitz@mellanox.com, ailan@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sameeh Jubran Signed-off-by: Jens Freimann --- hw/core/qdev.c | 27 ++++++++++++++++++++++++ hw/pci/pci.c | 1 + include/hw/pci/pci.h | 2 ++ include/hw/qdev-core.h | 8 +++++++ qdev-monitor.c | 48 ++++++++++++++++++++++++++++++++++++++---- vl.c | 7 ++++-- 6 files changed, 87 insertions(+), 6 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index f9b6efe509..5e1c8f0120 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -211,6 +211,33 @@ void device_listener_unregister(DeviceListener *listener) QTAILQ_REMOVE(&device_listeners, listener, link); } +bool qdev_should_hide_device(QemuOpts *opts, Error **errp) +{ + bool res = false; + bool match_found = false; + + DeviceListener *listener; + + QTAILQ_FOREACH(listener, &device_listeners, link) { + if (listener->should_be_hidden) { + listener->should_be_hidden(listener, opts, &match_found, &res); + } + + if (match_found) + { + break; + } + } + /* No suitable pair device was found */ + if (!match_found) + { + error_setg(errp, "An error occurred: Couln't attach to standby device" + " Please note that the primary device should be" + " must be placed after the standby device in the command line"); + } + return res; +} + void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version) { diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 35451c1e99..67b1b7c500 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -70,6 +70,7 @@ 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_STRING("standby", PCIDevice, standby_id_str), DEFINE_PROP_END_OF_LIST() }; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index d87f5f93e9..f75dace1ec 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -351,6 +351,8 @@ struct PCIDevice { MSIVectorUseNotifier msix_vector_use_notifier; MSIVectorReleaseNotifier msix_vector_release_notifier; MSIVectorPollNotifier msix_vector_poll_notifier; + + char *standby_id_str; }; void pci_register_bar(PCIDevice *pci_dev, int region_num, diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 33ed3b8dde..e3b11f5503 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -144,6 +144,7 @@ struct DeviceState { char *canonical_path; bool realized; bool pending_deleted_event; + bool hidden; QemuOpts *opts; int hotplugged; BusState *parent_bus; @@ -157,6 +158,11 @@ struct DeviceState { struct DeviceListener { void (*realize)(DeviceListener *listener, DeviceState *dev); void (*unrealize)(DeviceListener *listener, DeviceState *dev); + /* This callback is called just upon init of the DeviceState + * and can be used by a standby device for informing qdev if this + * device should be hidden by checking the device opts + */ + void (*should_be_hidden)(DeviceListener *listener, QemuOpts *device_opts,bool *match_found, bool *res); QTAILQ_ENTRY(DeviceListener) link; }; @@ -453,4 +459,6 @@ static inline bool qbus_is_hotpluggable(BusState *bus) void device_listener_register(DeviceListener *listener); void device_listener_unregister(DeviceListener *listener); +bool qdev_should_hide_device(QemuOpts *opts, Error **errp); + #endif diff --git a/qdev-monitor.c b/qdev-monitor.c index d4320986a2..f4cfc8d4a1 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -33,6 +33,7 @@ #include "qemu/option.h" #include "sysemu/block-backend.h" #include "migration/misc.h" +#include "migration/migration.h" /* * Aliases were a bad idea from the start. Let's keep them @@ -569,13 +570,49 @@ void qdev_set_id(DeviceState *dev, const char *id) } } +static int has_standby_device(void *opaque, const char *name, const char *value, + Error **errp) +{ + if (strcmp(name, "standby") == 0) + { + QemuOpts *opts = (QemuOpts *)opaque; + if (qdev_should_hide_device(opts, errp) && errp && !*errp) + { + return 1; + } + else if (errp && *errp) + { + return -1; + } + } + return 0; +} + +static bool should_hide_device(QemuOpts *opts, Error **err) +{ + if (qemu_opt_foreach(opts, has_standby_device, opts, err) == 0) + { + return false; + } + return true; +} + DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) { DeviceClass *dc; const char *driver, *path; - DeviceState *dev; + DeviceState *dev = NULL; BusState *bus = NULL; Error *err = NULL; + + if (opts && should_hide_device(opts, &err)) + { + if(err) + { + goto err_del_dev; + } + return NULL; + } driver = qemu_opt_get(opts, "driver"); if (!driver) { @@ -648,8 +685,11 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) err_del_dev: error_propagate(errp, err); - object_unparent(OBJECT(dev)); - object_unref(OBJECT(dev)); + if (dev) + { + object_unparent(OBJECT(dev)); + object_unref(OBJECT(dev)); + } return NULL; } @@ -875,7 +915,7 @@ void qdev_unplug(DeviceState *dev, Error **errp) return; } - if (!migration_is_idle()) { + if (!migration_is_idle() && !migration_in_setup(migrate_get_current())) { error_setg(errp, "device_del not allowed while migrating"); return; } diff --git a/vl.c b/vl.c index d61d5604e5..51e773a8a9 100644 --- a/vl.c +++ b/vl.c @@ -2337,10 +2337,13 @@ static int device_init_func(void *opaque, QemuOpts *opts, Error **errp) DeviceState *dev; dev = qdev_device_add(opts, errp); - if (!dev) { + if (!dev && *errp) { + error_report_err(*errp); return -1; + } else if (dev) + { + object_unref(OBJECT(dev)); } - object_unref(OBJECT(dev)); return 0; } From patchwork Fri Mar 22 13:44:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Freimann X-Patchwork-Id: 10865767 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C3BB21390 for ; Fri, 22 Mar 2019 13:51:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A6BE02A7CA for ; Fri, 22 Mar 2019 13:51:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9A9C02A7CF; Fri, 22 Mar 2019 13:51:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0C0FF2A7C9 for ; Fri, 22 Mar 2019 13:51:02 +0000 (UTC) Received: from localhost ([127.0.0.1]:57729 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h7KZa-0001cE-1p for patchwork-qemu-devel@patchwork.kernel.org; Fri, 22 Mar 2019 09:51:02 -0400 Received: from eggs.gnu.org ([209.51.188.92]:33019) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h7KTn-0004Vm-MV for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h7KTm-0003Vg-6J for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54426) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1h7KTl-0003Rz-Mh for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:02 -0400 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 mx1.redhat.com (Postfix) with ESMTPS id CAC5018DF6C; Fri, 22 Mar 2019 13:45:00 +0000 (UTC) Received: from localhost (ovpn-117-44.ams2.redhat.com [10.36.117.44]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 534B0600C4; Fri, 22 Mar 2019 13:45:00 +0000 (UTC) From: Jens Freimann To: qemu-devel@nongnu.org Date: Fri, 22 Mar 2019 14:44:47 +0100 Message-Id: <20190322134447.14831-3-jfreimann@redhat.com> In-Reply-To: <20190322134447.14831-1-jfreimann@redhat.com> References: <20190322134447.14831-1-jfreimann@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 22 Mar 2019 13:45:00 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH 2/2] net/virtio: add failover support 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: pkrempa@redhat.com, ehabkost@redhat.com, mst@redhat.com, mdroth@linux.vnet.ibm.com, liran.alon@oracle.com, laine@redhat.com, ogerlitz@mellanox.com, ailan@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sameeh Jubran --- hw/net/virtio-net.c | 95 ++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-net.h | 7 +++ 2 files changed, 102 insertions(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 7e2c2a6f6a..880420a673 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -12,6 +12,7 @@ */ #include "qemu/osdep.h" +#include "qemu/atomic.h" #include "qemu/iov.h" #include "hw/virtio/virtio.h" #include "net/net.h" @@ -19,6 +20,7 @@ #include "net/tap.h" #include "qemu/error-report.h" #include "qemu/timer.h" +#include "qemu/option.h" #include "hw/virtio/virtio-net.h" #include "net/vhost_net.h" #include "net/announce.h" @@ -29,6 +31,8 @@ #include "migration/misc.h" #include "standard-headers/linux/ethtool.h" #include "trace.h" +#include "monitor/qdev.h" +#include "hw/pci/pci.h" #define VIRTIO_NET_VM_VERSION 11 @@ -364,6 +368,9 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) } } + +static void virtio_net_primary_plug_timer(void *opaque); + static void virtio_net_set_link_status(NetClientState *nc) { VirtIONet *n = qemu_get_nic_opaque(nc); @@ -786,6 +793,14 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) } else { memset(n->vlans, 0xff, MAX_VLAN >> 3); } + + if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { + atomic_set(&n->primary_should_be_hidden, false); + if (n->primary_device_timer) + timer_mod(n->primary_device_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + 4000); + } } static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, @@ -2626,6 +2641,74 @@ void virtio_net_set_netclient_name(VirtIONet *n, const char *name, n->netclient_type = g_strdup(type); } +static void virtio_net_primary_plug_timer(void *opaque) +{ + VirtIONet *n = opaque; + Error *err = NULL; + + n->primary_dev = qdev_device_add(n->primary_device_opts, &err); + if (!n->primary_dev && err) + { + if (n->primary_device_timer) + timer_mod(n->primary_device_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + 100); + } +} + +static void virtio_net_handle_migration_primary(VirtIONet *n, MigrationState * s) +{ + Error *err = NULL; + bool should_be_hidden = atomic_read(&n->primary_should_be_hidden); + + if (migration_in_setup(s) && !should_be_hidden && n->primary_dev) { + /* Request unplug + * + * + */ + qdev_unplug(n->primary_dev, &err); + if (!err) + { + atomic_set(&n->primary_should_be_hidden, true); + n->primary_dev = NULL; + } + } else if (migration_has_failed(s)) { + if (should_be_hidden && !n->primary_dev) + { + /* We already unplugged the device let's plugged it back */ + n->primary_dev = qdev_device_add(n->primary_device_opts, &err); + } + else + { + } + } +} + +static void 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 void virtio_net_primary_should_be_hidden(DeviceListener *listener, QemuOpts *device_opts, + bool *match_found, bool *res) +{ + VirtIONet *n = container_of(listener, VirtIONet, primary_listener); + const char * dev_id = qemu_opts_id(device_opts); + + *match_found = !strcmp(n->net_conf.primary_id_str ,dev_id); + if (atomic_read(&n->primary_should_be_hidden) && !strcmp(qemu_opt_get(device_opts, "driver"), "vfio-pci") + && *match_found) + { + n->primary_device_opts = device_opts; + *res = true; + return; + } + + *res = false; +} + static void virtio_net_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ -2656,6 +2739,17 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX); } + if (n->net_conf.primary_id_str) { + n->primary_listener.should_be_hidden = virtio_net_primary_should_be_hidden; + atomic_set(&n->primary_should_be_hidden, true); + device_listener_register(&n->primary_listener); + n->migration_state.notify = migration_state_notifier; + add_migration_state_change_notifier(&n->migration_state); + n->host_features |= (1ULL << VIRTIO_NET_F_STANDBY); + n->primary_device_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, + virtio_net_primary_plug_timer, n); + } + virtio_net_set_config_size(n, n->host_features); virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size); @@ -2885,6 +2979,7 @@ static Property virtio_net_properties[] = { true), DEFINE_PROP_INT32("speed", VirtIONet, net_conf.speed, SPEED_UNKNOWN), DEFINE_PROP_STRING("duplex", VirtIONet, net_conf.duplex_str), + DEFINE_PROP_STRING("primary", VirtIONet, net_conf.primary_id_str), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index b96f0c643f..ec5f387aa9 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -43,6 +43,7 @@ typedef struct virtio_net_conf int32_t speed; char *duplex_str; uint8_t duplex; + char *primary_id_str; } virtio_net_conf; /* Coalesced packets type & status */ @@ -185,6 +186,12 @@ struct VirtIONet { AnnounceTimer announce_timer; bool needs_vnet_hdr_swap; bool mtu_bypass_backend; + QemuOpts *primary_device_opts; + DeviceState *primary_dev; + bool primary_should_be_hidden; + DeviceListener primary_listener; + QEMUTimer *primary_device_timer; + Notifier migration_state; }; void virtio_net_set_netclient_name(VirtIONet *n, const char *name,