All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/11] add failover feature for assigned network devices
@ 2019-10-18 20:20 Jens Freimann
  2019-10-18 20:20 ` [PATCH 01/11] qdev/qbus: add hidden device support Jens Freimann
                   ` (13 more replies)
  0 siblings, 14 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

This is implementing the host side of the net_failover concept
(https://www.kernel.org/doc/html/latest/networking/net_failover.html)

Changes since v3:
* Patch 1,  make return values of qdev_should_hide_device() more clear
* Patch 1,  clarify comment about new should_be_hidden DeviceListener
* Patch 2   new patch, add net_failover_option_id to PCIDevice, only
            allow PCIExpress devices for now 
* Patch 8,  only go into wait_unplug state when failover devices are present
* Patch 8,  add new state to migration_is_setup_or_active, tested cancelling
            while migration is in this state
* Patch 8,  simplify handling of wait_unplug state, don't cancel migration after
            timeout, let upper layer do this, get rid of retry counter (dgilbert)
* Patch 11, move net_failover_pair_id to PCIDev, move check for pci class
            to PCI code, only allow PCIe devices for now as we only support
            hotplugging these devices (aw)
* verified qemu make check tests ran, checked that docker-test-quick@centos7 runs
  successful, tested migration with/without failover, without vfio-pci 
* this now allows only PCIe devices because that's the only hotplug
  controller that supports the partial unplug as of now. I'll work on 
  making it discoverable for libvirt or on support for the
  other hotplug controllers in a follow-on patch set
 
The general idea is that we have a pair of devices, a vfio-pci and a
virtio-net device. Before migration the vfio device is unplugged and data
flows to the virtio-net device, on the target side another vfio-pci device
is plugged in to take over the data-path. In the guest the net_failover
module will pair net devices with the same MAC address.

* Patch 1 adds the infrastructure to hide the device for the qbus and qdev APIs

* Patch 2 adds checks to PCIDevice for only allowing ethernet devices as
  failover primary and only PCIExpress capable devices

* Patch 3 sets a new flag for PCIDevice 'partially_hotplugged' which we
  use to skip the unrealize code path when doing a unplug of the primary
  device

* Patch 4 sets the pending_deleted_event before triggering the guest
  unplug request

* Patch 5 and 6 add new qmp events, one sends the device id of a device
  that was just requested to be unplugged from the guest and another one
  to let libvirt know if VIRTIO_NET_F_STANDBY was negotiated

* Patch 7 make sure that we can unplug the vfio-device before
  migration starts

* Patch 8 adds a new migration state that is entered while we wait for
  devices to be unplugged by guest OS

* Patch 9 just adds the new migration state to a check in libqos code

* Patch 10 In the second patch the virtio-net uses the API to defer adding the vfio
  device until the VIRTIO_NET_F_STANDBY feature is acked. It also
  implements the migration handler to unplug the device from the guest and
  re-plug in case of migration failure

* Patch 11 allows migration for failover vfio-pci devices

Previous discussion:
  RFC v1 https://patchwork.ozlabs.org/cover/989098/
  RFC v2 https://www.mail-archive.com/qemu-devel@nongnu.org/msg606906.html
  v1: https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg03968.html
  v2: https://www.mail-archive.com/qemu-devel@nongnu.org/msg635214.html
  v3: https://patchew.org/QEMU/20191011112015.11785-1-jfreimann@redhat.com/

To summarize concerns/feedback from previous discussion:
1.- guest OS can reject or worse _delay_ unplug by any amount of time.
  Migration might get stuck for unpredictable time with unclear reason.
  This approach combines two tricky things, hot/unplug and migration.
  -> We need to let libvirt know what's happening. Add new qmp events
     and a new migration state. When a primary device is (partially)
     unplugged (only from guest) we send a qmp event with the device id. When
     it is unplugged from the guest the DEVICE_DELETED event is sent.
     Migration will enter the wait-unplug state while waiting for the guest
     os to unplug all primary devices and then move on with migration.
2. PCI devices are a precious ressource. The primary device should never
  be added to QEMU if it won't be used by guest instead of hiding it in
  QEMU.
  -> We only hotplug the device when the standby feature bit was
     negotiated. We save the device cmdline options until we need it for
     qdev_device_add()
     Hiding a device can be a useful concept to model. For example a
     pci device in a powered-off slot could be marked as hidden until the slot is
     powered on (mst).
3. Management layer software should handle this. Open Stack already has
  components/code to handle unplug/replug VFIO devices and metadata to
  provide to the guest for detecting which devices should be paired.
  -> An approach that includes all software from firmware to
     higher-level management software wasn't tried in the last years. This is
     an attempt to keep it simple and contained in QEMU as much as possible.
     One of the problems that stopped management software and libvirt from
     implementing this idea is that it can't be sure that it's possible to
     re-plug the primary device. By not freeing the devices resources in QEMU
     and only asking the guest OS to unplug it is possible to re-plug the
     device in case of a migration failure.
4. Hotplugging a device and then making it part of a failover setup is
   not possible
  -> addressed by extending qdev hotplug functions to check for hidden
     attribute, so e.g. device_add can be used to plug a device.


I have tested this with a mlx5 and igb NIC and was able to migrate the VM.

Command line example:

qemu-system-x86_64 -enable-kvm -m 3072 -smp 3 \
        -machine q35,kernel-irqchip=split -cpu host   \
        -serial stdio   \
        -net none \
        -qmp unix:/tmp/qmp.socket,server,nowait \
        -monitor telnet:127.0.0.1:5555,server,nowait \
        -device pcie-root-port,id=root0,multifunction=on,chassis=0,addr=0xa \
        -device pcie-root-port,id=root1,bus=pcie.0,chassis=1 \
        -device pcie-root-port,id=root2,bus=pcie.0,chassis=2 \
        -netdev tap,script=/root/bin/bridge.sh,downscript=no,id=hostnet1,vhost=on \
        -device virtio-net-pci,netdev=hostnet1,id=net1,mac=52:54:00:6f:55:cc,bus=root2,failover=on \
	-device vfio-pci,host=5e:00.2,id=hostdev0,bus=root1,net_failover_pair_id =net1 \
        /root/rhel-guest-image-8.0-1781.x86_64.qcow2

I'm grateful for any remarks or ideas!

Thanks!

regards,
Jens 


Jens Freimann (10):
  qdev/qbus: add hidden device support
  pci: mark devices partially unplugged
  pci: mark device having guest unplug request pending
  qapi: add unplug primary event
  qapi: add failover negotiated event
  migration: allow unplug during migration for failover devices
  migration: add new migration state wait-unplug
  libqos: tolerate wait-unplug migration state
  net/virtio: add failover support
  vfio: unplug failover primary device before migration

 hw/core/qdev.c                 |  20 +++
 hw/net/virtio-net.c            | 267 +++++++++++++++++++++++++++++++++
 hw/pci/pci.c                   |   2 +
 hw/pci/pcie.c                  |   6 +
 hw/vfio/pci.c                  |  35 ++++-
 hw/vfio/pci.h                  |   2 +
 include/hw/pci/pci.h           |   1 +
 include/hw/qdev-core.h         |  10 ++
 include/hw/virtio/virtio-net.h |  12 ++
 include/hw/virtio/virtio.h     |   1 +
 include/migration/vmstate.h    |   2 +
 migration/migration.c          |  34 +++++
 migration/migration.h          |   3 +
 migration/savevm.c             |  36 +++++
 migration/savevm.h             |   1 +
 qapi/migration.json            |  24 ++-
 qapi/net.json                  |  16 ++
 qdev-monitor.c                 |  43 +++++-
 tests/libqos/libqos.c          |   3 +-
 vl.c                           |   6 +-
 20 files changed, 515 insertions(+), 9 deletions(-)

-- 
2.21.0

*** BLURB HERE ***

Jens Freimann (11):
  qdev/qbus: add hidden device support
  pci: add option for net failover
  pci: mark devices partially unplugged
  pci: mark device having guest unplug request pending
  qapi: add unplug primary event
  qapi: add failover negotiated event
  migration: allow unplug during migration for failover devices
  migration: add new migration state wait-unplug
  libqos: tolerate wait-unplug migration state
  net/virtio: add failover support
  vfio: unplug failover primary device before migration

 hw/core/qdev.c                 |  24 +++
 hw/net/virtio-net.c            | 282 +++++++++++++++++++++++++++++++++
 hw/pci/pci.c                   |  17 ++
 hw/pci/pcie.c                  |   6 +
 hw/vfio/pci.c                  |  26 ++-
 hw/vfio/pci.h                  |   1 +
 include/hw/pci/pci.h           |   4 +
 include/hw/qdev-core.h         |   9 ++
 include/hw/virtio/virtio-net.h |  12 ++
 include/hw/virtio/virtio.h     |   1 +
 include/migration/vmstate.h    |   2 +
 migration/migration.c          |  22 +++
 migration/migration.h          |   3 +
 migration/savevm.c             |  36 +++++
 migration/savevm.h             |   1 +
 qapi/migration.json            |  24 ++-
 qapi/net.json                  |  16 ++
 qdev-monitor.c                 |  38 ++++-
 tests/libqos/libqos.c          |   3 +-
 vl.c                           |   6 +-
 20 files changed, 519 insertions(+), 14 deletions(-)

-- 
2.21.0


Jens Freimann (11):
  qdev/qbus: add hidden device support
  pci: add option for net failover
  pci: mark devices partially unplugged
  pci: mark device having guest unplug request pending
  qapi: add unplug primary event
  qapi: add failover negotiated event
  migration: allow unplug during migration for failover devices
  migration: add new migration state wait-unplug
  libqos: tolerate wait-unplug migration state
  net/virtio: add failover support
  vfio: unplug failover primary device before migration

 hw/core/qdev.c                 |  24 +++
 hw/net/virtio-net.c            | 282 +++++++++++++++++++++++++++++++++
 hw/pci/pci.c                   |  17 ++
 hw/pci/pcie.c                  |   6 +
 hw/vfio/pci.c                  |  26 ++-
 hw/vfio/pci.h                  |   1 +
 include/hw/pci/pci.h           |   4 +
 include/hw/qdev-core.h         |   9 ++
 include/hw/virtio/virtio-net.h |  12 ++
 include/hw/virtio/virtio.h     |   1 +
 include/migration/vmstate.h    |   2 +
 migration/migration.c          |  21 +++
 migration/migration.h          |   3 +
 migration/savevm.c             |  36 +++++
 migration/savevm.h             |   2 +
 qapi/migration.json            |  24 ++-
 qapi/net.json                  |  16 ++
 qdev-monitor.c                 |  38 ++++-
 tests/libqos/libqos.c          |   3 +-
 vl.c                           |   6 +-
 20 files changed, 519 insertions(+), 14 deletions(-)

-- 
2.21.0

Jens Freimann (11):
  qdev/qbus: add hidden device support
  pci: add option for net failover
  pci: mark devices partially unplugged
  pci: mark device having guest unplug request pending
  qapi: add unplug primary event
  qapi: add failover negotiated event
  migration: allow unplug during migration for failover devices
  migration: add new migration state wait-unplug
  libqos: tolerate wait-unplug migration state
  net/virtio: add failover support
  vfio: unplug failover primary device before migration

 hw/core/qdev.c                 |  24 +++
 hw/net/virtio-net.c            | 282 +++++++++++++++++++++++++++++++++
 hw/pci/pci.c                   |  17 ++
 hw/pci/pcie.c                  |   6 +
 hw/vfio/pci.c                  |  31 +++-
 hw/vfio/pci.h                  |   1 +
 include/hw/pci/pci.h           |   4 +
 include/hw/qdev-core.h         |   9 ++
 include/hw/virtio/virtio-net.h |  12 ++
 include/hw/virtio/virtio.h     |   1 +
 include/migration/vmstate.h    |   2 +
 migration/migration.c          |  21 +++
 migration/migration.h          |   3 +
 migration/savevm.c             |  36 +++++
 migration/savevm.h             |   2 +
 qapi/migration.json            |  24 ++-
 qapi/net.json                  |  16 ++
 qdev-monitor.c                 |  38 ++++-
 tests/libqos/libqos.c          |   3 +-
 vl.c                           |   6 +-
 20 files changed, 524 insertions(+), 14 deletions(-)

-- 
2.21.0



^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/11] qdev/qbus: add hidden device support
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-21 12:44   ` Cornelia Huck
  2019-10-21 12:53   ` Peter Maydell
  2019-10-18 20:20 ` [PATCH 02/11] pci: add option for net failover Jens Freimann
                   ` (12 subsequent siblings)
  13 siblings, 2 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

This adds support for hiding a device to the qbus and qdev APIs.  The
first user of this will be the virtio-net failover feature but the API
introduced with this patch could be used to implement other features as
well, for example hiding pci devices when a pci bus is powered off.

qdev_device_add() is modified to check for a net_failover_pair_id
argument in the option string. A DeviceListener callback
should_be_hidden() is added. It can be used by a standby device to
inform qdev that this device should not be added now. The standby device
handler can store the device options to plug the device in at a later
point in time.

One reason for hiding the device is that we don't want to expose both
devices to the guest kernel until the respective virtio feature bit
VIRTIO_NET_F_STANDBY was negotiated and we know that the devices will be
handled correctly by the guest.

More information on the kernel feature this is using:
 https://www.kernel.org/doc/html/latest/networking/net_failover.html

An example where the primary device is a vfio-pci device and the standby
device is a virtio-net device:

A device is hidden when it has an "net_failover_pair_id" option, e.g.

 -device virtio-net-pci,...,failover=on,...
 -device vfio-pci,...,net_failover_pair_id=net1,...

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 hw/core/qdev.c         | 23 +++++++++++++++++++++++
 include/hw/qdev-core.h |  8 ++++++++
 qdev-monitor.c         | 36 +++++++++++++++++++++++++++++++++---
 vl.c                   |  6 ++++--
 4 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index cbad6c1d55..89c134ec53 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -212,6 +212,29 @@ void device_listener_unregister(DeviceListener *listener)
     QTAILQ_REMOVE(&device_listeners, listener, link);
 }
 
+bool qdev_should_hide_device(QemuOpts *opts)
+{
+    int rc;
+    DeviceListener *listener;
+
+    QTAILQ_FOREACH(listener, &device_listeners, link) {
+       if (listener->should_be_hidden) {
+            /* should_be_hidden_will return
+             *  1 if device matches opts and it should be hidden
+             *  0 if device matches opts and should not be hidden
+             *  -1 if device doesn't match ops
+             */
+            rc = listener->should_be_hidden(listener, opts);
+        }
+
+        if (rc > 0) {
+            break;
+        }
+    }
+
+    return rc > 0;
+}
+
 void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
                                  int required_for_version)
 {
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index aa123f88cb..28f594a47d 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -154,6 +154,12 @@ struct DeviceState {
 struct DeviceListener {
     void (*realize)(DeviceListener *listener, DeviceState *dev);
     void (*unrealize)(DeviceListener *listener, DeviceState *dev);
+    /*
+     * This callback is called upon init of the DeviceState and allows to
+     * inform qdev that a device should be hidden, depending on the device
+     * opts, for example, to hide a standby device.
+     */
+    int (*should_be_hidden)(DeviceListener *listener, QemuOpts *device_opts);
     QTAILQ_ENTRY(DeviceListener) link;
 };
 
@@ -451,4 +457,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);
+
 #endif
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 148df9cacf..508d85df87 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -32,9 +32,11 @@
 #include "qemu/help_option.h"
 #include "qemu/option.h"
 #include "qemu/qemu-print.h"
+#include "qemu/option_int.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/sysemu.h"
 #include "migration/misc.h"
+#include "migration/migration.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -562,14 +564,40 @@ void qdev_set_id(DeviceState *dev, const char *id)
     }
 }
 
+static int is_failover_device(void *opaque, const char *name, const char *value,
+                        Error **errp)
+{
+    if (strcmp(name, "net_failover_pair_id") == 0) {
+        QemuOpts *opts = (QemuOpts *)opaque;
+
+        if (qdev_should_hide_device(opts)) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static bool should_hide_device(QemuOpts *opts)
+{
+    if (qemu_opt_foreach(opts, is_failover_device, opts, NULL) == 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)) {
+        return NULL;
+    }
+
     driver = qemu_opt_get(opts, "driver");
     if (!driver) {
         error_setg(errp, QERR_MISSING_PARAMETER, "driver");
@@ -648,8 +676,10 @@ 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;
 }
 
diff --git a/vl.c b/vl.c
index 4489cfb2bb..62c388cb49 100644
--- a/vl.c
+++ b/vl.c
@@ -2204,10 +2204,12 @@ 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;
 }
 
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/11] pci: add option for net failover
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
  2019-10-18 20:20 ` [PATCH 01/11] qdev/qbus: add hidden device support Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-21 14:58   ` Alex Williamson
  2019-10-18 20:20 ` [PATCH 03/11] pci: mark devices partially unplugged Jens Freimann
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

This patch adds a net_failover_pair_id property to PCIDev which is
used to link the primary device in a failover pair (the PCI dev) to
a standby (a virtio-net-pci) device.

It only supports ethernet devices. Also currently it only supports
PCIe devices. QEMU will exit with an error message otherwise.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 hw/pci/pci.c         | 17 +++++++++++++++++
 include/hw/pci/pci.h |  3 +++
 2 files changed, 20 insertions(+)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index aa05c2b9b2..fa9b5219f8 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -75,6 +75,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_STRING("net_failover_pair_id", PCIDevice,
+            net_failover_pair_id),
     DEFINE_PROP_END_OF_LIST()
 };
 
@@ -2077,6 +2079,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
     ObjectClass *klass = OBJECT_CLASS(pc);
     Error *local_err = NULL;
     bool is_default_rom;
+    uint16_t class_id;
 
     /* initialize cap_present for pci_is_express() and pci_config_size(),
      * Note that hybrid PCIs are not set automatically and need to manage
@@ -2101,6 +2104,20 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
         }
     }
 
+    if (pci_dev->net_failover_pair_id) {
+        if (!pci_is_express(pci_dev)) {
+            error_setg(errp, "failover device is not a PCIExpress device");
+            error_propagate(errp, local_err);
+            return;
+        }
+        class_id = pci_get_word(pci_dev->config + PCI_CLASS_DEVICE);
+        if (class_id != PCI_CLASS_NETWORK_ETHERNET) {
+            error_setg(errp, "failover device is not an Ethernet device");
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+
     /* rom loading */
     is_default_rom = false;
     if (pci_dev->romfile == NULL && pc->romfile != NULL) {
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index f3f0ffd5fb..def5435685 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -352,6 +352,9 @@ struct PCIDevice {
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
     MSIVectorPollNotifier msix_vector_poll_notifier;
+
+    /* ID of standby device in net_failover pair */
+    char *net_failover_pair_id;
 };
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/11] pci: mark devices partially unplugged
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
  2019-10-18 20:20 ` [PATCH 01/11] qdev/qbus: add hidden device support Jens Freimann
  2019-10-18 20:20 ` [PATCH 02/11] pci: add option for net failover Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:20 ` [PATCH 04/11] pci: mark device having guest unplug request pending Jens Freimann
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

Only the guest unplug request was triggered. This is needed for
the failover feature. In case of a failed migration we need to
plug the device back to the guest.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 hw/pci/pcie.c        | 3 +++
 include/hw/pci/pci.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index a6beb567bd..19363ff8ce 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -456,6 +456,9 @@ static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
 {
     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev));
 
+    if (dev->partially_hotplugged) {
+        return;
+    }
     hotplug_handler_unplug(hotplug_ctrl, DEVICE(dev), &error_abort);
     object_unparent(OBJECT(dev));
 }
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index def5435685..7b7eac845c 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -265,6 +265,7 @@ typedef struct PCIReqIDCache PCIReqIDCache;
 
 struct PCIDevice {
     DeviceState qdev;
+    bool partially_hotplugged;
 
     /* PCI config space */
     uint8_t *config;
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/11] pci: mark device having guest unplug request pending
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (2 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 03/11] pci: mark devices partially unplugged Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:20 ` [PATCH 05/11] qapi: add unplug primary event Jens Freimann
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

Set pending_deleted_event in DeviceState for failover
primary devices that were successfully unplugged by the Guest OS.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 hw/pci/pcie.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 19363ff8ce..08718188bb 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -457,6 +457,7 @@ static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev));
 
     if (dev->partially_hotplugged) {
+        dev->qdev.pending_deleted_event = false;
         return;
     }
     hotplug_handler_unplug(hotplug_ctrl, DEVICE(dev), &error_abort);
@@ -476,6 +477,8 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
         return;
     }
 
+    dev->pending_deleted_event = true;
+
     /* In case user cancel the operation of multi-function hot-add,
      * remove the function that is unexposed to guest individually,
      * without interaction with guest.
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/11] qapi: add unplug primary event
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (3 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 04/11] pci: mark device having guest unplug request pending Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:28   ` Eric Blake
  2019-10-18 20:20 ` [PATCH 06/11] qapi: add failover negotiated event Jens Freimann
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

This event is emitted when we sent a request to unplug a
failover primary device from the Guest OS and it includes the
device id of the primary device.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 qapi/migration.json | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/qapi/migration.json b/qapi/migration.json
index 82feb5bd39..52e69e2868 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1448,3 +1448,22 @@
 # Since: 3.0
 ##
 { 'command': 'migrate-pause', 'allow-oob': true }
+
+##
+# @UNPLUG_PRIMARY:
+#
+# Emitted from source side of a migration when migration state is
+# WAIT_UNPLUG. Device was unplugged by guest operating system.
+# Device resources in QEMU are kept on standby to be able to re-plug it in case
+# of migration failure.
+#
+# @device_id: QEMU device id of the unplugged device
+#
+# Since: 4.2
+#
+# Example:
+#   {"event": "UNPLUG_PRIMARY", "data": {"device_id": "hostdev0"} }
+#
+##
+{ 'event': 'UNPLUG_PRIMARY',
+  'data': { 'device_id': 'str' } }
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/11] qapi: add failover negotiated event
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (4 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 05/11] qapi: add unplug primary event Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:20 ` [PATCH 07/11] migration: allow unplug during migration for failover devices Jens Freimann
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

This event is sent to let libvirt know that VIRTIO_NET_F_STANDBY
feature was not negotiated during virtio feature negotiation. If this
event is received it means any primary devices hotplugged before
this were were never really added to QEMU devices.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 qapi/net.json | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/qapi/net.json b/qapi/net.json
index 728990f4fb..8c5f3f1fb2 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -737,3 +737,19 @@
 ##
 { 'command': 'announce-self', 'boxed': true,
   'data' : 'AnnounceParameters'}
+
+##
+# @FAILOVER_NEGOTIATED:
+#
+# Emitted when VIRTIO_NET_F_STANDBY was negotiated during feature negotiation
+#
+# Since: 4.2
+#
+# Example:
+#
+# <- { "event": "FAILOVER_NEGOTIATED",
+#      "data": {} }
+#
+##
+{ 'event': 'FAILOVER_NEGOTIATED',
+  'data': {} }
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/11] migration: allow unplug during migration for failover devices
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (5 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 06/11] qapi: add failover negotiated event Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:20 ` [PATCH 08/11] migration: add new migration state wait-unplug Jens Freimann
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

In "b06424de62 migration: Disable hotplug/unplug during migration" we
added a check to disable unplug for all devices until we have figured
out what works. For failover primary devices qdev_unplug() is called
from the migration handler, i.e. during migration.

This patch adds a flag to DeviceState which is set to false for all
devices and makes an exception for vfio-pci devices that are also
primary devices in a failover pair.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 hw/core/qdev.c         | 1 +
 include/hw/qdev-core.h | 1 +
 qdev-monitor.c         | 2 +-
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 89c134ec53..b1be568af3 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -995,6 +995,7 @@ static void device_initfn(Object *obj)
 
     dev->instance_id_alias = -1;
     dev->realized = false;
+    dev->allow_unplug_during_migration = false;
 
     object_property_add_bool(obj, "realized",
                              device_get_realized, device_set_realized, NULL);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 28f594a47d..6b690e85b1 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -143,6 +143,7 @@ struct DeviceState {
     bool pending_deleted_event;
     QemuOpts *opts;
     int hotplugged;
+    bool allow_unplug_during_migration;
     BusState *parent_bus;
     QLIST_HEAD(, NamedGPIOList) gpios;
     QLIST_HEAD(, BusState) child_bus;
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 508d85df87..265ab4f0d5 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -848,7 +848,7 @@ void qdev_unplug(DeviceState *dev, Error **errp)
         return;
     }
 
-    if (!migration_is_idle()) {
+    if (!migration_is_idle() && !dev->allow_unplug_during_migration) {
         error_setg(errp, "device_del not allowed while migrating");
         return;
     }
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/11] migration: add new migration state wait-unplug
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (6 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 07/11] migration: allow unplug during migration for failover devices Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:20 ` [PATCH 09/11] libqos: tolerate wait-unplug migration state Jens Freimann
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

This patch adds a new migration state called wait-unplug.  It is entered
after the SETUP state if failover devices are present. It will transition
into ACTIVE once all devices were succesfully unplugged from the guest.

So if a guest doesn't respond or takes long to honor the unplug request
the user will see the migration state 'wait-unplug'.

In the migration thread we query failover devices if they're are still
pending the guest unplug. When all are unplugged the migration
continues. If one device won't unplug migration will stay in wait_unplug
state.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 include/migration/vmstate.h |  2 ++
 migration/migration.c       | 21 +++++++++++++++++++++
 migration/migration.h       |  3 +++
 migration/savevm.c          | 36 ++++++++++++++++++++++++++++++++++++
 migration/savevm.h          |  2 ++
 qapi/migration.json         |  5 ++++-
 6 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index b9ee563aa4..ac4f46a67d 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -186,6 +186,8 @@ struct VMStateDescription {
     int (*pre_save)(void *opaque);
     int (*post_save)(void *opaque);
     bool (*needed)(void *opaque);
+    bool (*dev_unplug_pending)(void *opaque);
+
     const VMStateField *fields;
     const VMStateDescription **subsections;
 };
diff --git a/migration/migration.c b/migration/migration.c
index 3febd0f8f3..51764f2565 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -52,6 +52,7 @@
 #include "hw/qdev-properties.h"
 #include "monitor/monitor.h"
 #include "net/announce.h"
+#include "qemu/queue.h"
 
 #define MAX_THROTTLE  (32 << 20)      /* Migration transfer speed throttling */
 
@@ -819,6 +820,7 @@ bool migration_is_setup_or_active(int state)
     case MIGRATION_STATUS_SETUP:
     case MIGRATION_STATUS_PRE_SWITCHOVER:
     case MIGRATION_STATUS_DEVICE:
+    case MIGRATION_STATUS_WAIT_UNPLUG:
         return true;
 
     default:
@@ -954,6 +956,9 @@ static void fill_source_migration_info(MigrationInfo *info)
     case MIGRATION_STATUS_CANCELLED:
         info->has_status = true;
         break;
+    case MIGRATION_STATUS_WAIT_UNPLUG:
+        info->has_status = true;
+        break;
     }
     info->status = s->state;
 }
@@ -1694,6 +1699,7 @@ bool migration_is_idle(void)
     case MIGRATION_STATUS_COLO:
     case MIGRATION_STATUS_PRE_SWITCHOVER:
     case MIGRATION_STATUS_DEVICE:
+    case MIGRATION_STATUS_WAIT_UNPLUG:
         return false;
     case MIGRATION_STATUS__MAX:
         g_assert_not_reached();
@@ -3264,6 +3270,19 @@ static void *migration_thread(void *opaque)
 
     qemu_savevm_state_setup(s->to_dst_file);
 
+    if (qemu_savevm_nr_failover_devices()) {
+        migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
+                          MIGRATION_STATUS_WAIT_UNPLUG);
+
+        while (s->state == MIGRATION_STATUS_WAIT_UNPLUG &&
+                !qemu_savevm_state_guest_unplug_pending()) {
+            qemu_sem_timedwait(&s->wait_unplug_sem, 250);
+        }
+
+        migrate_set_state(&s->state, MIGRATION_STATUS_WAIT_UNPLUG,
+                MIGRATION_STATUS_ACTIVE);
+    }
+
     s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start;
     migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
                       MIGRATION_STATUS_ACTIVE);
@@ -3511,6 +3530,7 @@ static void migration_instance_finalize(Object *obj)
     qemu_mutex_destroy(&ms->qemu_file_lock);
     g_free(params->tls_hostname);
     g_free(params->tls_creds);
+    qemu_sem_destroy(&ms->wait_unplug_sem);
     qemu_sem_destroy(&ms->rate_limit_sem);
     qemu_sem_destroy(&ms->pause_sem);
     qemu_sem_destroy(&ms->postcopy_pause_sem);
@@ -3556,6 +3576,7 @@ static void migration_instance_init(Object *obj)
     qemu_sem_init(&ms->postcopy_pause_rp_sem, 0);
     qemu_sem_init(&ms->rp_state.rp_sem, 0);
     qemu_sem_init(&ms->rate_limit_sem, 0);
+    qemu_sem_init(&ms->wait_unplug_sem, 0);
     qemu_mutex_init(&ms->qemu_file_lock);
 }
 
diff --git a/migration/migration.h b/migration/migration.h
index 4f2fe193dc..79b3dda146 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -206,6 +206,9 @@ struct MigrationState
     /* Flag set once the migration thread called bdrv_inactivate_all */
     bool block_inactive;
 
+    /* Migration is waiting for guest to unplug device */
+    QemuSemaphore wait_unplug_sem;
+
     /* Migration is paused due to pause-before-switchover */
     QemuSemaphore pause_sem;
 
diff --git a/migration/savevm.c b/migration/savevm.c
index 8d95e261f6..0f18dea49e 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1113,6 +1113,42 @@ void qemu_savevm_state_header(QEMUFile *f)
     }
 }
 
+int qemu_savevm_nr_failover_devices(void)
+{
+    SaveStateEntry *se;
+    int n = 0;
+
+    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+        if (se->vmsd && se->vmsd->dev_unplug_pending) {
+            n++;
+        }
+    }
+
+    return n;
+}
+
+bool qemu_savevm_state_guest_unplug_pending(void)
+{
+    int nr_failover_devs;
+    SaveStateEntry *se;
+    bool ret = false;
+    int n = 0;
+
+    nr_failover_devs = qemu_savevm_nr_failover_devices();
+
+    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+        if (!se->vmsd || !se->vmsd->dev_unplug_pending) {
+            continue;
+        }
+        ret = se->vmsd->dev_unplug_pending(se->opaque);
+        if (!ret) {
+            n++;
+        }
+    }
+
+    return n == nr_failover_devs;
+}
+
 void qemu_savevm_state_setup(QEMUFile *f)
 {
     SaveStateEntry *se;
diff --git a/migration/savevm.h b/migration/savevm.h
index 51a4b9caa8..c42b9c80ee 100644
--- a/migration/savevm.h
+++ b/migration/savevm.h
@@ -31,6 +31,8 @@
 
 bool qemu_savevm_state_blocked(Error **errp);
 void qemu_savevm_state_setup(QEMUFile *f);
+int qemu_savevm_nr_failover_devices(void);
+bool qemu_savevm_state_guest_unplug_pending(void);
 int qemu_savevm_state_resume_prepare(MigrationState *s);
 void qemu_savevm_state_header(QEMUFile *f);
 int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy);
diff --git a/qapi/migration.json b/qapi/migration.json
index 52e69e2868..5a06cd489f 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -133,6 +133,9 @@
 # @device: During device serialisation when pause-before-switchover is enabled
 #        (since 2.11)
 #
+# @wait-unplug: wait for device unplug request by guest OS to be completed.
+#               (since 4.2)
+#
 # Since: 2.3
 #
 ##
@@ -140,7 +143,7 @@
   'data': [ 'none', 'setup', 'cancelling', 'cancelled',
             'active', 'postcopy-active', 'postcopy-paused',
             'postcopy-recover', 'completed', 'failed', 'colo',
-            'pre-switchover', 'device' ] }
+            'pre-switchover', 'device', 'wait-unplug' ] }
 
 ##
 # @MigrationInfo:
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/11] libqos: tolerate wait-unplug migration state
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (7 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 08/11] migration: add new migration state wait-unplug Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:20 ` [PATCH 10/11] net/virtio: add failover support Jens Freimann
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 tests/libqos/libqos.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c
index d71557c5cb..f229eb2cb8 100644
--- a/tests/libqos/libqos.c
+++ b/tests/libqos/libqos.c
@@ -125,7 +125,8 @@ void migrate(QOSState *from, QOSState *to, const char *uri)
             break;
         }
 
-        if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0)) {
+        if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0)
+            || (strcmp(st, "wait-unplug") == 0)) {
             qobject_unref(rsp);
             g_usleep(5000);
             continue;
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/11] net/virtio: add failover support
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (8 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 09/11] libqos: tolerate wait-unplug migration state Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-18 20:20 ` [PATCH 11/11] vfio: unplug failover primary device before migration Jens Freimann
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

This patch adds support to handle failover device pairs of a virtio-net
device and a vfio-pci device, where the virtio-net acts as the standby
device and the vfio-pci device as the primary.

The general idea is that we have a pair of devices, a vfio-pci and a
emulated (virtio-net) device. Before migration the vfio device is
unplugged and data flows to the emulated device, on the target side
another vfio-pci device is plugged in to take over the data-path. In the
guest the net_failover module will pair net devices with the same MAC
address.

To achieve this we need:

1. Provide a callback function for the should_be_hidden DeviceListener.
   It is called when the primary device is plugged in. Evaluate the QOpt
   passed in to check if it is the matching primary device. It returns
   two values:
     - one to signal if the device to be added is the matching
       primary device
     - another one to signal to qdev if it should actually
       continue with adding the device or skip it.

   In the latter case it stores the device options in the VirtioNet
   struct and the device is added once the VIRTIO_NET_F_STANDBY feature is
   negotiated during virtio feature negotiation.

   If the virtio-net devices are not realized at the time the vfio-pci
   devices are realized, we need to connect the devices later. This way
   we make sure primary and standby devices can be specified in any
   order.

2. Register a callback for migration status notifier. When called it
   will unplug its primary device before the migration happens.

3. Register a callback for the migration code that checks if a device
   needs to be unplugged from the guest.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 hw/net/virtio-net.c            | 282 +++++++++++++++++++++++++++++++++
 include/hw/virtio/virtio-net.h |  12 ++
 include/hw/virtio/virtio.h     |   1 +
 3 files changed, 295 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 9f11422337..afe113f083 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 "qemu/main-loop.h"
 #include "qemu/module.h"
@@ -21,6 +22,10 @@
 #include "net/tap.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
+#include "qemu/option.h"
+#include "qemu/option_int.h"
+#include "qemu/config-file.h"
+#include "qapi/qmp/qdict.h"
 #include "hw/virtio/virtio-net.h"
 #include "net/vhost_net.h"
 #include "net/announce.h"
@@ -28,11 +33,15 @@
 #include "qapi/error.h"
 #include "qapi/qapi-events-net.h"
 #include "hw/qdev-properties.h"
+#include "qapi/qapi-types-migration.h"
+#include "qapi/qapi-events-migration.h"
 #include "hw/virtio/virtio-access.h"
 #include "migration/misc.h"
 #include "standard-headers/linux/ethtool.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
+#include "monitor/qdev.h"
+#include "hw/pci/pci.h"
 
 #define VIRTIO_NET_VM_VERSION    11
 
@@ -746,9 +755,85 @@ static inline uint64_t virtio_net_supported_guest_offloads(VirtIONet *n)
     return virtio_net_guest_offloads_by_features(vdev->guest_features);
 }
 
+static void failover_add_primary(VirtIONet *n)
+{
+    Error *err = NULL;
+
+    n->primary_device_opts = qemu_opts_find(qemu_find_opts("device"),
+            n->primary_device_id);
+    if (n->primary_device_opts) {
+        n->primary_dev = qdev_device_add(n->primary_device_opts, &err);
+        if (err) {
+            qemu_opts_del(n->primary_device_opts);
+        }
+        if (n->primary_dev) {
+            n->primary_bus = n->primary_dev->parent_bus;
+            if (err) {
+                qdev_unplug(n->primary_dev, &err);
+                qdev_set_id(n->primary_dev, "");
+
+            }
+        }
+    }
+    if (err) {
+        error_report_err(err);
+    }
+}
+
+static int is_my_primary(void *opaque, QemuOpts *opts, Error **errp)
+{
+    VirtIONet *n = opaque;
+    int ret = 0;
+
+    const char *standby_id = qemu_opt_get(opts, "net_failover_pair_id");
+
+    if (standby_id != NULL && (g_strcmp0(standby_id, n->netclient_name) == 0)) {
+        n->primary_device_id = g_strdup(opts->id);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+static DeviceState *virtio_net_find_primary(VirtIONet *n, Error *err)
+{
+    DeviceState *dev = NULL;
+
+    if (qemu_opts_foreach(qemu_find_opts("device"),
+                         is_my_primary, n, &err)) {
+        if (n->primary_device_id) {
+            dev = qdev_find_recursive(sysbus_get_default(),
+                    n->primary_device_id);
+        } else {
+            return NULL;
+        }
+    }
+    return dev;
+}
+
+
+
+static DeviceState *virtio_connect_failover_devices(VirtIONet *n,
+                                                    DeviceState *dev,
+                                                    Error **errp)
+{
+    DeviceState *prim_dev = NULL;
+
+    prim_dev = virtio_net_find_primary(n, *errp);
+    if (prim_dev) {
+        n->primary_device_id = g_strdup(prim_dev->id);
+        n->primary_device_opts = prim_dev->opts;
+    } else {
+        error_setg(errp, "connect: virtio_net: Could not find primary device");
+    }
+
+    return prim_dev;
+}
+
 static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
 {
     VirtIONet *n = VIRTIO_NET(vdev);
+    Error *err = NULL;
     int i;
 
     if (n->mtu_bypass_backend &&
@@ -790,6 +875,22 @@ 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);
+        failover_add_primary(n);
+        if (!n->primary_dev) {
+            n->primary_dev = virtio_connect_failover_devices(n, n->qdev, &err);
+            if (!n->primary_dev) {
+                failover_add_primary(n);
+                n->primary_dev = virtio_connect_failover_devices(n, n->qdev,
+                                                                 &err);
+            }
+        }
+    }
+    if (err) {
+        error_report_err(err);
+    }
 }
 
 static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
@@ -2630,6 +2731,150 @@ void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
     n->netclient_type = g_strdup(type);
 }
 
+static bool failover_unplug_primary(VirtIONet *n)
+{
+    HotplugHandler *hotplug_ctrl;
+    PCIDevice *pci_dev;
+    Error *err = NULL;
+
+    hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev);
+    if (hotplug_ctrl) {
+        pci_dev = PCI_DEVICE(n->primary_dev);
+        pci_dev->partially_hotplugged = true;
+        hotplug_handler_unplug_request(hotplug_ctrl, n->primary_dev, &err);
+        if (err) {
+            error_report_err(err);
+            return false;
+        }
+    } else {
+        return false;
+    }
+    return true;
+}
+
+static bool failover_replug_primary(VirtIONet *n, Error **errp)
+{
+    HotplugHandler *hotplug_ctrl;
+    PCIDevice *pdev = PCI_DEVICE(n->primary_dev);
+
+    if (!pdev->partially_hotplugged) {
+        return true;
+    }
+    if (!n->primary_device_opts) {
+        n->primary_device_opts = qemu_opts_from_qdict(
+                qemu_find_opts("device"),
+                n->primary_device_dict, errp);
+    }
+    if (n->primary_device_opts) {
+        if (n->primary_dev) {
+            n->primary_bus = n->primary_dev->parent_bus;
+        }
+        qdev_set_parent_bus(n->primary_dev, n->primary_bus);
+        n->primary_should_be_hidden = false;
+        qemu_opt_set_bool(n->primary_device_opts,
+                "partially_hotplugged", true, errp);
+        hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev);
+        if (hotplug_ctrl) {
+            hotplug_handler_pre_plug(hotplug_ctrl, n->primary_dev, errp);
+            hotplug_handler_plug(hotplug_ctrl, n->primary_dev, errp);
+        }
+        if (!n->primary_dev) {
+            error_setg(errp, "virtio_net: couldn't find primary device");
+        }
+    }
+    return *errp != NULL;
+}
+
+static void virtio_net_handle_migration_primary(VirtIONet *n,
+                                                MigrationState *s)
+{
+    bool should_be_hidden;
+    Error *err = NULL;
+
+    should_be_hidden = atomic_read(&n->primary_should_be_hidden);
+
+    if (!n->primary_dev) {
+        n->primary_dev = virtio_connect_failover_devices(n, n->qdev, &err);
+        if (!n->primary_dev) {
+            return;
+        }
+    }
+
+    if (migration_in_setup(s) && !should_be_hidden &&
+        n->primary_dev) {
+        if (failover_unplug_primary(n)) {
+            vmstate_unregister(n->primary_dev, qdev_get_vmsd(n->primary_dev),
+                    n->primary_dev);
+            qapi_event_send_unplug_primary(n->primary_device_id);
+            atomic_set(&n->primary_should_be_hidden, true);
+        } else {
+            warn_report("virtio_net: Couldn't unplug primary device");
+        }
+    } else if (migration_has_failed(s)) {
+        /* We already unplugged the device let's plugged it back */
+        if (!failover_replug_primary(n, &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 int virtio_net_primary_should_be_hidden(DeviceListener *listener,
+            QemuOpts *device_opts)
+{
+    VirtIONet *n = container_of(listener, VirtIONet, primary_listener);
+    bool match_found;
+    bool hide;
+
+    n->primary_device_dict = qemu_opts_to_qdict(device_opts,
+            n->primary_device_dict);
+    if (n->primary_device_dict) {
+        g_free(n->standby_id);
+        n->standby_id = g_strdup(qdict_get_try_str(n->primary_device_dict,
+                    "net_failover_pair_id"));
+    }
+    if (device_opts && g_strcmp0(n->standby_id, n->netclient_name) == 0) {
+        match_found = true;
+    } else {
+        match_found = false;
+        hide = false;
+        g_free(n->standby_id);
+        n->primary_device_dict = NULL;
+        goto out;
+    }
+
+    n->primary_device_opts = device_opts;
+
+    /* primary_should_be_hidden is set during feature negotiation */
+    hide = atomic_read(&n->primary_should_be_hidden);
+
+    if (n->primary_device_dict) {
+        g_free(n->primary_device_id);
+        n->primary_device_id = g_strdup(qdict_get_try_str(
+                    n->primary_device_dict, "id"));
+        if (!n->primary_device_id) {
+            warn_report("primary_device_id NULL");
+        }
+    }
+
+out:
+    if (match_found && hide) {
+        return 1;
+    } else if (match_found && !hide) {
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
 static void virtio_net_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -2660,6 +2905,16 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
         n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX);
     }
 
+    if (n->failover) {
+        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 = virtio_net_migration_state_notifier;
+        add_migration_state_change_notifier(&n->migration_state);
+        n->host_features |= (1ULL << VIRTIO_NET_F_STANDBY);
+    }
+
     virtio_net_set_config_size(n, n->host_features);
     virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
 
@@ -2782,6 +3037,13 @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
     g_free(n->mac_table.macs);
     g_free(n->vlans);
 
+    if (n->failover) {
+        g_free(n->primary_device_id);
+        g_free(n->standby_id);
+        qobject_unref(n->primary_device_dict);
+        n->primary_device_dict = NULL;
+    }
+
     max_queues = n->multiqueue ? n->max_queues : 1;
     for (i = 0; i < max_queues; i++) {
         virtio_net_del_queue(n, i);
@@ -2819,6 +3081,23 @@ static int virtio_net_pre_save(void *opaque)
     return 0;
 }
 
+static bool primary_unplug_pending(void *opaque)
+{
+    DeviceState *dev = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIONet *n = VIRTIO_NET(vdev);
+
+    return n->primary_dev ? n->primary_dev->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,
@@ -2828,6 +3107,7 @@ 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[] = {
@@ -2889,6 +3169,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_BOOL("failover", VirtIONet, failover, false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -2913,6 +3194,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
     vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
     vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO);
     vdc->vmsd = &vmstate_virtio_net_device;
+    vdc->primary_unplug_pending = primary_unplug_pending;
 }
 
 static const TypeInfo virtio_net_info = {
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index b96f0c643f..3da4ca382a 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -18,6 +18,7 @@
 #include "standard-headers/linux/virtio_net.h"
 #include "hw/virtio/virtio.h"
 #include "net/announce.h"
+#include "qemu/option_int.h"
 
 #define TYPE_VIRTIO_NET "virtio-net-device"
 #define VIRTIO_NET(obj) \
@@ -43,6 +44,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 +187,16 @@ struct VirtIONet {
     AnnounceTimer announce_timer;
     bool needs_vnet_hdr_swap;
     bool mtu_bypass_backend;
+    QemuOpts *primary_device_opts;
+    QDict *primary_device_dict;
+    DeviceState *primary_dev;
+    BusState *primary_bus;
+    char *primary_device_id;
+    char *standby_id;
+    bool primary_should_be_hidden;
+    bool failover;
+    DeviceListener primary_listener;
+    Notifier migration_state;
 };
 
 void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 48e8d04ff6..0c857ecf1a 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -159,6 +159,7 @@ typedef struct VirtioDeviceClass {
     void (*save)(VirtIODevice *vdev, QEMUFile *f);
     int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id);
     const VMStateDescription *vmsd;
+    bool (*primary_unplug_pending)(void *opaque);
 } VirtioDeviceClass;
 
 void virtio_instance_init_common(Object *proxy_obj, void *data,
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/11] vfio: unplug failover primary device before migration
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (9 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 10/11] net/virtio: add failover support Jens Freimann
@ 2019-10-18 20:20 ` Jens Freimann
  2019-10-21 13:45   ` Cornelia Huck
  2019-10-21 15:19   ` Alex Williamson
  2019-10-19 15:12 ` [PATCH v4 0/11] add failover feature for assigned network devices no-reply
                   ` (2 subsequent siblings)
  13 siblings, 2 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-18 20:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

As usual block all vfio-pci devices from being migrated, but make an
exception for failover primary devices. This is achieved by setting
unmigratable to 0 but also add a migration blocker for all vfio-pci
devices except failover primary devices. These will be unplugged before
migration happens by the migration handler of the corresponding
virtio-net standby device.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
---
 hw/vfio/pci.c | 31 +++++++++++++++++++++++++------
 hw/vfio/pci.h |  1 +
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 12fac39804..a15b83c6b6 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -40,6 +40,9 @@
 #include "pci.h"
 #include "trace.h"
 #include "qapi/error.h"
+#include "migration/blocker.h"
+#include "qemu/option.h"
+#include "qemu/option_int.h"
 
 #define TYPE_VFIO_PCI "vfio-pci"
 #define PCI_VFIO(obj)    OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI)
@@ -2712,12 +2715,26 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
     int i, ret;
     bool is_mdev;
 
+    if (!pdev->net_failover_pair_id) {
+        error_setg(&vdev->migration_blocker,
+                "VFIO device doesn't support migration");
+        ret = migrate_add_blocker(vdev->migration_blocker, &err);
+        if (err) {
+            error_propagate(errp, err);
+            goto error;
+        }
+    } else {
+            pdev->qdev.allow_unplug_during_migration = true;
+    }
+
     if (!vdev->vbasedev.sysfsdev) {
         if (!(~vdev->host.domain || ~vdev->host.bus ||
               ~vdev->host.slot || ~vdev->host.function)) {
             error_setg(errp, "No provided host device");
             error_append_hint(errp, "Use -device vfio-pci,host=DDDD:BB:DD.F "
                               "or -device vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
+            migrate_del_blocker(vdev->migration_blocker);
+            error_free(vdev->migration_blocker);
             return;
         }
         vdev->vbasedev.sysfsdev =
@@ -2729,6 +2746,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
     if (stat(vdev->vbasedev.sysfsdev, &st) < 0) {
         error_setg_errno(errp, errno, "no such host device");
         error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.sysfsdev);
+        migrate_del_blocker(vdev->migration_blocker);
+        error_free(vdev->migration_blocker);
         return;
     }
 
@@ -3008,6 +3027,8 @@ out_teardown:
     vfio_bars_exit(vdev);
 error:
     error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
+    migrate_del_blocker(vdev->migration_blocker);
+    error_free(vdev->migration_blocker);
 }
 
 static void vfio_instance_finalize(Object *obj)
@@ -3019,6 +3040,10 @@ static void vfio_instance_finalize(Object *obj)
     vfio_bars_finalize(vdev);
     g_free(vdev->emulated_config_bits);
     g_free(vdev->rom);
+    if (vdev->migration_blocker) {
+        migrate_del_blocker(vdev->migration_blocker);
+        error_free(vdev->migration_blocker);
+    }
     /*
      * XXX Leaking igd_opregion is not an oversight, we can't remove the
      * fw_cfg entry therefore leaking this allocation seems like the safest
@@ -3151,11 +3176,6 @@ static Property vfio_pci_dev_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static const VMStateDescription vfio_pci_vmstate = {
-    .name = "vfio-pci",
-    .unmigratable = 1,
-};
-
 static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -3163,7 +3183,6 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
 
     dc->reset = vfio_pci_reset;
     dc->props = vfio_pci_dev_properties;
-    dc->vmsd = &vfio_pci_vmstate;
     dc->desc = "VFIO-based PCI device assignment";
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     pdc->realize = vfio_realize;
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 834a90d646..b329d50338 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -168,6 +168,7 @@ typedef struct VFIOPCIDevice {
     bool no_vfio_ioeventfd;
     bool enable_ramfb;
     VFIODisplay *dpy;
+    Error *migration_blocker;
 } VFIOPCIDevice;
 
 uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/11] qapi: add unplug primary event
  2019-10-18 20:20 ` [PATCH 05/11] qapi: add unplug primary event Jens Freimann
@ 2019-10-18 20:28   ` Eric Blake
  2019-10-21  7:23     ` Jens Freimann
  0 siblings, 1 reply; 31+ messages in thread
From: Eric Blake @ 2019-10-18 20:28 UTC (permalink / raw)
  To: Jens Freimann, qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

On 10/18/19 3:20 PM, Jens Freimann wrote:
> This event is emitted when we sent a request to unplug a
> failover primary device from the Guest OS and it includes the
> device id of the primary device.
> 
> Signed-off-by: Jens Freimann <jfreimann@redhat.com>
> ---
>   qapi/migration.json | 19 +++++++++++++++++++
>   1 file changed, 19 insertions(+)
> 
> diff --git a/qapi/migration.json b/qapi/migration.json
> index 82feb5bd39..52e69e2868 100644
> --- a/qapi/migration.json
> +++ b/qapi/migration.json
> @@ -1448,3 +1448,22 @@
>   # Since: 3.0
>   ##
>   { 'command': 'migrate-pause', 'allow-oob': true }
> +
> +##
> +# @UNPLUG_PRIMARY:
> +#
> +# Emitted from source side of a migration when migration state is
> +# WAIT_UNPLUG. Device was unplugged by guest operating system.
> +# Device resources in QEMU are kept on standby to be able to re-plug it in case
> +# of migration failure.
> +#
> +# @device_id: QEMU device id of the unplugged device
> +#
> +# Since: 4.2
> +#
> +# Example:
> +#   {"event": "UNPLUG_PRIMARY", "data": {"device_id": "hostdev0"} }

Unless there is a strong reason in favor of 'device_id' (such as 
consistency with a similar event), our naming convention prefers this to 
be 'device-id'.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v4 0/11] add failover feature for assigned network devices
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (10 preceding siblings ...)
  2019-10-18 20:20 ` [PATCH 11/11] vfio: unplug failover primary device before migration Jens Freimann
@ 2019-10-19 15:12 ` no-reply
  2019-10-21  7:30   ` Jens Freimann
  2019-10-19 15:15 ` no-reply
  2019-10-21 14:18 ` Cornelia Huck
  13 siblings, 1 reply; 31+ messages in thread
From: no-reply @ 2019-10-19 15:12 UTC (permalink / raw)
  To: jfreimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

Patchew URL: https://patchew.org/QEMU/20191018202040.30349-1-jfreimann@redhat.com/



Hi,

This series failed the docker-quick@centos7 build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-centos7 V=1 NETWORK=1
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
=== TEST SCRIPT END ===

  CC      hw/core/or-irq.o
  CC      hw/core/split-irq.o
/tmp/qemu-test/src/hw/core/qdev.c: In function 'qdev_should_hide_device':
/tmp/qemu-test/src/hw/core/qdev.c:235:5: error: 'rc' may be used uninitialized in this function [-Werror=maybe-uninitialized]
     return rc > 0;
     ^
cc1: all warnings being treated as errors
make: *** [hw/core/qdev.o] Error 1
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 662, in <module>
---
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=45df366e5eaf45f6ac429142fe2cc309', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-ozx9dk_0/src/docker-src.2019-10-19-11.10.07.7972:/var/tmp/qemu:z,ro', 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2.
filter=--filter=label=com.qemu.instance.uuid=45df366e5eaf45f6ac429142fe2cc309
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ozx9dk_0/src'
make: *** [docker-run-test-quick@centos7] Error 2

real    2m19.619s
user    0m8.409s


The full log is available at
http://patchew.org/logs/20191018202040.30349-1-jfreimann@redhat.com/testing.docker-quick@centos7/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v4 0/11] add failover feature for assigned network devices
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (11 preceding siblings ...)
  2019-10-19 15:12 ` [PATCH v4 0/11] add failover feature for assigned network devices no-reply
@ 2019-10-19 15:15 ` no-reply
  2019-10-21 14:18 ` Cornelia Huck
  13 siblings, 0 replies; 31+ messages in thread
From: no-reply @ 2019-10-19 15:15 UTC (permalink / raw)
  To: jfreimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

Patchew URL: https://patchew.org/QEMU/20191018202040.30349-1-jfreimann@redhat.com/



Hi,

This series failed the docker-mingw@fedora build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#! /bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-mingw@fedora J=14 NETWORK=1
=== TEST SCRIPT END ===

  CC      hw/core/platform-bus.o
  CC      hw/core/generic-loader.o
/tmp/qemu-test/src/hw/core/qdev.c: In function 'qdev_should_hide_device':
/tmp/qemu-test/src/hw/core/qdev.c:235:15: error: 'rc' may be used uninitialized in this function [-Werror=maybe-uninitialized]
     return rc > 0;
            ~~~^~~
cc1: all warnings being treated as errors
make: *** [/tmp/qemu-test/src/rules.mak:69: hw/core/qdev.o] Error 1
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 662, in <module>
---
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=1d57bd92e38c4da3a26a7b0d378b562e', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-ggapjx1d/src/docker-src.2019-10-19-11.13.01.17849:/var/tmp/qemu:z,ro', 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit status 2.
filter=--filter=label=com.qemu.instance.uuid=1d57bd92e38c4da3a26a7b0d378b562e
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ggapjx1d/src'
make: *** [docker-run-test-mingw@fedora] Error 2

real    2m33.496s
user    0m8.171s


The full log is available at
http://patchew.org/logs/20191018202040.30349-1-jfreimann@redhat.com/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/11] qapi: add unplug primary event
  2019-10-18 20:28   ` Eric Blake
@ 2019-10-21  7:23     ` Jens Freimann
  0 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-21  7:23 UTC (permalink / raw)
  To: Eric Blake
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

On Fri, Oct 18, 2019 at 03:28:36PM -0500, Eric Blake wrote:
>On 10/18/19 3:20 PM, Jens Freimann wrote:
>>This event is emitted when we sent a request to unplug a
>>failover primary device from the Guest OS and it includes the
>>device id of the primary device.
>>
>>Signed-off-by: Jens Freimann <jfreimann@redhat.com>
>>---
>>  qapi/migration.json | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>
>>diff --git a/qapi/migration.json b/qapi/migration.json
>>index 82feb5bd39..52e69e2868 100644
>>--- a/qapi/migration.json
>>+++ b/qapi/migration.json
>>@@ -1448,3 +1448,22 @@
>>  # Since: 3.0
>>  ##
>>  { 'command': 'migrate-pause', 'allow-oob': true }
>>+
>>+##
>>+# @UNPLUG_PRIMARY:
>>+#
>>+# Emitted from source side of a migration when migration state is
>>+# WAIT_UNPLUG. Device was unplugged by guest operating system.
>>+# Device resources in QEMU are kept on standby to be able to re-plug it in case
>>+# of migration failure.
>>+#
>>+# @device_id: QEMU device id of the unplugged device
>>+#
>>+# Since: 4.2
>>+#
>>+# Example:
>>+#   {"event": "UNPLUG_PRIMARY", "data": {"device_id": "hostdev0"} }
>
>Unless there is a strong reason in favor of 'device_id' (such as 
>consistency with a similar event), our naming convention prefers this 
>to be 'device-id'.

No reason, I'll change it.

Thanks Eric!

regards,
Jens 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v4 0/11] add failover feature for assigned network devices
  2019-10-19 15:12 ` [PATCH v4 0/11] add failover feature for assigned network devices no-reply
@ 2019-10-21  7:30   ` Jens Freimann
  0 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-21  7:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: pkrempa, berrange, ehabkost, mst, aadam, dgilbert,
	alex.williamson, laine, ailan, parav

On Sat, Oct 19, 2019 at 08:12:27AM -0700, no-reply@patchew.org wrote:
>Patchew URL: https://patchew.org/QEMU/20191018202040.30349-1-jfreimann@redhat.com/
>
>
>
>Hi,
>
>This series failed the docker-quick@centos7 build test. Please find the testing commands and
>their output below. If you have Docker installed, you can probably reproduce it
>locally.
>
>=== TEST SCRIPT BEGIN ===
>#!/bin/bash
>make docker-image-centos7 V=1 NETWORK=1
>time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
>=== TEST SCRIPT END ===
>
>  CC      hw/core/or-irq.o
>  CC      hw/core/split-irq.o
>/tmp/qemu-test/src/hw/core/qdev.c: In function 'qdev_should_hide_device':
>/tmp/qemu-test/src/hw/core/qdev.c:235:5: error: 'rc' may be used uninitialized in this function [-Werror=maybe-uninitialized]
>     return rc > 0;

hmpf, always run all tests especially after last minute changes on friday afternoon. I'll fix this.

regards,
Jens 


     ^
>cc1: all warnings being treated as errors
>make: *** [hw/core/qdev.o] Error 1
>make: *** Waiting for unfinished jobs....
>Traceback (most recent call last):
>  File "./tests/docker/docker.py", line 662, in <module>
>---
>    raise CalledProcessError(retcode, cmd)
>subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=45df366e5eaf45f6ac429142fe2cc309', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-ozx9dk_0/src/docker-src.2019-10-19-11.10.07.7972:/var/tmp/qemu:z,ro', 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2.
>filter=--filter=label=com.qemu.instance.uuid=45df366e5eaf45f6ac429142fe2cc309
>make[1]: *** [docker-run] Error 1
>make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ozx9dk_0/src'
>make: *** [docker-run-test-quick@centos7] Error 2
>
>real    2m19.619s
>user    0m8.409s
>
>
>The full log is available at
>http://patchew.org/logs/20191018202040.30349-1-jfreimann@redhat.com/testing.docker-quick@centos7/?type=message.
>---
>Email generated automatically by Patchew [https://patchew.org/].
>Please send your feedback to patchew-devel@redhat.com



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 01/11] qdev/qbus: add hidden device support
  2019-10-18 20:20 ` [PATCH 01/11] qdev/qbus: add hidden device support Jens Freimann
@ 2019-10-21 12:44   ` Cornelia Huck
  2019-10-21 12:52     ` Jens Freimann
  2019-10-21 12:53   ` Peter Maydell
  1 sibling, 1 reply; 31+ messages in thread
From: Cornelia Huck @ 2019-10-21 12:44 UTC (permalink / raw)
  To: Jens Freimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

On Fri, 18 Oct 2019 22:20:30 +0200
Jens Freimann <jfreimann@redhat.com> wrote:

> This adds support for hiding a device to the qbus and qdev APIs.  The
> first user of this will be the virtio-net failover feature but the API
> introduced with this patch could be used to implement other features as
> well, for example hiding pci devices when a pci bus is powered off.
> 
> qdev_device_add() is modified to check for a net_failover_pair_id
> argument in the option string. A DeviceListener callback
> should_be_hidden() is added. It can be used by a standby device to
> inform qdev that this device should not be added now. The standby device
> handler can store the device options to plug the device in at a later
> point in time.
> 
> One reason for hiding the device is that we don't want to expose both
> devices to the guest kernel until the respective virtio feature bit
> VIRTIO_NET_F_STANDBY was negotiated and we know that the devices will be
> handled correctly by the guest.
> 
> More information on the kernel feature this is using:
>  https://www.kernel.org/doc/html/latest/networking/net_failover.html
> 
> An example where the primary device is a vfio-pci device and the standby
> device is a virtio-net device:
> 
> A device is hidden when it has an "net_failover_pair_id" option, e.g.
> 
>  -device virtio-net-pci,...,failover=on,...
>  -device vfio-pci,...,net_failover_pair_id=net1,...
> 
> Signed-off-by: Jens Freimann <jfreimann@redhat.com>
> ---
>  hw/core/qdev.c         | 23 +++++++++++++++++++++++
>  include/hw/qdev-core.h |  8 ++++++++
>  qdev-monitor.c         | 36 +++++++++++++++++++++++++++++++++---
>  vl.c                   |  6 ++++--
>  4 files changed, 68 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index cbad6c1d55..89c134ec53 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -212,6 +212,29 @@ void device_listener_unregister(DeviceListener *listener)
>      QTAILQ_REMOVE(&device_listeners, listener, link);
>  }
>  
> +bool qdev_should_hide_device(QemuOpts *opts)
> +{
> +    int rc;

Initialize to 0?

> +    DeviceListener *listener;
> +
> +    QTAILQ_FOREACH(listener, &device_listeners, link) {
> +       if (listener->should_be_hidden) {
> +            /* should_be_hidden_will return
> +             *  1 if device matches opts and it should be hidden
> +             *  0 if device matches opts and should not be hidden
> +             *  -1 if device doesn't match ops
> +             */
> +            rc = listener->should_be_hidden(listener, opts);
> +        }
> +
> +        if (rc > 0) {
> +            break;
> +        }
> +    }
> +
> +    return rc > 0;
> +}
> +
>  void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
>                                   int required_for_version)
>  {

(...)

> +static bool should_hide_device(QemuOpts *opts)
> +{
> +    if (qemu_opt_foreach(opts, is_failover_device, opts, NULL) == 0) {
> +        return false;
> +    }
> +    return true;
> +}

I still think you should turn the check around to make it easier to
extend in the future, but this is fine as well.

(...)

With the rc thing changed,

Reviewed-by: Cornelia Huck <cohuck@redhat.com>



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 01/11] qdev/qbus: add hidden device support
  2019-10-21 12:44   ` Cornelia Huck
@ 2019-10-21 12:52     ` Jens Freimann
  0 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-21 12:52 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

On Mon, Oct 21, 2019 at 02:44:08PM +0200, Cornelia Huck wrote:
>On Fri, 18 Oct 2019 22:20:30 +0200
>Jens Freimann <jfreimann@redhat.com> wrote:
>
>> This adds support for hiding a device to the qbus and qdev APIs.  The
>> first user of this will be the virtio-net failover feature but the API
>> introduced with this patch could be used to implement other features as
>> well, for example hiding pci devices when a pci bus is powered off.
>>
>> qdev_device_add() is modified to check for a net_failover_pair_id
>> argument in the option string. A DeviceListener callback
>> should_be_hidden() is added. It can be used by a standby device to
>> inform qdev that this device should not be added now. The standby device
>> handler can store the device options to plug the device in at a later
>> point in time.
>>
>> One reason for hiding the device is that we don't want to expose both
>> devices to the guest kernel until the respective virtio feature bit
>> VIRTIO_NET_F_STANDBY was negotiated and we know that the devices will be
>> handled correctly by the guest.
>>
>> More information on the kernel feature this is using:
>>  https://www.kernel.org/doc/html/latest/networking/net_failover.html
>>
>> An example where the primary device is a vfio-pci device and the standby
>> device is a virtio-net device:
>>
>> A device is hidden when it has an "net_failover_pair_id" option, e.g.
>>
>>  -device virtio-net-pci,...,failover=on,...
>>  -device vfio-pci,...,net_failover_pair_id=net1,...
>>
>> Signed-off-by: Jens Freimann <jfreimann@redhat.com>
>> ---
>>  hw/core/qdev.c         | 23 +++++++++++++++++++++++
>>  include/hw/qdev-core.h |  8 ++++++++
>>  qdev-monitor.c         | 36 +++++++++++++++++++++++++++++++++---
>>  vl.c                   |  6 ++++--
>>  4 files changed, 68 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
>> index cbad6c1d55..89c134ec53 100644
>> --- a/hw/core/qdev.c
>> +++ b/hw/core/qdev.c
>> @@ -212,6 +212,29 @@ void device_listener_unregister(DeviceListener *listener)
>>      QTAILQ_REMOVE(&device_listeners, listener, link);
>>  }
>>
>> +bool qdev_should_hide_device(QemuOpts *opts)
>> +{
>> +    int rc;
>
>Initialize to 0?

Yes, that's what the test bot found as well. Fixed it already. 
Though I initialize to -1, otherwise all devices will be hidden.

>> +    DeviceListener *listener;
>> +
>> +    QTAILQ_FOREACH(listener, &device_listeners, link) {
>> +       if (listener->should_be_hidden) {
>> +            /* should_be_hidden_will return
>> +             *  1 if device matches opts and it should be hidden
>> +             *  0 if device matches opts and should not be hidden
>> +             *  -1 if device doesn't match ops
>> +             */
>> +            rc = listener->should_be_hidden(listener, opts);
>> +        }
>> +
>> +        if (rc > 0) {
>> +            break;
>> +        }
>> +    }
>> +
>> +    return rc > 0;
>> +}
>> +
>>  void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
>>                                   int required_for_version)
>>  {
>
>(...)
>
>> +static bool should_hide_device(QemuOpts *opts)
>> +{
>> +    if (qemu_opt_foreach(opts, is_failover_device, opts, NULL) == 0) {
>> +        return false;
>> +    }
>> +    return true;
>> +}
>
>I still think you should turn the check around to make it easier to
>extend in the future, but this is fine as well.

Sorry, I've gone back and forth on this and ended up with the same.
I'll take another look at it. 

>(...)
>
>With the rc thing changed,
>
>Reviewed-by: Cornelia Huck <cohuck@redhat.com>

Thanks!

regards,
Jens 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 01/11] qdev/qbus: add hidden device support
  2019-10-18 20:20 ` [PATCH 01/11] qdev/qbus: add hidden device support Jens Freimann
  2019-10-21 12:44   ` Cornelia Huck
@ 2019-10-21 12:53   ` Peter Maydell
  2019-10-21 13:00     ` Jens Freimann
  1 sibling, 1 reply; 31+ messages in thread
From: Peter Maydell @ 2019-10-21 12:53 UTC (permalink / raw)
  To: Jens Freimann
  Cc: Peter Krempa, Daniel P. Berrange, Eduardo Habkost,
	Michael S. Tsirkin, aadam, QEMU Developers,
	Dr. David Alan Gilbert, Alex Williamson, Laine Stump, Amnon Ilan,
	parav

On Fri, 18 Oct 2019 at 21:22, Jens Freimann <jfreimann@redhat.com> wrote:
>
> This adds support for hiding a device to the qbus and qdev APIs.  The
> first user of this will be the virtio-net failover feature but the API
> introduced with this patch could be used to implement other features as
> well, for example hiding pci devices when a pci bus is powered off.

In what sense is a hidden device hidden? Is it hidden from
the guest (in what way) ? Is it hidden from the QMP/HMP monitor
commands? Is it hidden from QEMU functions that iterate through
the qbus, or that walk the QOM tree ? What does a hidden device
have to do to be successfully hidden ? Is it completely disconnected
from the rest of the simulation, or does it itself have to avoid
doing things like asserting IRQ lines ?

Expanding the DeviceClass doc comment might be a good place to answer
questions like the above and generally describe the 'hidden device'
mechanism.

>  };
>
> @@ -451,4 +457,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);

New globally visible functions should always have doc-comment
format documentation comments, please.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 01/11] qdev/qbus: add hidden device support
  2019-10-21 12:53   ` Peter Maydell
@ 2019-10-21 13:00     ` Jens Freimann
  0 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-21 13:00 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Krempa, Daniel P. Berrange, Eduardo Habkost,
	Michael S. Tsirkin, aadam, QEMU Developers,
	Dr. David Alan Gilbert, Alex Williamson, Laine Stump, Amnon Ilan,
	parav

On Mon, Oct 21, 2019 at 01:53:58PM +0100, Peter Maydell wrote:
>On Fri, 18 Oct 2019 at 21:22, Jens Freimann <jfreimann@redhat.com> wrote:
>>
>> This adds support for hiding a device to the qbus and qdev APIs.  The
>> first user of this will be the virtio-net failover feature but the API
>> introduced with this patch could be used to implement other features as
>> well, for example hiding pci devices when a pci bus is powered off.
>
>In what sense is a hidden device hidden? Is it hidden from
>the guest (in what way) ? Is it hidden from the QMP/HMP monitor
>commands? Is it hidden from QEMU functions that iterate through
>the qbus, or that walk the QOM tree ? What does a hidden device
>have to do to be successfully hidden ? Is it completely disconnected
>from the rest of the simulation, or does it itself have to avoid
>doing things like asserting IRQ lines ?
>
>Expanding the DeviceClass doc comment might be a good place to answer
>questions like the above and generally describe the 'hidden device'
>mechanism.

ok, I will add to the DeviceClass comment. 

>
>>  };
>>
>> @@ -451,4 +457,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);
>
>New globally visible functions should always have doc-comment
>format documentation comments, please.

Will add this too. Thanks for the review!

regards,
Jens 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 11/11] vfio: unplug failover primary device before migration
  2019-10-18 20:20 ` [PATCH 11/11] vfio: unplug failover primary device before migration Jens Freimann
@ 2019-10-21 13:45   ` Cornelia Huck
  2019-10-21 14:09     ` Jens Freimann
  2019-10-21 15:19   ` Alex Williamson
  1 sibling, 1 reply; 31+ messages in thread
From: Cornelia Huck @ 2019-10-21 13:45 UTC (permalink / raw)
  To: Jens Freimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

On Fri, 18 Oct 2019 22:20:40 +0200
Jens Freimann <jfreimann@redhat.com> wrote:

> As usual block all vfio-pci devices from being migrated, but make an
> exception for failover primary devices. This is achieved by setting
> unmigratable to 0 but also add a migration blocker for all vfio-pci
> devices except failover primary devices. These will be unplugged before
> migration happens by the migration handler of the corresponding
> virtio-net standby device.
> 
> Signed-off-by: Jens Freimann <jfreimann@redhat.com>
> ---
>  hw/vfio/pci.c | 31 +++++++++++++++++++++++++------
>  hw/vfio/pci.h |  1 +
>  2 files changed, 26 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 12fac39804..a15b83c6b6 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -40,6 +40,9 @@
>  #include "pci.h"
>  #include "trace.h"
>  #include "qapi/error.h"
> +#include "migration/blocker.h"
> +#include "qemu/option.h"
> +#include "qemu/option_int.h"
>  
>  #define TYPE_VFIO_PCI "vfio-pci"
>  #define PCI_VFIO(obj)    OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI)
> @@ -2712,12 +2715,26 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
>      int i, ret;
>      bool is_mdev;
>  
> +    if (!pdev->net_failover_pair_id) {
> +        error_setg(&vdev->migration_blocker,
> +                "VFIO device doesn't support migration");
> +        ret = migrate_add_blocker(vdev->migration_blocker, &err);
> +        if (err) {
> +            error_propagate(errp, err);
> +            goto error;

This looks wrong, you haven't set up vbasedev.name yet.

> +        }
> +    } else {
> +            pdev->qdev.allow_unplug_during_migration = true;
> +    }
> +
>      if (!vdev->vbasedev.sysfsdev) {
>          if (!(~vdev->host.domain || ~vdev->host.bus ||
>                ~vdev->host.slot || ~vdev->host.function)) {
>              error_setg(errp, "No provided host device");
>              error_append_hint(errp, "Use -device vfio-pci,host=DDDD:BB:DD.F "
>                                "or -device vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
> +            migrate_del_blocker(vdev->migration_blocker);
> +            error_free(vdev->migration_blocker);
>              return;
>          }
>          vdev->vbasedev.sysfsdev =
> @@ -2729,6 +2746,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
>      if (stat(vdev->vbasedev.sysfsdev, &st) < 0) {
>          error_setg_errno(errp, errno, "no such host device");
>          error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.sysfsdev);
> +        migrate_del_blocker(vdev->migration_blocker);
> +        error_free(vdev->migration_blocker);
>          return;
>      }

Might be a bit easier cleanup-wise if you set up the blocker resp.
allow unplug during migration only here. The only difference is that
you'll get a different error message when trying to set up a
non-failover device with invalid specs on a migratable-only setup.

>  
> @@ -3008,6 +3027,8 @@ out_teardown:
>      vfio_bars_exit(vdev);
>  error:
>      error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
> +    migrate_del_blocker(vdev->migration_blocker);
> +    error_free(vdev->migration_blocker);

Shouldn't you check whether migration_block has been set up, like in
the finalize routine?

>  }
>  
>  static void vfio_instance_finalize(Object *obj)
> @@ -3019,6 +3040,10 @@ static void vfio_instance_finalize(Object *obj)
>      vfio_bars_finalize(vdev);
>      g_free(vdev->emulated_config_bits);
>      g_free(vdev->rom);
> +    if (vdev->migration_blocker) {
> +        migrate_del_blocker(vdev->migration_blocker);
> +        error_free(vdev->migration_blocker);
> +    }
>      /*
>       * XXX Leaking igd_opregion is not an oversight, we can't remove the
>       * fw_cfg entry therefore leaking this allocation seems like the safest



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 11/11] vfio: unplug failover primary device before migration
  2019-10-21 13:45   ` Cornelia Huck
@ 2019-10-21 14:09     ` Jens Freimann
  0 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-21 14:09 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

On Mon, Oct 21, 2019 at 03:45:04PM +0200, Cornelia Huck wrote:
>On Fri, 18 Oct 2019 22:20:40 +0200
>Jens Freimann <jfreimann@redhat.com> wrote:
>
>> As usual block all vfio-pci devices from being migrated, but make an
>> exception for failover primary devices. This is achieved by setting
>> unmigratable to 0 but also add a migration blocker for all vfio-pci
>> devices except failover primary devices. These will be unplugged before
>> migration happens by the migration handler of the corresponding
>> virtio-net standby device.
>>
>> Signed-off-by: Jens Freimann <jfreimann@redhat.com>
>> ---
>>  hw/vfio/pci.c | 31 +++++++++++++++++++++++++------
>>  hw/vfio/pci.h |  1 +
>>  2 files changed, 26 insertions(+), 6 deletions(-)
>>
>> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
>> index 12fac39804..a15b83c6b6 100644
>> --- a/hw/vfio/pci.c
>> +++ b/hw/vfio/pci.c
>> @@ -40,6 +40,9 @@
>>  #include "pci.h"
>>  #include "trace.h"
>>  #include "qapi/error.h"
>> +#include "migration/blocker.h"
>> +#include "qemu/option.h"
>> +#include "qemu/option_int.h"
>>
>>  #define TYPE_VFIO_PCI "vfio-pci"
>>  #define PCI_VFIO(obj)    OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI)
>> @@ -2712,12 +2715,26 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
>>      int i, ret;
>>      bool is_mdev;
>>
>> +    if (!pdev->net_failover_pair_id) {
>> +        error_setg(&vdev->migration_blocker,
>> +                "VFIO device doesn't support migration");
>> +        ret = migrate_add_blocker(vdev->migration_blocker, &err);
>> +        if (err) {
>> +            error_propagate(errp, err);
>> +            goto error;
>
>This looks wrong, you haven't set up vbasedev.name yet.

You're right.

>> +        }
>> +    } else {
>> +            pdev->qdev.allow_unplug_during_migration = true;
>> +    }
>> +
>>      if (!vdev->vbasedev.sysfsdev) {
>>          if (!(~vdev->host.domain || ~vdev->host.bus ||
>>                ~vdev->host.slot || ~vdev->host.function)) {
>>              error_setg(errp, "No provided host device");
>>              error_append_hint(errp, "Use -device vfio-pci,host=DDDD:BB:DD.F "
>>                                "or -device vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
>> +            migrate_del_blocker(vdev->migration_blocker);
>> +            error_free(vdev->migration_blocker);
>>              return;
>>          }
>>          vdev->vbasedev.sysfsdev =
>> @@ -2729,6 +2746,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
>>      if (stat(vdev->vbasedev.sysfsdev, &st) < 0) {
>>          error_setg_errno(errp, errno, "no such host device");
>>          error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.sysfsdev);
>> +        migrate_del_blocker(vdev->migration_blocker);
>> +        error_free(vdev->migration_blocker);
>>          return;
>>      }
>
>Might be a bit easier cleanup-wise if you set up the blocker resp.
>allow unplug during migration only here. The only difference is that
>you'll get a different error message when trying to set up a
>non-failover device with invalid specs on a migratable-only setup.

Yes, so I moved it to this place now. This saves me cleanup up the
migration blocker in the above two cases. I don't jump to error if
adding the migration blocker failed, I just have to free the blocker
Error and can return.
>
>>
>> @@ -3008,6 +3027,8 @@ out_teardown:
>>      vfio_bars_exit(vdev);
>>  error:
>>      error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
>> +    migrate_del_blocker(vdev->migration_blocker);
>> +    error_free(vdev->migration_blocker);
>
>Shouldn't you check whether migration_block has been set up, like in
>the finalize routine?

yes, added the same check here.

Thanks Conny!

regards,
Jens 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v4 0/11] add failover feature for assigned network devices
  2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
                   ` (12 preceding siblings ...)
  2019-10-19 15:15 ` no-reply
@ 2019-10-21 14:18 ` Cornelia Huck
  13 siblings, 0 replies; 31+ messages in thread
From: Cornelia Huck @ 2019-10-21 14:18 UTC (permalink / raw)
  To: Jens Freimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	alex.williamson, laine, ailan, parav

On Fri, 18 Oct 2019 22:20:29 +0200
Jens Freimann <jfreimann@redhat.com> wrote:

> This is implementing the host side of the net_failover concept
> (https://www.kernel.org/doc/html/latest/networking/net_failover.html)

(...)

> Jens Freimann (10):
>   qdev/qbus: add hidden device support
>   pci: mark devices partially unplugged
>   pci: mark device having guest unplug request pending
>   qapi: add unplug primary event
>   qapi: add failover negotiated event
>   migration: allow unplug during migration for failover devices
>   migration: add new migration state wait-unplug
>   libqos: tolerate wait-unplug migration state
>   net/virtio: add failover support
>   vfio: unplug failover primary device before migration

I have looked over the patches I have not commented on directly as
well, and they look sane to me (i.e. I didn't spot any obvious
problems). Feel free to add my ack if you like.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/11] pci: add option for net failover
  2019-10-18 20:20 ` [PATCH 02/11] pci: add option for net failover Jens Freimann
@ 2019-10-21 14:58   ` Alex Williamson
  2019-10-21 18:45     ` Jens Freimann
  0 siblings, 1 reply; 31+ messages in thread
From: Alex Williamson @ 2019-10-21 14:58 UTC (permalink / raw)
  To: Jens Freimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	laine, ailan, parav

On Fri, 18 Oct 2019 22:20:31 +0200
Jens Freimann <jfreimann@redhat.com> wrote:

> This patch adds a net_failover_pair_id property to PCIDev which is
> used to link the primary device in a failover pair (the PCI dev) to
> a standby (a virtio-net-pci) device.
> 
> It only supports ethernet devices. Also currently it only supports
> PCIe devices. QEMU will exit with an error message otherwise.

Doesn't the PCIe device also need to be hotpluggable?  We can have PCIe
devices attached to the root bus where we don't currently support
hotplug.  Thanks,

Alex
 
> Signed-off-by: Jens Freimann <jfreimann@redhat.com>
> ---
>  hw/pci/pci.c         | 17 +++++++++++++++++
>  include/hw/pci/pci.h |  3 +++
>  2 files changed, 20 insertions(+)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index aa05c2b9b2..fa9b5219f8 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -75,6 +75,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_STRING("net_failover_pair_id", PCIDevice,
> +            net_failover_pair_id),
>      DEFINE_PROP_END_OF_LIST()
>  };
>  
> @@ -2077,6 +2079,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
>      ObjectClass *klass = OBJECT_CLASS(pc);
>      Error *local_err = NULL;
>      bool is_default_rom;
> +    uint16_t class_id;
>  
>      /* initialize cap_present for pci_is_express() and pci_config_size(),
>       * Note that hybrid PCIs are not set automatically and need to manage
> @@ -2101,6 +2104,20 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
>          }
>      }
>  
> +    if (pci_dev->net_failover_pair_id) {
> +        if (!pci_is_express(pci_dev)) {
> +            error_setg(errp, "failover device is not a PCIExpress device");
> +            error_propagate(errp, local_err);
> +            return;
> +        }
> +        class_id = pci_get_word(pci_dev->config + PCI_CLASS_DEVICE);
> +        if (class_id != PCI_CLASS_NETWORK_ETHERNET) {
> +            error_setg(errp, "failover device is not an Ethernet device");
> +            error_propagate(errp, local_err);
> +            return;
> +        }
> +    }
> +
>      /* rom loading */
>      is_default_rom = false;
>      if (pci_dev->romfile == NULL && pc->romfile != NULL) {
> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> index f3f0ffd5fb..def5435685 100644
> --- a/include/hw/pci/pci.h
> +++ b/include/hw/pci/pci.h
> @@ -352,6 +352,9 @@ struct PCIDevice {
>      MSIVectorUseNotifier msix_vector_use_notifier;
>      MSIVectorReleaseNotifier msix_vector_release_notifier;
>      MSIVectorPollNotifier msix_vector_poll_notifier;
> +
> +    /* ID of standby device in net_failover pair */
> +    char *net_failover_pair_id;
>  };
>  
>  void pci_register_bar(PCIDevice *pci_dev, int region_num,



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 11/11] vfio: unplug failover primary device before migration
  2019-10-18 20:20 ` [PATCH 11/11] vfio: unplug failover primary device before migration Jens Freimann
  2019-10-21 13:45   ` Cornelia Huck
@ 2019-10-21 15:19   ` Alex Williamson
  2019-10-21 19:16     ` Jens Freimann
  1 sibling, 1 reply; 31+ messages in thread
From: Alex Williamson @ 2019-10-21 15:19 UTC (permalink / raw)
  To: Jens Freimann, parav
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	laine, ailan

On Fri, 18 Oct 2019 22:20:40 +0200
Jens Freimann <jfreimann@redhat.com> wrote:

> As usual block all vfio-pci devices from being migrated, but make an
> exception for failover primary devices. This is achieved by setting
> unmigratable to 0 but also add a migration blocker for all vfio-pci
> devices except failover primary devices. These will be unplugged before
> migration happens by the migration handler of the corresponding
> virtio-net standby device.
> 
> Signed-off-by: Jens Freimann <jfreimann@redhat.com>
> ---
>  hw/vfio/pci.c | 31 +++++++++++++++++++++++++------
>  hw/vfio/pci.h |  1 +
>  2 files changed, 26 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 12fac39804..a15b83c6b6 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -40,6 +40,9 @@
>  #include "pci.h"
>  #include "trace.h"
>  #include "qapi/error.h"
> +#include "migration/blocker.h"
> +#include "qemu/option.h"
> +#include "qemu/option_int.h"
>  
>  #define TYPE_VFIO_PCI "vfio-pci"
>  #define PCI_VFIO(obj)    OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI)
> @@ -2712,12 +2715,26 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
>      int i, ret;
>      bool is_mdev;
>  
> +    if (!pdev->net_failover_pair_id) {
> +        error_setg(&vdev->migration_blocker,
> +                "VFIO device doesn't support migration");
> +        ret = migrate_add_blocker(vdev->migration_blocker, &err);
> +        if (err) {
> +            error_propagate(errp, err);
> +            goto error;
> +        }
> +    } else {
> +            pdev->qdev.allow_unplug_during_migration = true;

Why is this unique to vfio-pci, shouldn't any device set as the primary
for a failover allow unplug during migration, and therefore should it
be done in the core code rather than device driver?  With the
net_failover_pair_id set in PCIDevice, I should be able to test with an
e1000e NIC as primary, but this suggests they wouldn't be handled
identically elsewhere.  Thanks,

Alex

> +    }
> +
>      if (!vdev->vbasedev.sysfsdev) {
>          if (!(~vdev->host.domain || ~vdev->host.bus ||
>                ~vdev->host.slot || ~vdev->host.function)) {
>              error_setg(errp, "No provided host device");
>              error_append_hint(errp, "Use -device vfio-pci,host=DDDD:BB:DD.F "
>                                "or -device vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
> +            migrate_del_blocker(vdev->migration_blocker);
> +            error_free(vdev->migration_blocker);
>              return;
>          }
>          vdev->vbasedev.sysfsdev =
> @@ -2729,6 +2746,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
>      if (stat(vdev->vbasedev.sysfsdev, &st) < 0) {
>          error_setg_errno(errp, errno, "no such host device");
>          error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.sysfsdev);
> +        migrate_del_blocker(vdev->migration_blocker);
> +        error_free(vdev->migration_blocker);
>          return;
>      }
>  
> @@ -3008,6 +3027,8 @@ out_teardown:
>      vfio_bars_exit(vdev);
>  error:
>      error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
> +    migrate_del_blocker(vdev->migration_blocker);
> +    error_free(vdev->migration_blocker);
>  }
>  
>  static void vfio_instance_finalize(Object *obj)
> @@ -3019,6 +3040,10 @@ static void vfio_instance_finalize(Object *obj)
>      vfio_bars_finalize(vdev);
>      g_free(vdev->emulated_config_bits);
>      g_free(vdev->rom);
> +    if (vdev->migration_blocker) {
> +        migrate_del_blocker(vdev->migration_blocker);
> +        error_free(vdev->migration_blocker);
> +    }
>      /*
>       * XXX Leaking igd_opregion is not an oversight, we can't remove the
>       * fw_cfg entry therefore leaking this allocation seems like the safest
> @@ -3151,11 +3176,6 @@ static Property vfio_pci_dev_properties[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static const VMStateDescription vfio_pci_vmstate = {
> -    .name = "vfio-pci",
> -    .unmigratable = 1,
> -};
> -
>  static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -3163,7 +3183,6 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = vfio_pci_reset;
>      dc->props = vfio_pci_dev_properties;
> -    dc->vmsd = &vfio_pci_vmstate;
>      dc->desc = "VFIO-based PCI device assignment";
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>      pdc->realize = vfio_realize;
> diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
> index 834a90d646..b329d50338 100644
> --- a/hw/vfio/pci.h
> +++ b/hw/vfio/pci.h
> @@ -168,6 +168,7 @@ typedef struct VFIOPCIDevice {
>      bool no_vfio_ioeventfd;
>      bool enable_ramfb;
>      VFIODisplay *dpy;
> +    Error *migration_blocker;
>  } VFIOPCIDevice;
>  
>  uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/11] pci: add option for net failover
  2019-10-21 14:58   ` Alex Williamson
@ 2019-10-21 18:45     ` Jens Freimann
  2019-10-21 19:01       ` Alex Williamson
  0 siblings, 1 reply; 31+ messages in thread
From: Jens Freimann @ 2019-10-21 18:45 UTC (permalink / raw)
  To: Alex Williamson
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	laine, ailan, parav

On Mon, Oct 21, 2019 at 08:58:23AM -0600, Alex Williamson wrote:
>On Fri, 18 Oct 2019 22:20:31 +0200
>Jens Freimann <jfreimann@redhat.com> wrote:
>
>> This patch adds a net_failover_pair_id property to PCIDev which is
>> used to link the primary device in a failover pair (the PCI dev) to
>> a standby (a virtio-net-pci) device.
>>
>> It only supports ethernet devices. Also currently it only supports
>> PCIe devices. QEMU will exit with an error message otherwise.
>
>Doesn't the PCIe device also need to be hotpluggable?  We can have PCIe
>devices attached to the root bus where we don't currently support
>hotplug.  Thanks,

How do I recognize such a device? hotpluggable in DeviceClass?

regards,
Jens 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/11] pci: add option for net failover
  2019-10-21 18:45     ` Jens Freimann
@ 2019-10-21 19:01       ` Alex Williamson
  2019-10-21 20:28         ` Jens Freimann
  0 siblings, 1 reply; 31+ messages in thread
From: Alex Williamson @ 2019-10-21 19:01 UTC (permalink / raw)
  To: Jens Freimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	laine, ailan, parav

On Mon, 21 Oct 2019 20:45:46 +0200
Jens Freimann <jfreimann@redhat.com> wrote:

> On Mon, Oct 21, 2019 at 08:58:23AM -0600, Alex Williamson wrote:
> >On Fri, 18 Oct 2019 22:20:31 +0200
> >Jens Freimann <jfreimann@redhat.com> wrote:
> >  
> >> This patch adds a net_failover_pair_id property to PCIDev which is
> >> used to link the primary device in a failover pair (the PCI dev) to
> >> a standby (a virtio-net-pci) device.
> >>
> >> It only supports ethernet devices. Also currently it only supports
> >> PCIe devices. QEMU will exit with an error message otherwise.  
> >
> >Doesn't the PCIe device also need to be hotpluggable?  We can have PCIe
> >devices attached to the root bus where we don't currently support
> >hotplug.  Thanks,  
> 
> How do I recognize such a device? hotpluggable in DeviceClass?

I wouldn't expect it to be a device property, it's more of a function
of whether the bus that it's attached to supports hotplug, so probably
something related to the bus controller.  Thanks,

Alex



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 11/11] vfio: unplug failover primary device before migration
  2019-10-21 15:19   ` Alex Williamson
@ 2019-10-21 19:16     ` Jens Freimann
  0 siblings, 0 replies; 31+ messages in thread
From: Jens Freimann @ 2019-10-21 19:16 UTC (permalink / raw)
  To: Alex Williamson
  Cc: pkrempa, berrange, parav, mst, aadam, qemu-devel, dgilbert,
	laine, ailan, ehabkost

On Mon, Oct 21, 2019 at 09:19:20AM -0600, Alex Williamson wrote:
>On Fri, 18 Oct 2019 22:20:40 +0200
>Jens Freimann <jfreimann@redhat.com> wrote:
[...]
>> +    if (!pdev->net_failover_pair_id) {
>> +        error_setg(&vdev->migration_blocker,
>> +                "VFIO device doesn't support migration");
>> +        ret = migrate_add_blocker(vdev->migration_blocker, &err);
>> +        if (err) {
>> +            error_propagate(errp, err);
>> +            goto error;
>> +        }
>> +    } else {
>> +            pdev->qdev.allow_unplug_during_migration = true;
>
>Why is this unique to vfio-pci, shouldn't any device set as the primary
>for a failover allow unplug during migration, and therefore should it
>be done in the core code rather than device driver?  With the
>net_failover_pair_id set in PCIDevice, I should be able to test with an
>e1000e NIC as primary, but this suggests they wouldn't be handled
>identically elsewhere.  Thanks,

I assume you're talking about pci core code not qdev core. Failover is
pci specific at this time (only the part to hide devices is more
generic and is in qdev code). I can set the flag to allow migration in
pci_qdev_realize().

regards,
Jens 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/11] pci: add option for net failover
  2019-10-21 19:01       ` Alex Williamson
@ 2019-10-21 20:28         ` Jens Freimann
  2019-10-21 20:48           ` Alex Williamson
  0 siblings, 1 reply; 31+ messages in thread
From: Jens Freimann @ 2019-10-21 20:28 UTC (permalink / raw)
  To: Alex Williamson
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	laine, ailan, parav

On Mon, Oct 21, 2019 at 01:01:22PM -0600, Alex Williamson wrote:
>On Mon, 21 Oct 2019 20:45:46 +0200
>Jens Freimann <jfreimann@redhat.com> wrote:
>
>> On Mon, Oct 21, 2019 at 08:58:23AM -0600, Alex Williamson wrote:
>> >On Fri, 18 Oct 2019 22:20:31 +0200
>> >Jens Freimann <jfreimann@redhat.com> wrote:
>> >
>> >> This patch adds a net_failover_pair_id property to PCIDev which is
>> >> used to link the primary device in a failover pair (the PCI dev) to
>> >> a standby (a virtio-net-pci) device.
>> >>
>> >> It only supports ethernet devices. Also currently it only supports
>> >> PCIe devices. QEMU will exit with an error message otherwise.
>> >
>> >Doesn't the PCIe device also need to be hotpluggable?  We can have PCIe
>> >devices attached to the root bus where we don't currently support
>> >hotplug.  Thanks,
>>
>> How do I recognize such a device? hotpluggable in DeviceClass?
>
>I wouldn't expect it to be a device property, it's more of a function
>of whether the bus that it's attached to supports hotplug, so probably
>something related to the bus controller.  Thanks,

IIUC this is checked for in qdev_device_add() by this:

  if (qdev_hotplug && bus && !qbus_is_hotpluggable(bus)) {
        error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name);
        return NULL;
  }

So qemu will fail with 'Bus pcie.0 does not allow hotplug' when we try 
to hotplug the device. I tried a primary with bus=pcie.0 and it aborted.
Aborting qemu is not nice so I'll make it print a error message
QERR_BUS_NO_HOTPLUG instead but let it continue. This will be
a change in the virtio-net patch, not in this one. 

regards,
Jens 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/11] pci: add option for net failover
  2019-10-21 20:28         ` Jens Freimann
@ 2019-10-21 20:48           ` Alex Williamson
  0 siblings, 0 replies; 31+ messages in thread
From: Alex Williamson @ 2019-10-21 20:48 UTC (permalink / raw)
  To: Jens Freimann
  Cc: pkrempa, berrange, ehabkost, mst, aadam, qemu-devel, dgilbert,
	laine, ailan, parav

On Mon, 21 Oct 2019 22:28:57 +0200
Jens Freimann <jfreimann@redhat.com> wrote:

> On Mon, Oct 21, 2019 at 01:01:22PM -0600, Alex Williamson wrote:
> >On Mon, 21 Oct 2019 20:45:46 +0200
> >Jens Freimann <jfreimann@redhat.com> wrote:
> >  
> >> On Mon, Oct 21, 2019 at 08:58:23AM -0600, Alex Williamson wrote:  
> >> >On Fri, 18 Oct 2019 22:20:31 +0200
> >> >Jens Freimann <jfreimann@redhat.com> wrote:
> >> >  
> >> >> This patch adds a net_failover_pair_id property to PCIDev which is
> >> >> used to link the primary device in a failover pair (the PCI dev) to
> >> >> a standby (a virtio-net-pci) device.
> >> >>
> >> >> It only supports ethernet devices. Also currently it only supports
> >> >> PCIe devices. QEMU will exit with an error message otherwise.  
> >> >
> >> >Doesn't the PCIe device also need to be hotpluggable?  We can have PCIe
> >> >devices attached to the root bus where we don't currently support
> >> >hotplug.  Thanks,  
> >>
> >> How do I recognize such a device? hotpluggable in DeviceClass?  
> >
> >I wouldn't expect it to be a device property, it's more of a function
> >of whether the bus that it's attached to supports hotplug, so probably
> >something related to the bus controller.  Thanks,  
> 
> IIUC this is checked for in qdev_device_add() by this:
> 
>   if (qdev_hotplug && bus && !qbus_is_hotpluggable(bus)) {
>         error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name);
>         return NULL;
>   }
> 
> So qemu will fail with 'Bus pcie.0 does not allow hotplug' when we try 
> to hotplug the device. I tried a primary with bus=pcie.0 and it aborted.
> Aborting qemu is not nice so I'll make it print a error message
> QERR_BUS_NO_HOTPLUG instead but let it continue. This will be
> a change in the virtio-net patch, not in this one. 

qdev_hotplug is only set to true after qdev_machine_creation_done(), so
if we start a VM with cold-plugged primary and failover, wouldn't the
user only learn the configuration is invalid at the time they try to
use it?  I agree that the above should prevent a device from being
hot-added to the bus, but I don't think that's our starting position,
is it?  Thanks,

Alex



^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2019-10-21 20:49 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-18 20:20 [PATCH v4 0/11] add failover feature for assigned network devices Jens Freimann
2019-10-18 20:20 ` [PATCH 01/11] qdev/qbus: add hidden device support Jens Freimann
2019-10-21 12:44   ` Cornelia Huck
2019-10-21 12:52     ` Jens Freimann
2019-10-21 12:53   ` Peter Maydell
2019-10-21 13:00     ` Jens Freimann
2019-10-18 20:20 ` [PATCH 02/11] pci: add option for net failover Jens Freimann
2019-10-21 14:58   ` Alex Williamson
2019-10-21 18:45     ` Jens Freimann
2019-10-21 19:01       ` Alex Williamson
2019-10-21 20:28         ` Jens Freimann
2019-10-21 20:48           ` Alex Williamson
2019-10-18 20:20 ` [PATCH 03/11] pci: mark devices partially unplugged Jens Freimann
2019-10-18 20:20 ` [PATCH 04/11] pci: mark device having guest unplug request pending Jens Freimann
2019-10-18 20:20 ` [PATCH 05/11] qapi: add unplug primary event Jens Freimann
2019-10-18 20:28   ` Eric Blake
2019-10-21  7:23     ` Jens Freimann
2019-10-18 20:20 ` [PATCH 06/11] qapi: add failover negotiated event Jens Freimann
2019-10-18 20:20 ` [PATCH 07/11] migration: allow unplug during migration for failover devices Jens Freimann
2019-10-18 20:20 ` [PATCH 08/11] migration: add new migration state wait-unplug Jens Freimann
2019-10-18 20:20 ` [PATCH 09/11] libqos: tolerate wait-unplug migration state Jens Freimann
2019-10-18 20:20 ` [PATCH 10/11] net/virtio: add failover support Jens Freimann
2019-10-18 20:20 ` [PATCH 11/11] vfio: unplug failover primary device before migration Jens Freimann
2019-10-21 13:45   ` Cornelia Huck
2019-10-21 14:09     ` Jens Freimann
2019-10-21 15:19   ` Alex Williamson
2019-10-21 19:16     ` Jens Freimann
2019-10-19 15:12 ` [PATCH v4 0/11] add failover feature for assigned network devices no-reply
2019-10-21  7:30   ` Jens Freimann
2019-10-19 15:15 ` no-reply
2019-10-21 14:18 ` Cornelia Huck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.