qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

virtio: features, cleanups

virtio net failover
rcu cleanup

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Tue 29 Oct 2019 22:58:14 GMT
# gpg: using RSA key 281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67
# Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream:
virtio: Use auto rcu_read macros
virtio_net: use RCU_READ_LOCK_GUARD
virtio/vhost: Use auto_rcu_read macros
vfio: unplug failover primary device before migration
net/virtio: add failover support
libqos: tolerate wait-unplug migration state
migration: add new migration state wait-unplug
migration: allow unplug during migration for failover devices
qapi: add failover negotiated event
qapi: add unplug primary event
pci: mark device having guest unplug request pending
pci: mark devices partially unplugged
pci: add option for net failover
qdev/qbus: add hidden device support

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+673 -65
+1
MAINTAINERS
··· 1435 1435 F: hw/net/ 1436 1436 F: include/hw/net/ 1437 1437 F: tests/virtio-net-test.c 1438 + F: docs/virtio-net-failover.rst 1438 1439 T: git https://github.com/jasowang/qemu.git net 1439 1440 1440 1441 Parallel NOR Flash devices
+68
docs/virtio-net-failover.rst
··· 1 + ======================== 2 + QEMU virtio-net standby (net_failover) 3 + ======================== 4 + 5 + This document explains the setup and usage of virtio-net standby feature which 6 + is used to create a net_failover pair of devices. 7 + 8 + The general idea is that we have a pair of devices, a (vfio-)pci and a 9 + virtio-net device. Before migration the vfio device is unplugged and data flows 10 + through the virtio-net device, on the target side another vfio-pci device is 11 + plugged in to take over the data-path. In the guest the net_failover kernel 12 + module will pair net devices with the same MAC address. 13 + 14 + The two devices are called primary and standby device. The fast hardware based 15 + networking device is called the primary device and the virtio-net device is the 16 + standby device. 17 + 18 + Restrictions 19 + ------------ 20 + 21 + Currently only PCIe devices are allowed as primary devices, this restriction 22 + can be lifted in the future with enhanced QEMU support. Also, only networking 23 + devices are allowed as primary device. The user needs to ensure that primary 24 + and standby devices are not plugged into the same PCIe slot. 25 + 26 + Usecase 27 + ------- 28 + 29 + Virtio-net standby allows easy migration while using a passed-through fast 30 + networking device by falling back to a virtio-net device for the duration of 31 + the migration. It is like a simple version of a bond, the difference is that it 32 + requires no configuration in the guest. When a guest is live-migrated to 33 + another host QEMU will unplug the primary device via the PCIe based hotplug 34 + handler and traffic will go through the virtio-net device. On the target 35 + system the primary device will be automatically plugged back and the 36 + net_failover module registers it again as the primary device. 37 + 38 + Usage 39 + ----- 40 + 41 + The primary device can be hotplugged or be part of the startup configuration 42 + 43 + -device virtio-net-pci,netdev=hostnet1,id=net1,mac=52:54:00:6f:55:cc, \ 44 + bus=root2,failover=on 45 + 46 + With the parameter failover=on the VIRTIO_NET_F_STANDBY feature will be enabled. 47 + 48 + -device vfio-pci,host=5e:00.2,id=hostdev0,bus=root1,failover_pair_id=net1 49 + 50 + failover_pair_id references the id of the virtio-net standby device. This 51 + is only for pairing the devices within QEMU. The guest kernel module 52 + net_failover will match devices with identical MAC addresses. 53 + 54 + Hotplug 55 + ------- 56 + 57 + Both primary and standby device can be hotplugged via the QEMU monitor. Note 58 + that if the virtio-net device is plugged first a warning will be issued that it 59 + couldn't find the primary device. 60 + 61 + Migration 62 + --------- 63 + 64 + A new migration state wait-unplug was added for this feature. If failover primary 65 + devices are present in the configuration, migration will go into this state. 66 + It will wait until the device unplug is completed in the guest and then move into 67 + active state. On the target system the primary devices will be automatically hotplugged 68 + when the feature bit was negotiated for the virtio-net standby device.
+25
hw/core/qdev.c
··· 212 212 QTAILQ_REMOVE(&device_listeners, listener, link); 213 213 } 214 214 215 + bool qdev_should_hide_device(QemuOpts *opts) 216 + { 217 + int rc = -1; 218 + DeviceListener *listener; 219 + 220 + QTAILQ_FOREACH(listener, &device_listeners, link) { 221 + if (listener->should_be_hidden) { 222 + /* 223 + * should_be_hidden_will return 224 + * 1 if device matches opts and it should be hidden 225 + * 0 if device matches opts and should not be hidden 226 + * -1 if device doesn't match ops 227 + */ 228 + rc = listener->should_be_hidden(listener, opts); 229 + } 230 + 231 + if (rc > 0) { 232 + break; 233 + } 234 + } 235 + 236 + return rc > 0; 237 + } 238 + 215 239 void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, 216 240 int required_for_version) 217 241 { ··· 972 996 973 997 dev->instance_id_alias = -1; 974 998 dev->realized = false; 999 + dev->allow_unplug_during_migration = false; 975 1000 976 1001 object_property_add_bool(obj, "realized", 977 1002 device_get_realized, device_set_realized, NULL);
+304 -5
hw/net/virtio-net.c
··· 12 12 */ 13 13 14 14 #include "qemu/osdep.h" 15 + #include "qemu/atomic.h" 15 16 #include "qemu/iov.h" 16 17 #include "qemu/main-loop.h" 17 18 #include "qemu/module.h" ··· 21 22 #include "net/tap.h" 22 23 #include "qemu/error-report.h" 23 24 #include "qemu/timer.h" 25 + #include "qemu/option.h" 26 + #include "qemu/option_int.h" 27 + #include "qemu/config-file.h" 28 + #include "qapi/qmp/qdict.h" 24 29 #include "hw/virtio/virtio-net.h" 25 30 #include "net/vhost_net.h" 26 31 #include "net/announce.h" ··· 28 33 #include "qapi/error.h" 29 34 #include "qapi/qapi-events-net.h" 30 35 #include "hw/qdev-properties.h" 36 + #include "qapi/qapi-types-migration.h" 37 + #include "qapi/qapi-events-migration.h" 31 38 #include "hw/virtio/virtio-access.h" 32 39 #include "migration/misc.h" 33 40 #include "standard-headers/linux/ethtool.h" 34 41 #include "sysemu/sysemu.h" 35 42 #include "trace.h" 43 + #include "monitor/qdev.h" 44 + #include "hw/pci/pci.h" 36 45 37 46 #define VIRTIO_NET_VM_VERSION 11 38 47 ··· 746 755 return virtio_net_guest_offloads_by_features(vdev->guest_features); 747 756 } 748 757 758 + static void failover_add_primary(VirtIONet *n, Error **errp) 759 + { 760 + Error *err = NULL; 761 + 762 + n->primary_device_opts = qemu_opts_find(qemu_find_opts("device"), 763 + n->primary_device_id); 764 + if (n->primary_device_opts) { 765 + n->primary_dev = qdev_device_add(n->primary_device_opts, &err); 766 + if (err) { 767 + qemu_opts_del(n->primary_device_opts); 768 + } 769 + if (n->primary_dev) { 770 + n->primary_bus = n->primary_dev->parent_bus; 771 + if (err) { 772 + qdev_unplug(n->primary_dev, &err); 773 + qdev_set_id(n->primary_dev, ""); 774 + 775 + } 776 + } 777 + } else { 778 + error_setg(errp, "Primary device not found"); 779 + error_append_hint(errp, "Virtio-net failover will not work. Make " 780 + "sure primary device has parameter" 781 + " failover_pair_id=<virtio-net-id>\n"); 782 + } 783 + if (err) { 784 + error_propagate(errp, err); 785 + } 786 + } 787 + 788 + static int is_my_primary(void *opaque, QemuOpts *opts, Error **errp) 789 + { 790 + VirtIONet *n = opaque; 791 + int ret = 0; 792 + 793 + const char *standby_id = qemu_opt_get(opts, "failover_pair_id"); 794 + 795 + if (standby_id != NULL && (g_strcmp0(standby_id, n->netclient_name) == 0)) { 796 + n->primary_device_id = g_strdup(opts->id); 797 + ret = 1; 798 + } 799 + 800 + return ret; 801 + } 802 + 803 + static DeviceState *virtio_net_find_primary(VirtIONet *n, Error **errp) 804 + { 805 + DeviceState *dev = NULL; 806 + Error *err = NULL; 807 + 808 + if (qemu_opts_foreach(qemu_find_opts("device"), 809 + is_my_primary, n, &err)) { 810 + if (err) { 811 + error_propagate(errp, err); 812 + return NULL; 813 + } 814 + if (n->primary_device_id) { 815 + dev = qdev_find_recursive(sysbus_get_default(), 816 + n->primary_device_id); 817 + } else { 818 + error_setg(errp, "Primary device id not found"); 819 + return NULL; 820 + } 821 + } 822 + return dev; 823 + } 824 + 825 + 826 + 827 + static DeviceState *virtio_connect_failover_devices(VirtIONet *n, 828 + DeviceState *dev, 829 + Error **errp) 830 + { 831 + DeviceState *prim_dev = NULL; 832 + Error *err = NULL; 833 + 834 + prim_dev = virtio_net_find_primary(n, &err); 835 + if (prim_dev) { 836 + n->primary_device_id = g_strdup(prim_dev->id); 837 + n->primary_device_opts = prim_dev->opts; 838 + } else { 839 + if (err) { 840 + error_propagate(errp, err); 841 + } 842 + } 843 + 844 + return prim_dev; 845 + } 846 + 749 847 static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) 750 848 { 751 849 VirtIONet *n = VIRTIO_NET(vdev); 850 + Error *err = NULL; 752 851 int i; 753 852 754 853 if (n->mtu_bypass_backend && ··· 789 888 memset(n->vlans, 0, MAX_VLAN >> 3); 790 889 } else { 791 890 memset(n->vlans, 0xff, MAX_VLAN >> 3); 891 + } 892 + 893 + if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { 894 + qapi_event_send_failover_negotiated(n->netclient_name); 895 + atomic_set(&n->primary_should_be_hidden, false); 896 + failover_add_primary(n, &err); 897 + if (err) { 898 + n->primary_dev = virtio_connect_failover_devices(n, n->qdev, &err); 899 + if (err) { 900 + goto out_err; 901 + } 902 + failover_add_primary(n, &err); 903 + if (err) { 904 + goto out_err; 905 + } 906 + } 907 + } 908 + return; 909 + 910 + out_err: 911 + if (err) { 912 + warn_report_err(err); 792 913 } 793 914 } 794 915 ··· 1369 1490 static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf, 1370 1491 size_t size) 1371 1492 { 1372 - ssize_t r; 1493 + RCU_READ_LOCK_GUARD(); 1373 1494 1374 - rcu_read_lock(); 1375 - r = virtio_net_receive_rcu(nc, buf, size); 1376 - rcu_read_unlock(); 1377 - return r; 1495 + return virtio_net_receive_rcu(nc, buf, size); 1378 1496 } 1379 1497 1380 1498 static void virtio_net_rsc_extract_unit4(VirtioNetRscChain *chain, ··· 2650 2768 n->netclient_type = g_strdup(type); 2651 2769 } 2652 2770 2771 + static bool failover_unplug_primary(VirtIONet *n) 2772 + { 2773 + HotplugHandler *hotplug_ctrl; 2774 + PCIDevice *pci_dev; 2775 + Error *err = NULL; 2776 + 2777 + hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev); 2778 + if (hotplug_ctrl) { 2779 + pci_dev = PCI_DEVICE(n->primary_dev); 2780 + pci_dev->partially_hotplugged = true; 2781 + hotplug_handler_unplug_request(hotplug_ctrl, n->primary_dev, &err); 2782 + if (err) { 2783 + error_report_err(err); 2784 + return false; 2785 + } 2786 + } else { 2787 + return false; 2788 + } 2789 + return true; 2790 + } 2791 + 2792 + static bool failover_replug_primary(VirtIONet *n, Error **errp) 2793 + { 2794 + HotplugHandler *hotplug_ctrl; 2795 + PCIDevice *pdev = PCI_DEVICE(n->primary_dev); 2796 + 2797 + if (!pdev->partially_hotplugged) { 2798 + return true; 2799 + } 2800 + if (!n->primary_device_opts) { 2801 + n->primary_device_opts = qemu_opts_from_qdict( 2802 + qemu_find_opts("device"), 2803 + n->primary_device_dict, errp); 2804 + } 2805 + if (n->primary_device_opts) { 2806 + if (n->primary_dev) { 2807 + n->primary_bus = n->primary_dev->parent_bus; 2808 + } 2809 + qdev_set_parent_bus(n->primary_dev, n->primary_bus); 2810 + n->primary_should_be_hidden = false; 2811 + qemu_opt_set_bool(n->primary_device_opts, 2812 + "partially_hotplugged", true, errp); 2813 + hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev); 2814 + if (hotplug_ctrl) { 2815 + hotplug_handler_pre_plug(hotplug_ctrl, n->primary_dev, errp); 2816 + hotplug_handler_plug(hotplug_ctrl, n->primary_dev, errp); 2817 + } 2818 + if (!n->primary_dev) { 2819 + error_setg(errp, "virtio_net: couldn't find primary device"); 2820 + } 2821 + } 2822 + return *errp != NULL; 2823 + } 2824 + 2825 + static void virtio_net_handle_migration_primary(VirtIONet *n, 2826 + MigrationState *s) 2827 + { 2828 + bool should_be_hidden; 2829 + Error *err = NULL; 2830 + 2831 + should_be_hidden = atomic_read(&n->primary_should_be_hidden); 2832 + 2833 + if (!n->primary_dev) { 2834 + n->primary_dev = virtio_connect_failover_devices(n, n->qdev, &err); 2835 + if (!n->primary_dev) { 2836 + return; 2837 + } 2838 + } 2839 + 2840 + if (migration_in_setup(s) && !should_be_hidden && 2841 + n->primary_dev) { 2842 + if (failover_unplug_primary(n)) { 2843 + vmstate_unregister(n->primary_dev, qdev_get_vmsd(n->primary_dev), 2844 + n->primary_dev); 2845 + qapi_event_send_unplug_primary(n->primary_device_id); 2846 + atomic_set(&n->primary_should_be_hidden, true); 2847 + } else { 2848 + warn_report("couldn't unplug primary device"); 2849 + } 2850 + } else if (migration_has_failed(s)) { 2851 + /* We already unplugged the device let's plugged it back */ 2852 + if (!failover_replug_primary(n, &err)) { 2853 + if (err) { 2854 + error_report_err(err); 2855 + } 2856 + } 2857 + } 2858 + } 2859 + 2860 + static void virtio_net_migration_state_notifier(Notifier *notifier, void *data) 2861 + { 2862 + MigrationState *s = data; 2863 + VirtIONet *n = container_of(notifier, VirtIONet, migration_state); 2864 + virtio_net_handle_migration_primary(n, s); 2865 + } 2866 + 2867 + static int virtio_net_primary_should_be_hidden(DeviceListener *listener, 2868 + QemuOpts *device_opts) 2869 + { 2870 + VirtIONet *n = container_of(listener, VirtIONet, primary_listener); 2871 + bool match_found; 2872 + bool hide; 2873 + 2874 + n->primary_device_dict = qemu_opts_to_qdict(device_opts, 2875 + n->primary_device_dict); 2876 + if (n->primary_device_dict) { 2877 + g_free(n->standby_id); 2878 + n->standby_id = g_strdup(qdict_get_try_str(n->primary_device_dict, 2879 + "failover_pair_id")); 2880 + } 2881 + if (device_opts && g_strcmp0(n->standby_id, n->netclient_name) == 0) { 2882 + match_found = true; 2883 + } else { 2884 + match_found = false; 2885 + hide = false; 2886 + g_free(n->standby_id); 2887 + n->primary_device_dict = NULL; 2888 + goto out; 2889 + } 2890 + 2891 + n->primary_device_opts = device_opts; 2892 + 2893 + /* primary_should_be_hidden is set during feature negotiation */ 2894 + hide = atomic_read(&n->primary_should_be_hidden); 2895 + 2896 + if (n->primary_device_dict) { 2897 + g_free(n->primary_device_id); 2898 + n->primary_device_id = g_strdup(qdict_get_try_str( 2899 + n->primary_device_dict, "id")); 2900 + if (!n->primary_device_id) { 2901 + warn_report("primary_device_id not set"); 2902 + } 2903 + } 2904 + 2905 + out: 2906 + if (match_found && hide) { 2907 + return 1; 2908 + } else if (match_found && !hide) { 2909 + return 0; 2910 + } else { 2911 + return -1; 2912 + } 2913 + } 2914 + 2653 2915 static void virtio_net_device_realize(DeviceState *dev, Error **errp) 2654 2916 { 2655 2917 VirtIODevice *vdev = VIRTIO_DEVICE(dev); ··· 2678 2940 error_setg(errp, "'speed' must be between 0 and INT_MAX"); 2679 2941 } else if (n->net_conf.speed >= 0) { 2680 2942 n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX); 2943 + } 2944 + 2945 + if (n->failover) { 2946 + n->primary_listener.should_be_hidden = 2947 + virtio_net_primary_should_be_hidden; 2948 + atomic_set(&n->primary_should_be_hidden, true); 2949 + device_listener_register(&n->primary_listener); 2950 + n->migration_state.notify = virtio_net_migration_state_notifier; 2951 + add_migration_state_change_notifier(&n->migration_state); 2952 + n->host_features |= (1ULL << VIRTIO_NET_F_STANDBY); 2681 2953 } 2682 2954 2683 2955 virtio_net_set_config_size(n, n->host_features); ··· 2802 3074 g_free(n->mac_table.macs); 2803 3075 g_free(n->vlans); 2804 3076 3077 + if (n->failover) { 3078 + g_free(n->primary_device_id); 3079 + g_free(n->standby_id); 3080 + qobject_unref(n->primary_device_dict); 3081 + n->primary_device_dict = NULL; 3082 + } 3083 + 2805 3084 max_queues = n->multiqueue ? n->max_queues : 1; 2806 3085 for (i = 0; i < max_queues; i++) { 2807 3086 virtio_net_del_queue(n, i); ··· 2839 3118 return 0; 2840 3119 } 2841 3120 3121 + static bool primary_unplug_pending(void *opaque) 3122 + { 3123 + DeviceState *dev = opaque; 3124 + VirtIODevice *vdev = VIRTIO_DEVICE(dev); 3125 + VirtIONet *n = VIRTIO_NET(vdev); 3126 + 3127 + return n->primary_dev ? n->primary_dev->pending_deleted_event : false; 3128 + } 3129 + 3130 + static bool dev_unplug_pending(void *opaque) 3131 + { 3132 + DeviceState *dev = opaque; 3133 + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev); 3134 + 3135 + return vdc->primary_unplug_pending(dev); 3136 + } 3137 + 2842 3138 static const VMStateDescription vmstate_virtio_net = { 2843 3139 .name = "virtio-net", 2844 3140 .minimum_version_id = VIRTIO_NET_VM_VERSION, ··· 2848 3144 VMSTATE_END_OF_LIST() 2849 3145 }, 2850 3146 .pre_save = virtio_net_pre_save, 3147 + .dev_unplug_pending = dev_unplug_pending, 2851 3148 }; 2852 3149 2853 3150 static Property virtio_net_properties[] = { ··· 2909 3206 true), 2910 3207 DEFINE_PROP_INT32("speed", VirtIONet, net_conf.speed, SPEED_UNKNOWN), 2911 3208 DEFINE_PROP_STRING("duplex", VirtIONet, net_conf.duplex_str), 3209 + DEFINE_PROP_BOOL("failover", VirtIONet, failover, false), 2912 3210 DEFINE_PROP_END_OF_LIST(), 2913 3211 }; 2914 3212 ··· 2934 3232 vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO); 2935 3233 vdc->post_load = virtio_net_post_load_virtio; 2936 3234 vdc->vmsd = &vmstate_virtio_net_device; 3235 + vdc->primary_unplug_pending = primary_unplug_pending; 2937 3236 } 2938 3237 2939 3238 static const TypeInfo virtio_net_info = {
+32
hw/pci/pci.c
··· 75 75 QEMU_PCIE_LNKSTA_DLLLA_BITNR, true), 76 76 DEFINE_PROP_BIT("x-pcie-extcap-init", PCIDevice, cap_present, 77 77 QEMU_PCIE_EXTCAP_INIT_BITNR, true), 78 + DEFINE_PROP_STRING("failover_pair_id", PCIDevice, 79 + failover_pair_id), 78 80 DEFINE_PROP_END_OF_LIST() 79 81 }; 80 82 ··· 2077 2079 ObjectClass *klass = OBJECT_CLASS(pc); 2078 2080 Error *local_err = NULL; 2079 2081 bool is_default_rom; 2082 + uint16_t class_id; 2080 2083 2081 2084 /* initialize cap_present for pci_is_express() and pci_config_size(), 2082 2085 * Note that hybrid PCIs are not set automatically and need to manage ··· 2099 2102 do_pci_unregister_device(pci_dev); 2100 2103 return; 2101 2104 } 2105 + } 2106 + 2107 + if (pci_dev->failover_pair_id) { 2108 + if (!pci_bus_is_express(pci_get_bus(pci_dev))) { 2109 + error_setg(errp, "failover primary device must be on " 2110 + "PCIExpress bus"); 2111 + error_propagate(errp, local_err); 2112 + pci_qdev_unrealize(DEVICE(pci_dev), NULL); 2113 + return; 2114 + } 2115 + class_id = pci_get_word(pci_dev->config + PCI_CLASS_DEVICE); 2116 + if (class_id != PCI_CLASS_NETWORK_ETHERNET) { 2117 + error_setg(errp, "failover primary device is not an " 2118 + "Ethernet device"); 2119 + error_propagate(errp, local_err); 2120 + pci_qdev_unrealize(DEVICE(pci_dev), NULL); 2121 + return; 2122 + } 2123 + if (!(pci_dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) 2124 + && (PCI_FUNC(pci_dev->devfn) == 0)) { 2125 + qdev->allow_unplug_during_migration = true; 2126 + } else { 2127 + error_setg(errp, "failover: primary device must be in its own " 2128 + "PCI slot"); 2129 + error_propagate(errp, local_err); 2130 + pci_qdev_unrealize(DEVICE(pci_dev), NULL); 2131 + return; 2132 + } 2133 + qdev->allow_unplug_during_migration = true; 2102 2134 } 2103 2135 2104 2136 /* rom loading */
+6
hw/pci/pcie.c
··· 456 456 { 457 457 HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev)); 458 458 459 + if (dev->partially_hotplugged) { 460 + dev->qdev.pending_deleted_event = false; 461 + return; 462 + } 459 463 hotplug_handler_unplug(hotplug_ctrl, DEVICE(dev), &error_abort); 460 464 object_unparent(OBJECT(dev)); 461 465 } ··· 472 476 error_propagate(errp, local_err); 473 477 return; 474 478 } 479 + 480 + dev->pending_deleted_event = true; 475 481 476 482 /* In case user cancel the operation of multi-function hot-add, 477 483 * remove the function that is unexposed to guest individually,
+20 -6
hw/vfio/pci.c
··· 40 40 #include "pci.h" 41 41 #include "trace.h" 42 42 #include "qapi/error.h" 43 + #include "migration/blocker.h" 43 44 44 45 #define TYPE_VFIO_PCI "vfio-pci" 45 46 #define PCI_VFIO(obj) OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI) ··· 2732 2733 return; 2733 2734 } 2734 2735 2736 + if (!pdev->failover_pair_id) { 2737 + error_setg(&vdev->migration_blocker, 2738 + "VFIO device doesn't support migration"); 2739 + ret = migrate_add_blocker(vdev->migration_blocker, &err); 2740 + if (err) { 2741 + error_propagate(errp, err); 2742 + error_free(vdev->migration_blocker); 2743 + return; 2744 + } 2745 + } 2746 + 2735 2747 vdev->vbasedev.name = g_path_get_basename(vdev->vbasedev.sysfsdev); 2736 2748 vdev->vbasedev.ops = &vfio_pci_ops; 2737 2749 vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI; ··· 3008 3020 vfio_bars_exit(vdev); 3009 3021 error: 3010 3022 error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name); 3023 + if (vdev->migration_blocker) { 3024 + migrate_del_blocker(vdev->migration_blocker); 3025 + error_free(vdev->migration_blocker); 3026 + } 3011 3027 } 3012 3028 3013 3029 static void vfio_instance_finalize(Object *obj) ··· 3019 3035 vfio_bars_finalize(vdev); 3020 3036 g_free(vdev->emulated_config_bits); 3021 3037 g_free(vdev->rom); 3038 + if (vdev->migration_blocker) { 3039 + migrate_del_blocker(vdev->migration_blocker); 3040 + error_free(vdev->migration_blocker); 3041 + } 3022 3042 /* 3023 3043 * XXX Leaking igd_opregion is not an oversight, we can't remove the 3024 3044 * fw_cfg entry therefore leaking this allocation seems like the safest ··· 3151 3171 DEFINE_PROP_END_OF_LIST(), 3152 3172 }; 3153 3173 3154 - static const VMStateDescription vfio_pci_vmstate = { 3155 - .name = "vfio-pci", 3156 - .unmigratable = 1, 3157 - }; 3158 - 3159 3174 static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) 3160 3175 { 3161 3176 DeviceClass *dc = DEVICE_CLASS(klass); ··· 3163 3178 3164 3179 dc->reset = vfio_pci_reset; 3165 3180 dc->props = vfio_pci_dev_properties; 3166 - dc->vmsd = &vfio_pci_vmstate; 3167 3181 dc->desc = "VFIO-based PCI device assignment"; 3168 3182 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 3169 3183 pdc->realize = vfio_realize;
+1
hw/vfio/pci.h
··· 168 168 bool no_vfio_ioeventfd; 169 169 bool enable_ramfb; 170 170 VFIODisplay *dpy; 171 + Error *migration_blocker; 171 172 } VFIOPCIDevice; 172 173 173 174 uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
+1 -3
hw/virtio/vhost.c
··· 924 924 uint64_t uaddr, len; 925 925 int ret = -EFAULT; 926 926 927 - rcu_read_lock(); 927 + RCU_READ_LOCK_GUARD(); 928 928 929 929 trace_vhost_iotlb_miss(dev, 1); 930 930 ··· 956 956 trace_vhost_iotlb_miss(dev, 2); 957 957 958 958 out: 959 - rcu_read_unlock(); 960 - 961 959 return ret; 962 960 } 963 961
+23 -42
hw/virtio/virtio.c
··· 387 387 388 388 static void virtio_queue_split_set_notification(VirtQueue *vq, int enable) 389 389 { 390 - rcu_read_lock(); 390 + RCU_READ_LOCK_GUARD(); 391 + 391 392 if (virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) { 392 393 vring_set_avail_event(vq, vring_avail_idx(vq)); 393 394 } else if (enable) { ··· 399 400 /* Expose avail event/used flags before caller checks the avail idx. */ 400 401 smp_mb(); 401 402 } 402 - rcu_read_unlock(); 403 403 } 404 404 405 405 static void virtio_queue_packed_set_notification(VirtQueue *vq, int enable) ··· 408 408 VRingPackedDescEvent e; 409 409 VRingMemoryRegionCaches *caches; 410 410 411 - rcu_read_lock(); 411 + RCU_READ_LOCK_GUARD(); 412 412 caches = vring_get_region_caches(vq); 413 413 vring_packed_event_read(vq->vdev, &caches->used, &e); 414 414 ··· 429 429 /* Expose avail event/used flags before caller checks the avail idx. */ 430 430 smp_mb(); 431 431 } 432 - rcu_read_unlock(); 433 432 } 434 433 435 434 void virtio_queue_set_notification(VirtQueue *vq, int enable) ··· 577 576 return 0; 578 577 } 579 578 580 - rcu_read_lock(); 579 + RCU_READ_LOCK_GUARD(); 581 580 empty = vring_avail_idx(vq) == vq->last_avail_idx; 582 - rcu_read_unlock(); 583 581 return empty; 584 582 } 585 583 ··· 601 599 602 600 static int virtio_queue_packed_empty(VirtQueue *vq) 603 601 { 604 - bool empty; 605 - 606 - rcu_read_lock(); 607 - empty = virtio_queue_packed_empty_rcu(vq); 608 - rcu_read_unlock(); 609 - return empty; 602 + RCU_READ_LOCK_GUARD(); 603 + return virtio_queue_packed_empty_rcu(vq); 610 604 } 611 605 612 606 int virtio_queue_empty(VirtQueue *vq) ··· 859 853 void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, 860 854 unsigned int len) 861 855 { 862 - rcu_read_lock(); 856 + RCU_READ_LOCK_GUARD(); 863 857 virtqueue_fill(vq, elem, len, 0); 864 858 virtqueue_flush(vq, 1); 865 - rcu_read_unlock(); 866 859 } 867 860 868 861 /* Called within rcu_read_lock(). */ ··· 943 936 int64_t len = 0; 944 937 int rc; 945 938 946 - rcu_read_lock(); 939 + RCU_READ_LOCK_GUARD(); 940 + 947 941 idx = vq->last_avail_idx; 948 942 total_bufs = in_total = out_total = 0; 949 943 ··· 1033 1027 if (out_bytes) { 1034 1028 *out_bytes = out_total; 1035 1029 } 1036 - rcu_read_unlock(); 1037 1030 return; 1038 1031 1039 1032 err: ··· 1083 1076 VRingPackedDesc desc; 1084 1077 bool wrap_counter; 1085 1078 1086 - rcu_read_lock(); 1079 + RCU_READ_LOCK_GUARD(); 1087 1080 idx = vq->last_avail_idx; 1088 1081 wrap_counter = vq->last_avail_wrap_counter; 1089 1082 total_bufs = in_total = out_total = 0; ··· 1176 1169 if (out_bytes) { 1177 1170 *out_bytes = out_total; 1178 1171 } 1179 - rcu_read_unlock(); 1180 1172 return; 1181 1173 1182 1174 err: ··· 1360 1352 VRingDesc desc; 1361 1353 int rc; 1362 1354 1363 - rcu_read_lock(); 1355 + RCU_READ_LOCK_GUARD(); 1364 1356 if (virtio_queue_empty_rcu(vq)) { 1365 1357 goto done; 1366 1358 } ··· 1469 1461 trace_virtqueue_pop(vq, elem, elem->in_num, elem->out_num); 1470 1462 done: 1471 1463 address_space_cache_destroy(&indirect_desc_cache); 1472 - rcu_read_unlock(); 1473 1464 1474 1465 return elem; 1475 1466 ··· 1494 1485 uint16_t id; 1495 1486 int rc; 1496 1487 1497 - rcu_read_lock(); 1488 + RCU_READ_LOCK_GUARD(); 1498 1489 if (virtio_queue_packed_empty_rcu(vq)) { 1499 1490 goto done; 1500 1491 } ··· 1600 1591 trace_virtqueue_pop(vq, elem, elem->in_num, elem->out_num); 1601 1592 done: 1602 1593 address_space_cache_destroy(&indirect_desc_cache); 1603 - rcu_read_unlock(); 1604 1594 1605 1595 return elem; 1606 1596 ··· 2437 2427 2438 2428 void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq) 2439 2429 { 2440 - bool should_notify; 2441 - rcu_read_lock(); 2442 - should_notify = virtio_should_notify(vdev, vq); 2443 - rcu_read_unlock(); 2444 - 2445 - if (!should_notify) { 2446 - return; 2430 + WITH_RCU_READ_LOCK_GUARD() { 2431 + if (!virtio_should_notify(vdev, vq)) { 2432 + return; 2433 + } 2447 2434 } 2448 2435 2449 2436 trace_virtio_notify_irqfd(vdev, vq); ··· 2475 2462 2476 2463 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq) 2477 2464 { 2478 - bool should_notify; 2479 - rcu_read_lock(); 2480 - should_notify = virtio_should_notify(vdev, vq); 2481 - rcu_read_unlock(); 2482 - 2483 - if (!should_notify) { 2484 - return; 2465 + WITH_RCU_READ_LOCK_GUARD() { 2466 + if (!virtio_should_notify(vdev, vq)) { 2467 + return; 2468 + } 2485 2469 } 2486 2470 2487 2471 trace_virtio_notify(vdev, vq); ··· 3032 3016 vdev->start_on_kick = true; 3033 3017 } 3034 3018 3035 - rcu_read_lock(); 3019 + RCU_READ_LOCK_GUARD(); 3036 3020 for (i = 0; i < num; i++) { 3037 3021 if (vdev->vq[i].vring.desc) { 3038 3022 uint16_t nheads; ··· 3087 3071 } 3088 3072 } 3089 3073 } 3090 - rcu_read_unlock(); 3091 3074 3092 3075 if (vdc->post_load) { 3093 3076 ret = vdc->post_load(vdev); ··· 3297 3280 static void virtio_queue_split_restore_last_avail_idx(VirtIODevice *vdev, 3298 3281 int n) 3299 3282 { 3300 - rcu_read_lock(); 3283 + RCU_READ_LOCK_GUARD(); 3301 3284 if (vdev->vq[n].vring.desc) { 3302 3285 vdev->vq[n].last_avail_idx = vring_used_idx(&vdev->vq[n]); 3303 3286 vdev->vq[n].shadow_avail_idx = vdev->vq[n].last_avail_idx; 3304 3287 } 3305 - rcu_read_unlock(); 3306 3288 } 3307 3289 3308 3290 void virtio_queue_restore_last_avail_idx(VirtIODevice *vdev, int n) ··· 3322 3304 3323 3305 static void virtio_split_packed_update_used_idx(VirtIODevice *vdev, int n) 3324 3306 { 3325 - rcu_read_lock(); 3307 + RCU_READ_LOCK_GUARD(); 3326 3308 if (vdev->vq[n].vring.desc) { 3327 3309 vdev->vq[n].used_idx = vring_used_idx(&vdev->vq[n]); 3328 3310 } 3329 - rcu_read_unlock(); 3330 3311 } 3331 3312 3332 3313 void virtio_queue_update_used_idx(VirtIODevice *vdev, int n)
+4
include/hw/pci/pci.h
··· 265 265 266 266 struct PCIDevice { 267 267 DeviceState qdev; 268 + bool partially_hotplugged; 268 269 269 270 /* PCI config space */ 270 271 uint8_t *config; ··· 352 353 MSIVectorUseNotifier msix_vector_use_notifier; 353 354 MSIVectorReleaseNotifier msix_vector_release_notifier; 354 355 MSIVectorPollNotifier msix_vector_poll_notifier; 356 + 357 + /* ID of standby device in net_failover pair */ 358 + char *failover_pair_id; 355 359 }; 356 360 357 361 void pci_register_bar(PCIDevice *pci_dev, int region_num,
+30
include/hw/qdev-core.h
··· 78 78 * respective parent types. 79 79 * </para> 80 80 * </note> 81 + * 82 + * # Hiding a device # 83 + * To hide a device, a DeviceListener function should_be_hidden() needs to 84 + * be registered. 85 + * It can be used to defer adding a device and therefore hide it from the 86 + * guest. The handler registering to this DeviceListener can save the QOpts 87 + * passed to it for re-using it later and must return that it wants the device 88 + * to be/remain hidden or not. When the handler function decides the device 89 + * shall not be hidden it will be added in qdev_device_add() and 90 + * realized as any other device. Otherwise qdev_device_add() will return early 91 + * without adding the device. The guest will not see a "hidden" device 92 + * until it was marked don't hide and qdev_device_add called again. 93 + * 81 94 */ 82 95 typedef struct DeviceClass { 83 96 /*< private >*/ ··· 143 156 bool pending_deleted_event; 144 157 QemuOpts *opts; 145 158 int hotplugged; 159 + bool allow_unplug_during_migration; 146 160 BusState *parent_bus; 147 161 QLIST_HEAD(, NamedGPIOList) gpios; 148 162 QLIST_HEAD(, BusState) child_bus; ··· 154 168 struct DeviceListener { 155 169 void (*realize)(DeviceListener *listener, DeviceState *dev); 156 170 void (*unrealize)(DeviceListener *listener, DeviceState *dev); 171 + /* 172 + * This callback is called upon init of the DeviceState and allows to 173 + * inform qdev that a device should be hidden, depending on the device 174 + * opts, for example, to hide a standby device. 175 + */ 176 + int (*should_be_hidden)(DeviceListener *listener, QemuOpts *device_opts); 157 177 QTAILQ_ENTRY(DeviceListener) link; 158 178 }; 159 179 ··· 450 470 451 471 void device_listener_register(DeviceListener *listener); 452 472 void device_listener_unregister(DeviceListener *listener); 473 + 474 + /** 475 + * @qdev_should_hide_device: 476 + * @opts: QemuOpts as passed on cmdline. 477 + * 478 + * Check if a device should be added. 479 + * When a device is added via qdev_device_add() this will be called, 480 + * and return if the device should be added now or not. 481 + */ 482 + bool qdev_should_hide_device(QemuOpts *opts); 453 483 454 484 #endif
+12
include/hw/virtio/virtio-net.h
··· 18 18 #include "standard-headers/linux/virtio_net.h" 19 19 #include "hw/virtio/virtio.h" 20 20 #include "net/announce.h" 21 + #include "qemu/option_int.h" 21 22 22 23 #define TYPE_VIRTIO_NET "virtio-net-device" 23 24 #define VIRTIO_NET(obj) \ ··· 43 44 int32_t speed; 44 45 char *duplex_str; 45 46 uint8_t duplex; 47 + char *primary_id_str; 46 48 } virtio_net_conf; 47 49 48 50 /* Coalesced packets type & status */ ··· 187 189 AnnounceTimer announce_timer; 188 190 bool needs_vnet_hdr_swap; 189 191 bool mtu_bypass_backend; 192 + QemuOpts *primary_device_opts; 193 + QDict *primary_device_dict; 194 + DeviceState *primary_dev; 195 + BusState *primary_bus; 196 + char *primary_device_id; 197 + char *standby_id; 198 + bool primary_should_be_hidden; 199 + bool failover; 200 + DeviceListener primary_listener; 201 + Notifier migration_state; 190 202 }; 191 203 192 204 void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
+1
include/hw/virtio/virtio.h
··· 160 160 */ 161 161 int (*post_load)(VirtIODevice *vdev); 162 162 const VMStateDescription *vmsd; 163 + bool (*primary_unplug_pending)(void *opaque); 163 164 } VirtioDeviceClass; 164 165 165 166 void virtio_instance_init_common(Object *proxy_obj, void *data,
+2
include/migration/vmstate.h
··· 186 186 int (*pre_save)(void *opaque); 187 187 int (*post_save)(void *opaque); 188 188 bool (*needed)(void *opaque); 189 + bool (*dev_unplug_pending)(void *opaque); 190 + 189 191 const VMStateField *fields; 190 192 const VMStateDescription **subsections; 191 193 };
+21
migration/migration.c
··· 52 52 #include "hw/qdev-properties.h" 53 53 #include "monitor/monitor.h" 54 54 #include "net/announce.h" 55 + #include "qemu/queue.h" 55 56 56 57 #define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */ 57 58 ··· 819 820 case MIGRATION_STATUS_SETUP: 820 821 case MIGRATION_STATUS_PRE_SWITCHOVER: 821 822 case MIGRATION_STATUS_DEVICE: 823 + case MIGRATION_STATUS_WAIT_UNPLUG: 822 824 return true; 823 825 824 826 default: ··· 954 956 case MIGRATION_STATUS_CANCELLED: 955 957 info->has_status = true; 956 958 break; 959 + case MIGRATION_STATUS_WAIT_UNPLUG: 960 + info->has_status = true; 961 + break; 957 962 } 958 963 info->status = s->state; 959 964 } ··· 1694 1699 case MIGRATION_STATUS_COLO: 1695 1700 case MIGRATION_STATUS_PRE_SWITCHOVER: 1696 1701 case MIGRATION_STATUS_DEVICE: 1702 + case MIGRATION_STATUS_WAIT_UNPLUG: 1697 1703 return false; 1698 1704 case MIGRATION_STATUS__MAX: 1699 1705 g_assert_not_reached(); ··· 3264 3270 3265 3271 qemu_savevm_state_setup(s->to_dst_file); 3266 3272 3273 + if (qemu_savevm_nr_failover_devices()) { 3274 + migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, 3275 + MIGRATION_STATUS_WAIT_UNPLUG); 3276 + 3277 + while (s->state == MIGRATION_STATUS_WAIT_UNPLUG && 3278 + qemu_savevm_state_guest_unplug_pending()) { 3279 + qemu_sem_timedwait(&s->wait_unplug_sem, 250); 3280 + } 3281 + 3282 + migrate_set_state(&s->state, MIGRATION_STATUS_WAIT_UNPLUG, 3283 + MIGRATION_STATUS_ACTIVE); 3284 + } 3285 + 3267 3286 s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; 3268 3287 migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, 3269 3288 MIGRATION_STATUS_ACTIVE); ··· 3511 3530 qemu_mutex_destroy(&ms->qemu_file_lock); 3512 3531 g_free(params->tls_hostname); 3513 3532 g_free(params->tls_creds); 3533 + qemu_sem_destroy(&ms->wait_unplug_sem); 3514 3534 qemu_sem_destroy(&ms->rate_limit_sem); 3515 3535 qemu_sem_destroy(&ms->pause_sem); 3516 3536 qemu_sem_destroy(&ms->postcopy_pause_sem); ··· 3556 3576 qemu_sem_init(&ms->postcopy_pause_rp_sem, 0); 3557 3577 qemu_sem_init(&ms->rp_state.rp_sem, 0); 3558 3578 qemu_sem_init(&ms->rate_limit_sem, 0); 3579 + qemu_sem_init(&ms->wait_unplug_sem, 0); 3559 3580 qemu_mutex_init(&ms->qemu_file_lock); 3560 3581 } 3561 3582
+3
migration/migration.h
··· 206 206 /* Flag set once the migration thread called bdrv_inactivate_all */ 207 207 bool block_inactive; 208 208 209 + /* Migration is waiting for guest to unplug device */ 210 + QemuSemaphore wait_unplug_sem; 211 + 209 212 /* Migration is paused due to pause-before-switchover */ 210 213 QemuSemaphore pause_sem; 211 214
+31
migration/savevm.c
··· 1113 1113 } 1114 1114 } 1115 1115 1116 + int qemu_savevm_nr_failover_devices(void) 1117 + { 1118 + SaveStateEntry *se; 1119 + int n = 0; 1120 + 1121 + QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { 1122 + if (se->vmsd && se->vmsd->dev_unplug_pending) { 1123 + n++; 1124 + } 1125 + } 1126 + 1127 + return n; 1128 + } 1129 + 1130 + bool qemu_savevm_state_guest_unplug_pending(void) 1131 + { 1132 + SaveStateEntry *se; 1133 + int n = 0; 1134 + 1135 + QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { 1136 + if (!se->vmsd || !se->vmsd->dev_unplug_pending) { 1137 + continue; 1138 + } 1139 + if (se->vmsd->dev_unplug_pending(se->opaque)) { 1140 + n++; 1141 + } 1142 + } 1143 + 1144 + return n > 0; 1145 + } 1146 + 1116 1147 void qemu_savevm_state_setup(QEMUFile *f) 1117 1148 { 1118 1149 SaveStateEntry *se;
+2
migration/savevm.h
··· 31 31 32 32 bool qemu_savevm_state_blocked(Error **errp); 33 33 void qemu_savevm_state_setup(QEMUFile *f); 34 + int qemu_savevm_nr_failover_devices(void); 35 + bool qemu_savevm_state_guest_unplug_pending(void); 34 36 int qemu_savevm_state_resume_prepare(MigrationState *s); 35 37 void qemu_savevm_state_header(QEMUFile *f); 36 38 int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy);
+23 -1
qapi/migration.json
··· 133 133 # @device: During device serialisation when pause-before-switchover is enabled 134 134 # (since 2.11) 135 135 # 136 + # @wait-unplug: wait for device unplug request by guest OS to be completed. 137 + # (since 4.2) 138 + # 136 139 # Since: 2.3 137 140 # 138 141 ## ··· 140 143 'data': [ 'none', 'setup', 'cancelling', 'cancelled', 141 144 'active', 'postcopy-active', 'postcopy-paused', 142 145 'postcopy-recover', 'completed', 'failed', 'colo', 143 - 'pre-switchover', 'device' ] } 146 + 'pre-switchover', 'device', 'wait-unplug' ] } 144 147 145 148 ## 146 149 # @MigrationInfo: ··· 1448 1451 # Since: 3.0 1449 1452 ## 1450 1453 { 'command': 'migrate-pause', 'allow-oob': true } 1454 + 1455 + ## 1456 + # @UNPLUG_PRIMARY: 1457 + # 1458 + # Emitted from source side of a migration when migration state is 1459 + # WAIT_UNPLUG. Device was unplugged by guest operating system. 1460 + # Device resources in QEMU are kept on standby to be able to re-plug it in case 1461 + # of migration failure. 1462 + # 1463 + # @device-id: QEMU device id of the unplugged device 1464 + # 1465 + # Since: 4.2 1466 + # 1467 + # Example: 1468 + # {"event": "UNPLUG_PRIMARY", "data": {"device-id": "hostdev0"} } 1469 + # 1470 + ## 1471 + { 'event': 'UNPLUG_PRIMARY', 1472 + 'data': { 'device-id': 'str' } }
+19
qapi/net.json
··· 735 735 ## 736 736 { 'command': 'announce-self', 'boxed': true, 737 737 'data' : 'AnnounceParameters'} 738 + 739 + ## 740 + # @FAILOVER_NEGOTIATED: 741 + # 742 + # Emitted when VIRTIO_NET_F_STANDBY was enabled during feature negotiation. 743 + # Failover primary devices which were hidden (not hotplugged when requested) 744 + # before will now be hotplugged by the virtio-net standby device. 745 + # 746 + # device-id: QEMU device id of the unplugged device 747 + # Since: 4.2 748 + # 749 + # Example: 750 + # 751 + # <- { "event": "FAILOVER_NEGOTIATED", 752 + # "data": "net1" } 753 + # 754 + ## 755 + { 'event': 'FAILOVER_NEGOTIATED', 756 + 'data': {'device-id': 'str'} }
+38 -5
qdev-monitor.c
··· 32 32 #include "qemu/help_option.h" 33 33 #include "qemu/option.h" 34 34 #include "qemu/qemu-print.h" 35 + #include "qemu/option_int.h" 35 36 #include "sysemu/block-backend.h" 36 37 #include "sysemu/sysemu.h" 37 38 #include "migration/misc.h" 39 + #include "migration/migration.h" 38 40 39 41 /* 40 42 * Aliases were a bad idea from the start. Let's keep them ··· 562 564 } 563 565 } 564 566 567 + static int is_failover_device(void *opaque, const char *name, const char *value, 568 + Error **errp) 569 + { 570 + if (strcmp(name, "failover_pair_id") == 0) { 571 + QemuOpts *opts = (QemuOpts *)opaque; 572 + 573 + if (qdev_should_hide_device(opts)) { 574 + return 1; 575 + } 576 + } 577 + 578 + return 0; 579 + } 580 + 581 + static bool should_hide_device(QemuOpts *opts) 582 + { 583 + if (qemu_opt_foreach(opts, is_failover_device, opts, NULL) == 0) { 584 + return false; 585 + } 586 + return true; 587 + } 588 + 565 589 DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) 566 590 { 567 591 DeviceClass *dc; 568 592 const char *driver, *path; 569 - DeviceState *dev; 593 + DeviceState *dev = NULL; 570 594 BusState *bus = NULL; 571 595 Error *err = NULL; 596 + bool hide; 572 597 573 598 driver = qemu_opt_get(opts, "driver"); 574 599 if (!driver) { ··· 602 627 return NULL; 603 628 } 604 629 } 605 - if (qdev_hotplug && bus && !qbus_is_hotpluggable(bus)) { 630 + hide = should_hide_device(opts); 631 + 632 + if ((hide || qdev_hotplug) && bus && !qbus_is_hotpluggable(bus)) { 606 633 error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); 607 634 return NULL; 608 635 } 609 636 637 + if (hide) { 638 + return NULL; 639 + } 640 + 610 641 if (!migration_is_idle()) { 611 642 error_setg(errp, "device_add not allowed while migrating"); 612 643 return NULL; ··· 648 679 649 680 err_del_dev: 650 681 error_propagate(errp, err); 651 - object_unparent(OBJECT(dev)); 652 - object_unref(OBJECT(dev)); 682 + if (dev) { 683 + object_unparent(OBJECT(dev)); 684 + object_unref(OBJECT(dev)); 685 + } 653 686 return NULL; 654 687 } 655 688 ··· 818 851 return; 819 852 } 820 853 821 - if (!migration_is_idle()) { 854 + if (!migration_is_idle() && !dev->allow_unplug_during_migration) { 822 855 error_setg(errp, "device_del not allowed while migrating"); 823 856 return; 824 857 }
+2 -1
tests/libqos/libqos.c
··· 125 125 break; 126 126 } 127 127 128 - if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0)) { 128 + if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0) 129 + || (strcmp(st, "wait-unplug") == 0)) { 129 130 qobject_unref(rsp); 130 131 g_usleep(5000); 131 132 continue;
+4 -2
vl.c
··· 2207 2207 DeviceState *dev; 2208 2208 2209 2209 dev = qdev_device_add(opts, errp); 2210 - if (!dev) { 2210 + if (!dev && *errp) { 2211 + error_report_err(*errp); 2211 2212 return -1; 2213 + } else if (dev) { 2214 + object_unref(OBJECT(dev)); 2212 2215 } 2213 - object_unref(OBJECT(dev)); 2214 2216 return 0; 2215 2217 } 2216 2218