已开启
ub: support UB hostdev hotplug and hot-unplug #456
xiangzixuan123创建于 11 天前
ub: support UB hostdev hotplug and hot-unplug #456
已开启
共 6 个文件变更+117-16
| @@ -14592,8 +14592,8 @@ virDomainHostdevMatchSubsys(virDomainHostdevDef *a, | |||
| 14592 | return STREQ(a->source.subsys.u.vdpa.devpath, | 14592 | return STREQ(a->source.subsys.u.vdpa.devpath, |
| 14593 | b->source.subsys.u.vdpa.devpath); | 14593 | b->source.subsys.u.vdpa.devpath); |
| 14594 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: | 14594 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: |
| 14595 | - VIR_INFO("TODO: %s", __func__); | 14595 | + return STREQ(a->source.subsys.u.ub.addr.guidStr, |
| 14596 | - return 0; | 14596 | + b->source.subsys.u.ub.addr.guidStr); |
| 14597 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: | 14597 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: |
| 14598 | return 0; | 14598 | return 0; |
| 14599 | } | 14599 | } |
| @@ -5270,7 +5270,7 @@ qemuBuildHostdevSCSICommandLine(virCommand *cmd, | |||
| 5270 | return 0; | 5270 | return 0; |
| 5271 | } | 5271 | } |
| 5272 | 5272 | ||
| 5273 | -static virJSONValue * | 5273 | +virJSONValue * |
| 5274 | qemuBuildHostdevUBDevProps(const virDomainDef *domainDef, | 5274 | qemuBuildHostdevUBDevProps(const virDomainDef *domainDef, |
| 5275 | virDomainHostdevDef *dev) | 5275 | virDomainHostdevDef *dev) |
| 5276 | { | 5276 | { |
| @@ -202,6 +202,10 @@ virJSONValue * | |||
| 202 | qemuBuildHostdevVDPADevProps(const virDomainDef *def, | 202 | qemuBuildHostdevVDPADevProps(const virDomainDef *def, |
| 203 | virDomainHostdevDef *dev); | 203 | virDomainHostdevDef *dev); |
| 204 | 204 | ||
| 205 | +virJSONValue * | ||
| 206 | +qemuBuildHostdevUBDevProps(const virDomainDef *def, | ||
| 207 | + virDomainHostdevDef *dev); | ||
| 208 | + | ||
| 205 | virJSONValue * | 209 | virJSONValue * |
| 206 | qemuBuildRedirdevDevProps(const virDomainDef *def, | 210 | qemuBuildRedirdevDevProps(const virDomainDef *def, |
| 207 | virDomainRedirdevDef *dev); | 211 | virDomainRedirdevDef *dev); |
| @@ -363,7 +363,8 @@ qemuHostdevPrepareMediatedDevices(virQEMUDriver *driver, | |||
| 363 | 363 | ||
| 364 | 364 | ||
| 365 | static int | 365 | static int |
| 366 | -qemuHostdevCheckUBDevices(virDomainDef *def) | 366 | +qemuHostdevCheckUBDevices(virDomainControllerDef **controllers, |
| 367 | + int ncontrollers) | ||
| 367 | { | 368 | { |
| 368 | bool supportsPassthroughVFIO; | 369 | bool supportsPassthroughVFIO; |
| 369 | bool supportsIOMMUFD; | 370 | bool supportsIOMMUFD; |
| @@ -394,8 +395,8 @@ qemuHostdevCheckUBDevices(virDomainDef *def) | |||
| 394 | return -1; | 395 | return -1; |
| 395 | } | 396 | } |
| 396 | 397 | ||
| 397 | - for (i = 0; i < def->ncontrollers; i++) { | 398 | + for (i = 0; i < ncontrollers; i++) { |
| 398 | - cont = def->controllers[i]; | 399 | + cont = controllers[i]; |
| 399 | if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_UB) { | 400 | if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_UB) { |
| 400 | bus_instance_guid_str = cont->info.busInstance.guidStr; | 401 | bus_instance_guid_str = cont->info.busInstance.guidStr; |
| 401 | break; | 402 | break; |
| @@ -426,17 +427,17 @@ qemuHostdevCheckUBDevices(virDomainDef *def) | |||
| 426 | 427 | ||
| 427 | int | 428 | int |
| 428 | qemuHostdevPrepareUBDevices(virQEMUDriver *driver, | 429 | qemuHostdevPrepareUBDevices(virQEMUDriver *driver, |
| 429 | - virDomainDef *def) | 430 | + const char *name, |
| 431 | + virDomainControllerDef **controllers, | ||
| 432 | + int ncontrollers, | ||
| 433 | + virDomainHostdevDef **hostdevs, | ||
| 434 | + int nhostdevs) | ||
| 430 | { | 435 | { |
| 431 | - const char *name = def->name; | ||
| 432 | - virDomainHostdevDef **hostdevs = def->hostdevs; | ||
| 433 | - int nhostdevs = def->nhostdevs; | ||
| 434 | - | ||
| 435 | if (!virHostdevHasUBDevice(hostdevs, nhostdevs)) { | 436 | if (!virHostdevHasUBDevice(hostdevs, nhostdevs)) { |
| 436 | return 0; | 437 | return 0; |
| 437 | } | 438 | } |
| 438 | 439 | ||
| 439 | - if (qemuHostdevCheckUBDevices(def) < 0) { | 440 | + if (qemuHostdevCheckUBDevices(controllers, ncontrollers) < 0) { |
| 440 | return -1; | 441 | return -1; |
| 441 | } | 442 | } |
| 442 | 443 | ||
| @@ -477,7 +478,9 @@ qemuHostdevPrepareDomainDevices(virQEMUDriver *driver, | |||
| 477 | def->hostdevs, def->nhostdevs) < 0) | 478 | def->hostdevs, def->nhostdevs) < 0) |
| 478 | return -1; | 479 | return -1; |
| 479 | 480 | ||
| 480 | - if (qemuHostdevPrepareUBDevices(driver, def) < 0) | 481 | + if (qemuHostdevPrepareUBDevices(driver, def->name, |
| 482 | + def->controllers, def->ncontrollers, | ||
| 483 | + def->hostdevs, def->nhostdevs) < 0) | ||
| 481 | return -1; | 484 | return -1; |
| 482 | 485 | ||
| 483 | return 0; | 486 | return 0; |
| @@ -81,7 +81,11 @@ int qemuHostdevPrepareMediatedDevices(virQEMUDriver *driver, | |||
| 81 | virDomainHostdevDef **hostdevs, | 81 | virDomainHostdevDef **hostdevs, |
| 82 | int nhostdevs); | 82 | int nhostdevs); |
| 83 | int qemuHostdevPrepareUBDevices(virQEMUDriver *driver, | 83 | int qemuHostdevPrepareUBDevices(virQEMUDriver *driver, |
| 84 | - virDomainDef *def); | 84 | + const char *name, |
| 85 | + virDomainControllerDef **controllers, | ||
| 86 | + int ncontrollers, | ||
| 87 | + virDomainHostdevDef **hostdevs, | ||
| 88 | + int nhostdevs); | ||
| 85 | int qemuHostdevPrepareDomainDevices(virQEMUDriver *driver, | 89 | int qemuHostdevPrepareDomainDevices(virQEMUDriver *driver, |
| 86 | virDomainDef *def, | 90 | virDomainDef *def, |
| 87 | unsigned int flags); | 91 | unsigned int flags); |
| @@ -2838,6 +2838,77 @@ qemuDomainAttachVDPADevice(virQEMUDriver *driver, | |||
| 2838 | return -1; | 2838 | return -1; |
| 2839 | } | 2839 | } |
| 2840 | 2840 | ||
| 2841 | +static int | ||
| 2842 | +qemuDomainAttachUBDevice(virQEMUDriver *driver, | ||
| 2843 | + virDomainObj *vm, | ||
| 2844 | + virDomainHostdevDef *hostdev) | ||
| 2845 | +{ | ||
| 2846 | + int ret = -1; | ||
| 2847 | + g_autoptr(virJSONValue) devprops = NULL; | ||
| 2848 | + bool teardowncgroup = false; | ||
| 2849 | + bool teardownlabel = false; | ||
| 2850 | + bool teardowndevice = false; | ||
| 2851 | + bool teardownmemlock = false; | ||
| 2852 | + qemuDomainObjPrivate *priv = vm->privateData; | ||
| 2853 | + | ||
| 2854 | + if (qemuHostdevPrepareUBDevices(driver, vm->def->name, | ||
| 2855 | + vm->def->controllers, vm->def->ncontrollers, | ||
| 2856 | + &hostdev, 1) < 0) | ||
| 2857 | + return -1; | ||
| 2858 | + | ||
| 2859 | + if (qemuDomainAdjustMaxMemLockHostdev(vm, hostdev) < 0) | ||
| 2860 | + goto cleanup; | ||
| 2861 | + teardownmemlock = true; | ||
| 2862 | + | ||
| 2863 | + if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0) | ||
| 2864 | + goto cleanup; | ||
| 2865 | + | ||
| 2866 | + if (qemuSetupHostdevCgroup(vm, hostdev) < 0) | ||
| 2867 | + goto cleanup; | ||
| 2868 | + teardowncgroup = true; | ||
| 2869 | + | ||
| 2870 | + if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0) | ||
| 2871 | + goto cleanup; | ||
| 2872 | + teardownlabel = true; | ||
| 2873 | + | ||
| 2874 | + qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1); | ||
| 2875 | + | ||
| 2876 | + if (!(devprops = qemuBuildHostdevUBDevProps(vm->def, hostdev))) | ||
| 2877 | + goto cleanup; | ||
| 2878 | + | ||
| 2879 | + qemuDomainObjEnterMonitor(vm); | ||
| 2880 | + ret = qemuMonitorAddDeviceProps(priv->mon, &devprops); | ||
| 2881 | + qemuDomainObjExitMonitor(vm); | ||
| 2882 | + | ||
| 2883 | + virDomainAuditHostdev(vm, hostdev, "attach", ret == 0); | ||
| 2884 | + if (ret < 0) | ||
| 2885 | + goto cleanup; | ||
| 2886 | + | ||
| 2887 | + VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1); | ||
| 2888 | + VIR_APPEND_ELEMENT_INPLACE(vm->def->hostdevs, vm->def->nhostdevs, hostdev); | ||
| 2889 | + ret = 0; | ||
| 2890 | + cleanup: | ||
| 2891 | + if (ret < 0) { | ||
| 2892 | + if (teardownmemlock && qemuDomainAdjustMaxMemLock(vm) < 0) | ||
| 2893 | + VIR_WARN("Unable to reset maximum locked memory on hotplug fail"); | ||
| 2894 | + if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0) | ||
| 2895 | + VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail"); | ||
| 2896 | + if (teardownlabel && | ||
| 2897 | + qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0) | ||
| 2898 | + VIR_WARN("Unable to restore host device labelling on hotplug fail"); | ||
| 2899 | + if (teardowndevice && | ||
| 2900 | + qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0) | ||
| 2901 | + VIR_WARN("Unable to remove host device from /dev"); | ||
| 2902 | + qemuHostdevReAttachUBDevices(driver, | ||
| 2903 | + vm->def->name, | ||
| 2904 | + &hostdev, | ||
| 2905 | + 1); | ||
| 2906 | + qemuDomainReleaseDeviceAddress(vm, hostdev->info); | ||
| 2907 | + } | ||
| 2908 | + return ret; | ||
| 2909 | +} | ||
| 2910 | + | ||
| 2911 | + | ||
| 2841 | static int | 2912 | static int |
| 2842 | qemuDomainAttachHostDevice(virQEMUDriver *driver, | 2913 | qemuDomainAttachHostDevice(virQEMUDriver *driver, |
| 2843 | virDomainObj *vm, | 2914 | virDomainObj *vm, |
| @@ -2885,8 +2956,10 @@ qemuDomainAttachHostDevice(virQEMUDriver *driver, | |||
| 2885 | if (qemuDomainAttachVDPADevice(driver, vm, hostdev) < 0) | 2956 | if (qemuDomainAttachVDPADevice(driver, vm, hostdev) < 0) |
| 2886 | return -1; | 2957 | return -1; |
| 2887 | break; | 2958 | break; |
| 2888 | - /* ub current not supprot hotplug */ | ||
| 2889 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: | 2959 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: |
| 2960 | + if (qemuDomainAttachUBDevice(driver, vm, hostdev) < 0) | ||
| 2961 | + return -1; | ||
| 2962 | + break; | ||
| 2890 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: | 2963 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: |
| 2891 | default: | 2964 | default: |
| 2892 | virReportError(VIR_ERR_CONFIG_UNSUPPORTED, | 2965 | virReportError(VIR_ERR_CONFIG_UNSUPPORTED, |
| @@ -4787,6 +4860,16 @@ qemuDomainRemoveVDPADevice(virDomainObj *vm, | |||
| 4787 | } | 4860 | } |
| 4788 | 4861 | ||
| 4789 | 4862 | ||
| 4863 | +static void | ||
| 4864 | +qemuDomainRemoveUBDevice(virQEMUDriver *driver, | ||
| 4865 | + virDomainObj *vm, | ||
| 4866 | + virDomainHostdevDef *hostdev) | ||
| 4867 | +{ | ||
| 4868 | + qemuHostdevReAttachUBDevices(driver, vm->def->name, &hostdev, 1); | ||
| 4869 | + qemuDomainReleaseDeviceAddress(vm, hostdev->info); | ||
| 4870 | +} | ||
| 4871 | + | ||
| 4872 | + | ||
| 4790 | static int | 4873 | static int |
| 4791 | qemuDomainRemoveHostDevice(virQEMUDriver *driver, | 4874 | qemuDomainRemoveHostDevice(virQEMUDriver *driver, |
| 4792 | virDomainObj *vm, | 4875 | virDomainObj *vm, |
| @@ -4861,8 +4944,11 @@ qemuDomainRemoveHostDevice(virQEMUDriver *driver, | |||
| 4861 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: | 4944 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: |
| 4862 | qemuDomainRemoveVDPADevice(vm, hostdev); | 4945 | qemuDomainRemoveVDPADevice(vm, hostdev); |
| 4863 | break; | 4946 | break; |
| 4864 | - /* UB current not support hot remove */ | ||
| 4865 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: | 4947 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: |
| 4948 | + qemuDomainRemoveUBDevice(driver, vm, hostdev); | ||
| 4949 | + if (qemuDomainAdjustMaxMemLock(vm) < 0) | ||
| 4950 | + VIR_WARN("Failed to adjust locked memory limit"); | ||
| 4951 | + break; | ||
| 4866 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: | 4952 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: |
| 4867 | break; | 4953 | break; |
| 4868 | } | 4954 | } |
| @@ -5900,6 +5986,10 @@ qemuDomainDetachPrepHostdev(virDomainObj *vm, | |||
| 5900 | vdpasrc->devpath); | 5986 | vdpasrc->devpath); |
| 5901 | break; | 5987 | break; |
| 5902 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: | 5988 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_UB: |
| 5989 | + virReportError(VIR_ERR_DEVICE_MISSING, | ||
| 5990 | + _("host ub device '%1$s' not found"), | ||
| 5991 | + subsys->u.ub.addr.guidStr); | ||
| 5992 | + break; | ||
| 5903 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: | 5993 | case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: |
| 5904 | default: | 5994 | default: |
| 5905 | virReportError(VIR_ERR_INTERNAL_ERROR, | 5995 | virReportError(VIR_ERR_INTERNAL_ERROR, |