[libvirt] [PATCH v2 0/4] RFC: vcpupin: configure inactive domains' CPU affinity setting

Hi all, This patchset enables us to configure inactive domains' CPU affinity setting. The basic technique is the same as that of "virsh setmem" command. => http://www.redhat.com/archives/libvir-list/2011-March/msg00013.html v1 -> v2: - recreate based on 0.9.0 - add "CURRENT" mode *[PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) *[PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver *[PATCH 3/4] vcpupin: implement the remote protocol to address the new API *[PATCH 4/4] vcpupin: add the new options to "virsh vcpupin" command Best regards, Taku Izumi

This patch introduces a new libvirt API (virDomainPinVcpuFlags) Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 6 +++ src/driver.h | 7 +++ src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 4 ++ src/lxc/lxc_driver.c | 1 src/openvz/openvz_driver.c | 1 src/phyp/phyp_driver.c | 1 src/qemu/qemu_driver.c | 1 src/remote/remote_driver.c | 1 src/test/test_driver.c | 1 src/uml/uml_driver.c | 1 src/vbox/vbox_tmpl.c | 1 src/vmware/vmware_driver.c | 1 src/xen/xen_driver.c | 1 src/xenapi/xenapi_driver.c | 1 15 files changed, 111 insertions(+) Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -1017,6 +1017,7 @@ typedef virVcpuInfo *virVcpuInfoPtr; /* Flags for controlling virtual CPU hot-plugging. */ typedef enum { + VIR_DOMAIN_VCPU_CURRENT = 0, /* Affect current domain state */ /* Must choose at least one of these two bits; SetVcpus can choose both */ VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */ VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */ @@ -1037,6 +1038,11 @@ int virDomainPinVcpu unsigned int vcpu, unsigned char *cpumap, int maplen); +int virDomainPinVcpuFlags (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); /** * VIR_USE_CPU: Index: libvirt/src/driver.h =================================================================== --- libvirt.orig/src/driver.h +++ libvirt/src/driver.h @@ -220,6 +220,12 @@ typedef int unsigned char *cpumap, int maplen); typedef int + (*virDrvDomainPinVcpuFlags) (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); +typedef int (*virDrvDomainGetVcpus) (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -570,6 +576,7 @@ struct _virDriver { virDrvDomainSetVcpusFlags domainSetVcpusFlags; virDrvDomainGetVcpusFlags domainGetVcpusFlags; virDrvDomainPinVcpu domainPinVcpu; + virDrvDomainPinVcpuFlags domainPinVcpuFlags; virDrvDomainGetVcpus domainGetVcpus; virDrvDomainGetMaxVcpus domainGetMaxVcpus; virDrvDomainGetSecurityLabel domainGetSecurityLabel; Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -5461,6 +5461,89 @@ error: } /** + * virDomainPinVcpuFlags: + * @domain: pointer to domain object, or NULL for Domain0 + * @vcpu: virtual CPU number + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) + * Each bit set to 1 means that corresponding CPU is usable. + * Bytes are stored in little-endian order: CPU0-7, 8-15... + * In each byte, lowest CPU number is least significant bit. + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in + * underlying virtualization system (Xen...). + * If maplen < size, missing bytes are set to zero. + * If maplen > size, failure code is returned. + * @flags: an OR'ed subset of virDomainVcpuFlags + * + * Dynamically change the real CPUs which can be allocated to a virtual CPU. + * This function requires privileged access to the hypervisor. + * + * @flags may include VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. + * Both flags may be set, but VIR_DOMAIN_VCPU_MAXIMUM cannot be set. + * If VIR_DOMAIN_VCPU_LIVE is set, the change affects a running domain + * and may fail if domain is not alive. + * If VIR_DOMAIN_VCPU_CONFIG is set, the change affects persistent state, + * and will fail for transient domains. + * If neither flag is specified (tha is, @flags is VIR_DOMAIN_VCPU_CURRENT), + * then an inactive domain modifies persistent setup, while an active domain + * is hypervisor-dependent on whether just live or both live and persistent + * state is changed. + * Not all hypervisors can support all flag combinations. + * + * Returns 0 in case of success, -1 in case of failure. + * + */ +int +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, + unsigned char *cpumap, int maplen, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "vcpu=%u, cpumap=%p, maplen=%d flags=%u", + vcpu, cpumap, maplen, flags); + + virResetLastError(); + + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainPinVcpuFlags) { + int ret; + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; + +} + +/** * virDomainGetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @info: pointer to an array of virVcpuInfo structures (OUT) Index: libvirt/src/libvirt_public.syms =================================================================== --- libvirt.orig/src/libvirt_public.syms +++ libvirt/src/libvirt_public.syms @@ -436,4 +436,8 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + virDomainPinVcpuFlags; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... Index: libvirt/src/lxc/lxc_driver.c =================================================================== --- libvirt.orig/src/lxc/lxc_driver.c +++ libvirt/src/lxc/lxc_driver.c @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/openvz/openvz_driver.c =================================================================== --- libvirt.orig/src/openvz/openvz_driver.c +++ libvirt/src/openvz/openvz_driver.c @@ -1598,6 +1598,7 @@ static virDriver openvzDriver = { openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/phyp/phyp_driver.c =================================================================== --- libvirt.orig/src/phyp/phyp_driver.c +++ libvirt/src/phyp/phyp_driver.c @@ -4003,6 +4003,7 @@ static virDriver phypDriver = { phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ phypGetLparCPUMAX, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -6864,6 +6864,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/remote/remote_driver.c =================================================================== --- libvirt.orig/src/remote/remote_driver.c +++ libvirt/src/remote/remote_driver.c @@ -11231,6 +11231,7 @@ static virDriver remote_driver = { remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ remoteDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ remoteDomainGetVcpus, /* domainGetVcpus */ remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/test/test_driver.c =================================================================== --- libvirt.orig/src/test/test_driver.c +++ libvirt/src/test/test_driver.c @@ -5378,6 +5378,7 @@ static virDriver testDriver = { testDomainSetVcpusFlags, /* domainSetVcpusFlags */ testDomainGetVcpusFlags, /* domainGetVcpusFlags */ testDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ testDomainGetVcpus, /* domainGetVcpus */ testDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/uml/uml_driver.c =================================================================== --- libvirt.orig/src/uml/uml_driver.c +++ libvirt/src/uml/uml_driver.c @@ -2184,6 +2184,7 @@ static virDriver umlDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vbox/vbox_tmpl.c =================================================================== --- libvirt.orig/src/vbox/vbox_tmpl.c +++ libvirt/src/vbox/vbox_tmpl.c @@ -8568,6 +8568,7 @@ virDriver NAME(Driver) = { vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vmware/vmware_driver.c =================================================================== --- libvirt.orig/src/vmware/vmware_driver.c +++ libvirt/src/vmware/vmware_driver.c @@ -938,6 +938,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xen/xen_driver.c =================================================================== --- libvirt.orig/src/xen/xen_driver.c +++ libvirt/src/xen/xen_driver.c @@ -2072,6 +2072,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenUnifiedDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenUnifiedDomainGetVcpus, /* domainGetVcpus */ xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xenapi/xenapi_driver.c =================================================================== --- libvirt.orig/src/xenapi/xenapi_driver.c +++ libvirt/src/xenapi/xenapi_driver.c @@ -1820,6 +1820,7 @@ static virDriver xenapiDriver = { xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenapiDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenapiDomainGetVcpus, /* domainGetVcpus */ xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */

At 04/08/2011 01:20 PM, Taku Izumi Write:
This patch introduces a new libvirt API (virDomainPinVcpuFlags)
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 6 +++ src/driver.h | 7 +++ src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 4 ++ src/lxc/lxc_driver.c | 1 src/openvz/openvz_driver.c | 1 src/phyp/phyp_driver.c | 1 src/qemu/qemu_driver.c | 1 src/remote/remote_driver.c | 1 src/test/test_driver.c | 1 src/uml/uml_driver.c | 1 src/vbox/vbox_tmpl.c | 1 src/vmware/vmware_driver.c | 1 src/xen/xen_driver.c | 1 src/xenapi/xenapi_driver.c | 1 15 files changed, 111 insertions(+)
Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -1017,6 +1017,7 @@ typedef virVcpuInfo *virVcpuInfoPtr;
/* Flags for controlling virtual CPU hot-plugging. */ typedef enum { + VIR_DOMAIN_VCPU_CURRENT = 0, /* Affect current domain state */ /* Must choose at least one of these two bits; SetVcpus can choose both */ VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */ VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */ @@ -1037,6 +1038,11 @@ int virDomainPinVcpu unsigned int vcpu, unsigned char *cpumap, int maplen); +int virDomainPinVcpuFlags (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags);
/** * VIR_USE_CPU: Index: libvirt/src/driver.h =================================================================== --- libvirt.orig/src/driver.h +++ libvirt/src/driver.h @@ -220,6 +220,12 @@ typedef int unsigned char *cpumap, int maplen); typedef int + (*virDrvDomainPinVcpuFlags) (virDomainPtr domain,
Please use tab between 'virDrvDomainPinVcpuFlags)' and '(virDomainPtr' instead of space as we use tab in all the other places.
+ unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); +typedef int (*virDrvDomainGetVcpus) (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -570,6 +576,7 @@ struct _virDriver { virDrvDomainSetVcpusFlags domainSetVcpusFlags; virDrvDomainGetVcpusFlags domainGetVcpusFlags; virDrvDomainPinVcpu domainPinVcpu; + virDrvDomainPinVcpuFlags domainPinVcpuFlags;
Please use tab between virDrvDomainPinVcpuFlags and domainPinVcpuFlags.
virDrvDomainGetVcpus domainGetVcpus; virDrvDomainGetMaxVcpus domainGetMaxVcpus; virDrvDomainGetSecurityLabel domainGetSecurityLabel; Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -5461,6 +5461,89 @@ error: }
/** + * virDomainPinVcpuFlags: + * @domain: pointer to domain object, or NULL for Domain0 + * @vcpu: virtual CPU number + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) + * Each bit set to 1 means that corresponding CPU is usable. + * Bytes are stored in little-endian order: CPU0-7, 8-15... + * In each byte, lowest CPU number is least significant bit. + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in + * underlying virtualization system (Xen...). + * If maplen < size, missing bytes are set to zero. + * If maplen > size, failure code is returned. + * @flags: an OR'ed subset of virDomainVcpuFlags + * + * Dynamically change the real CPUs which can be allocated to a virtual CPU. + * This function requires privileged access to the hypervisor. + * + * @flags may include VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. + * Both flags may be set, but VIR_DOMAIN_VCPU_MAXIMUM cannot be set. + * If VIR_DOMAIN_VCPU_LIVE is set, the change affects a running domain + * and may fail if domain is not alive. + * If VIR_DOMAIN_VCPU_CONFIG is set, the change affects persistent state, + * and will fail for transient domains. + * If neither flag is specified (tha is, @flags is VIR_DOMAIN_VCPU_CURRENT),
s/tha/that/
+ * then an inactive domain modifies persistent setup, while an active domain + * is hypervisor-dependent on whether just live or both live and persistent + * state is changed. + * Not all hypervisors can support all flag combinations. + * + * Returns 0 in case of success, -1 in case of failure. + * + */ +int +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, + unsigned char *cpumap, int maplen, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "vcpu=%u, cpumap=%p, maplen=%d flags=%u", s/maplen=%d flags=%u/maplen=%d, flags=%u/
+ vcpu, cpumap, maplen, flags); + + virResetLastError(); + + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + }
Why we check the flags here? We can check it in hypervisor's implementation.
+ + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainPinVcpuFlags) { + int ret; + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags);
There is no need to add space between 'domainPinVcpuFlags' and '(domain', it is old coding style.
+ if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; + +} + +/** * virDomainGetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @info: pointer to an array of virVcpuInfo structures (OUT) Index: libvirt/src/libvirt_public.syms =================================================================== --- libvirt.orig/src/libvirt_public.syms +++ libvirt/src/libvirt_public.syms @@ -436,4 +436,8 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8;
+LIBVIRT_0.9.1 { + virDomainPinVcpuFlags; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... Index: libvirt/src/lxc/lxc_driver.c =================================================================== --- libvirt.orig/src/lxc/lxc_driver.c +++ libvirt/src/lxc/lxc_driver.c @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/openvz/openvz_driver.c =================================================================== --- libvirt.orig/src/openvz/openvz_driver.c +++ libvirt/src/openvz/openvz_driver.c @@ -1598,6 +1598,7 @@ static virDriver openvzDriver = { openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/phyp/phyp_driver.c =================================================================== --- libvirt.orig/src/phyp/phyp_driver.c +++ libvirt/src/phyp/phyp_driver.c @@ -4003,6 +4003,7 @@ static virDriver phypDriver = { phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ phypGetLparCPUMAX, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -6864,6 +6864,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/remote/remote_driver.c =================================================================== --- libvirt.orig/src/remote/remote_driver.c +++ libvirt/src/remote/remote_driver.c @@ -11231,6 +11231,7 @@ static virDriver remote_driver = { remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ remoteDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ remoteDomainGetVcpus, /* domainGetVcpus */ remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/test/test_driver.c =================================================================== --- libvirt.orig/src/test/test_driver.c +++ libvirt/src/test/test_driver.c @@ -5378,6 +5378,7 @@ static virDriver testDriver = { testDomainSetVcpusFlags, /* domainSetVcpusFlags */ testDomainGetVcpusFlags, /* domainGetVcpusFlags */ testDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ testDomainGetVcpus, /* domainGetVcpus */ testDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/uml/uml_driver.c =================================================================== --- libvirt.orig/src/uml/uml_driver.c +++ libvirt/src/uml/uml_driver.c @@ -2184,6 +2184,7 @@ static virDriver umlDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vbox/vbox_tmpl.c =================================================================== --- libvirt.orig/src/vbox/vbox_tmpl.c +++ libvirt/src/vbox/vbox_tmpl.c @@ -8568,6 +8568,7 @@ virDriver NAME(Driver) = { vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vmware/vmware_driver.c =================================================================== --- libvirt.orig/src/vmware/vmware_driver.c +++ libvirt/src/vmware/vmware_driver.c @@ -938,6 +938,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xen/xen_driver.c =================================================================== --- libvirt.orig/src/xen/xen_driver.c +++ libvirt/src/xen/xen_driver.c @@ -2072,6 +2072,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenUnifiedDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenUnifiedDomainGetVcpus, /* domainGetVcpus */ xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xenapi/xenapi_driver.c =================================================================== --- libvirt.orig/src/xenapi/xenapi_driver.c +++ libvirt/src/xenapi/xenapi_driver.c @@ -1820,6 +1820,7 @@ static virDriver xenapiDriver = { xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenapiDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenapiDomainGetVcpus, /* domainGetVcpus */ xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

Index: libvirt/src/lxc/lxc_driver.c =================================================================== --- libvirt.orig/src/lxc/lxc_driver.c +++ libvirt/src/lxc/lxc_driver.c @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */
should also add this line to src/esx/esx_driver.c

于 2011年04月08日 13:20, Taku Izumi 写道:
This patch introduces a new libvirt API (virDomainPinVcpuFlags)
Signed-off-by: Taku Izumi<izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 6 +++ src/driver.h | 7 +++ src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 4 ++ src/lxc/lxc_driver.c | 1 src/openvz/openvz_driver.c | 1 src/phyp/phyp_driver.c | 1 src/qemu/qemu_driver.c | 1 src/remote/remote_driver.c | 1 src/test/test_driver.c | 1 src/uml/uml_driver.c | 1 src/vbox/vbox_tmpl.c | 1 src/vmware/vmware_driver.c | 1 src/xen/xen_driver.c | 1 src/xenapi/xenapi_driver.c | 1 15 files changed, 111 insertions(+)
Lacks of changes on "libxl/libxl_driver.c" for xenlight driver. Regards Osier

Wen-san, Hu-san, Osier-san, Thank you for reviewing. I'll update this. to Wen-san,
+
+ if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + } Why we check the flags here? We can check it in hypervisor's implementation.
We can't use this API with flags except VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. I think validation should be done here.
+ int ret; + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); There is no need to add space between 'domainPinVcpuFlags' and '(domain', it is old coding
+ if (conn->driver->domainPinVcpuFlags) { style.
I intentionally did because such a style is adopted in a lot of other places where drivers' function are invoked. Best regards, Taku Izumi

At 04/11/2011 01:56 PM, Taku Izumi Write:
Wen-san, Hu-san, Osier-san,
Thank you for reviewing. I'll update this.
to Wen-san,
+
+ if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + } Why we check the flags here? We can check it in hypervisor's implementation.
We can't use this API with flags except VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. I think validation should be done here.
The other API virDomain*Flags do not check the flags here. If we do not check it here, it will cause some problems?
+ int ret; + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); There is no need to add space between 'domainPinVcpuFlags' and '(domain', it is old coding
+ if (conn->driver->domainPinVcpuFlags) { style.
I intentionally did because such a style is adopted in a lot of other places where drivers' function are invoked.
Best regards, Taku Izumi

This patch introduces a new libvirt API (virDomainPinVcpuFlags) Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 6 +++ src/driver.h | 7 +++ src/esx/esx_driver.c | 1 src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 4 ++ src/libxl/libxl_driver.c | 1 src/lxc/lxc_driver.c | 1 src/openvz/openvz_driver.c | 1 src/phyp/phyp_driver.c | 1 src/qemu/qemu_driver.c | 1 src/remote/remote_driver.c | 1 src/test/test_driver.c | 1 src/uml/uml_driver.c | 1 src/vbox/vbox_tmpl.c | 1 src/vmware/vmware_driver.c | 1 src/xen/xen_driver.c | 1 src/xenapi/xenapi_driver.c | 1 17 files changed, 113 insertions(+) Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -1018,6 +1018,7 @@ typedef virVcpuInfo *virVcpuInfoPtr; /* Flags for controlling virtual CPU hot-plugging. */ typedef enum { + VIR_DOMAIN_VCPU_CURRENT = 0, /* Affect current domain state */ /* Must choose at least one of these two bits; SetVcpus can choose both */ VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */ VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */ @@ -1038,6 +1039,11 @@ int virDomainPinVcpu unsigned int vcpu, unsigned char *cpumap, int maplen); +int virDomainPinVcpuFlags (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); /** * VIR_USE_CPU: Index: libvirt/src/driver.h =================================================================== --- libvirt.orig/src/driver.h +++ libvirt/src/driver.h @@ -220,6 +220,12 @@ typedef int unsigned char *cpumap, int maplen); typedef int + (*virDrvDomainPinVcpuFlags) (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); +typedef int (*virDrvDomainGetVcpus) (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -570,6 +576,7 @@ struct _virDriver { virDrvDomainSetVcpusFlags domainSetVcpusFlags; virDrvDomainGetVcpusFlags domainGetVcpusFlags; virDrvDomainPinVcpu domainPinVcpu; + virDrvDomainPinVcpuFlags domainPinVcpuFlags; virDrvDomainGetVcpus domainGetVcpus; virDrvDomainGetMaxVcpus domainGetMaxVcpus; virDrvDomainGetSecurityLabel domainGetSecurityLabel; Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -5464,6 +5464,89 @@ error: } /** + * virDomainPinVcpuFlags: + * @domain: pointer to domain object, or NULL for Domain0 + * @vcpu: virtual CPU number + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) + * Each bit set to 1 means that corresponding CPU is usable. + * Bytes are stored in little-endian order: CPU0-7, 8-15... + * In each byte, lowest CPU number is least significant bit. + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in + * underlying virtualization system (Xen...). + * If maplen < size, missing bytes are set to zero. + * If maplen > size, failure code is returned. + * @flags: an OR'ed subset of virDomainVcpuFlags + * + * Dynamically change the real CPUs which can be allocated to a virtual CPU. + * This function requires privileged access to the hypervisor. + * + * @flags may include VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. + * Both flags may be set, but VIR_DOMAIN_VCPU_MAXIMUM cannot be set. + * If VIR_DOMAIN_VCPU_LIVE is set, the change affects a running domain + * and may fail if domain is not alive. + * If VIR_DOMAIN_VCPU_CONFIG is set, the change affects persistent state, + * and will fail for transient domains. + * If neither flag is specified (that is, @flags is VIR_DOMAIN_VCPU_CURRENT), + * then an inactive domain modifies persistent setup, while an active domain + * is hypervisor-dependent on whether just live or both live and persistent + * state is changed. + * Not all hypervisors can support all flag combinations. + * + * Returns 0 in case of success, -1 in case of failure. + * + */ +int +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, + unsigned char *cpumap, int maplen, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "vcpu=%u, cpumap=%p, maplen=%d, flags=%u", + vcpu, cpumap, maplen, flags); + + virResetLastError(); + + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainPinVcpuFlags) { + int ret; + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; + +} + +/** * virDomainGetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @info: pointer to an array of virVcpuInfo structures (OUT) Index: libvirt/src/libvirt_public.syms =================================================================== --- libvirt.orig/src/libvirt_public.syms +++ libvirt/src/libvirt_public.syms @@ -436,4 +436,8 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + virDomainPinVcpuFlags; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... Index: libvirt/src/lxc/lxc_driver.c =================================================================== --- libvirt.orig/src/lxc/lxc_driver.c +++ libvirt/src/lxc/lxc_driver.c @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/openvz/openvz_driver.c =================================================================== --- libvirt.orig/src/openvz/openvz_driver.c +++ libvirt/src/openvz/openvz_driver.c @@ -1598,6 +1598,7 @@ static virDriver openvzDriver = { openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/phyp/phyp_driver.c =================================================================== --- libvirt.orig/src/phyp/phyp_driver.c +++ libvirt/src/phyp/phyp_driver.c @@ -4003,6 +4003,7 @@ static virDriver phypDriver = { phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ phypGetLparCPUMAX, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -6901,6 +6901,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/remote/remote_driver.c =================================================================== --- libvirt.orig/src/remote/remote_driver.c +++ libvirt/src/remote/remote_driver.c @@ -11231,6 +11231,7 @@ static virDriver remote_driver = { remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ remoteDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ remoteDomainGetVcpus, /* domainGetVcpus */ remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/test/test_driver.c =================================================================== --- libvirt.orig/src/test/test_driver.c +++ libvirt/src/test/test_driver.c @@ -5378,6 +5378,7 @@ static virDriver testDriver = { testDomainSetVcpusFlags, /* domainSetVcpusFlags */ testDomainGetVcpusFlags, /* domainGetVcpusFlags */ testDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ testDomainGetVcpus, /* domainGetVcpus */ testDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/uml/uml_driver.c =================================================================== --- libvirt.orig/src/uml/uml_driver.c +++ libvirt/src/uml/uml_driver.c @@ -2184,6 +2184,7 @@ static virDriver umlDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vbox/vbox_tmpl.c =================================================================== --- libvirt.orig/src/vbox/vbox_tmpl.c +++ libvirt/src/vbox/vbox_tmpl.c @@ -8568,6 +8568,7 @@ virDriver NAME(Driver) = { vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vmware/vmware_driver.c =================================================================== --- libvirt.orig/src/vmware/vmware_driver.c +++ libvirt/src/vmware/vmware_driver.c @@ -938,6 +938,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xen/xen_driver.c =================================================================== --- libvirt.orig/src/xen/xen_driver.c +++ libvirt/src/xen/xen_driver.c @@ -2072,6 +2072,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenUnifiedDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenUnifiedDomainGetVcpus, /* domainGetVcpus */ xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xenapi/xenapi_driver.c =================================================================== --- libvirt.orig/src/xenapi/xenapi_driver.c +++ libvirt/src/xenapi/xenapi_driver.c @@ -1820,6 +1820,7 @@ static virDriver xenapiDriver = { xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenapiDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenapiDomainGetVcpus, /* domainGetVcpus */ xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/libxl/libxl_driver.c =================================================================== --- libvirt.orig/src/libxl/libxl_driver.c +++ libvirt/src/libxl/libxl_driver.c @@ -2594,6 +2594,7 @@ static virDriver libxlDriver = { libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ libxlDomainGetVcpusFlags, /* domainGetVcpusFlags */ libxlDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ libxlDomainGetVcpus, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/esx/esx_driver.c =================================================================== --- libvirt.orig/src/esx/esx_driver.c +++ libvirt/src/esx/esx_driver.c @@ -4606,6 +4606,7 @@ static virDriver esxDriver = { esxDomainSetVcpusFlags, /* domainSetVcpusFlags */ esxDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ esxDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */

This patch implements the code to address the new API (virDomainPinVcpuFlags) in the qemu driver. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- src/qemu/qemu_driver.c | 94 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 22 deletions(-) Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -2630,17 +2630,24 @@ qemudDomainSetVcpus(virDomainPtr dom, un static int -qemudDomainPinVcpu(virDomainPtr dom, - unsigned int vcpu, - unsigned char *cpumap, - int maplen) { +qemudDomainPinVcpuFlags(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags) { + struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; + virDomainDefPtr persistentDef = NULL; int maxcpu, hostcpus; virNodeInfo nodeinfo; int ret = -1; + bool isActive; qemuDomainObjPrivatePtr priv; + virCheckFlags(VIR_DOMAIN_VCPU_LIVE | + VIR_DOMAIN_VCPU_CONFIG, -1); + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); qemuDriverUnlock(driver); @@ -2653,7 +2660,15 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (!virDomainObjIsActive(vm)) { + isActive = virDomainObjIsActive(vm); + if (flags == VIR_DOMAIN_VCPU_CURRENT) { + if (isActive) + flags = VIR_DOMAIN_VCPU_LIVE; + else + flags = VIR_DOMAIN_VCPU_CONFIG; + } + + if (!isActive && (flags & VIR_DOMAIN_VCPU_LIVE)) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",_("cannot pin vcpus on an inactive domain")); goto cleanup; @@ -2668,27 +2683,54 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (nodeGetInfo(dom->conn, &nodeinfo) < 0) - goto cleanup; + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + if (!vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot change persistent config of a transient domain")); + goto cleanup; + } + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) + goto cleanup; + } - hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); - maxcpu = maplen * 8; - if (maxcpu > hostcpus) - maxcpu = hostcpus; + if (flags & VIR_DOMAIN_VCPU_LIVE) { - if (priv->vcpupids != NULL) { - if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], - cpumap, maplen, maxcpu) < 0) + if (nodeGetInfo(dom->conn, &nodeinfo) < 0) goto cleanup; - } else { - qemuReportError(VIR_ERR_NO_SUPPORT, - "%s", _("cpu affinity is not supported")); - goto cleanup; + + hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); + maxcpu = maplen * 8; + if (maxcpu > hostcpus) + maxcpu = hostcpus; + + if (priv->vcpupids != NULL) { + if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], + cpumap, maplen, maxcpu) < 0) + goto cleanup; + } else { + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cpu affinity is not supported")); + goto cleanup; + } + + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("failed to update or add vcpupin xml of a running domain")); + goto cleanup; + } + } - if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to update or add vcpupin xml")); + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + + if (virDomainVcpupinAdd(persistentDef, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("failed to update or add vcpupin xml of a persistent domain")); + goto cleanup; + } + ret = virDomainSaveConfig(driver->configDir, persistentDef); goto cleanup; } @@ -2701,6 +2743,14 @@ cleanup: } static int +qemudDomainPinVcpu(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen) { + return qemudDomainPinVcpuFlags(dom, vcpu, cpumap, maplen, VIR_DOMAIN_VCPU_LIVE); +} + +static int qemudDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo, @@ -6864,7 +6914,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ - NULL, /* domainPinVcpuFlags */ + qemudDomainPinVcpuFlags, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */

This patch implements the code to address the new API (virDomainPinVcpuFlags) in the qemu driver. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- src/qemu/qemu_driver.c | 100 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 24 deletions(-) Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -2667,17 +2667,24 @@ qemudDomainSetVcpus(virDomainPtr dom, un static int -qemudDomainPinVcpu(virDomainPtr dom, - unsigned int vcpu, - unsigned char *cpumap, - int maplen) { +qemudDomainPinVcpuFlags(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags) { + struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; + virDomainDefPtr persistentDef = NULL; int maxcpu, hostcpus; virNodeInfo nodeinfo; int ret = -1; + bool isActive; qemuDomainObjPrivatePtr priv; + virCheckFlags(VIR_DOMAIN_VCPU_LIVE | + VIR_DOMAIN_VCPU_CONFIG, -1); + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); qemuDriverUnlock(driver); @@ -2690,9 +2697,18 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s",_("cannot pin vcpus on an inactive domain")); + isActive = virDomainObjIsActive(vm); + if (flags == VIR_DOMAIN_VCPU_CURRENT) { + if (isActive) + flags = VIR_DOMAIN_VCPU_LIVE; + else + flags = VIR_DOMAIN_VCPU_CONFIG; + } + + if (!isActive && (flags & VIR_DOMAIN_VCPU_LIVE)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("a domain is inactive; can change only " + "persistent config")); goto cleanup; } @@ -2705,27 +2721,54 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (nodeGetInfo(dom->conn, &nodeinfo) < 0) - goto cleanup; + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + if (!vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot change persistent config of a transient domain")); + goto cleanup; + } + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) + goto cleanup; + } - hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); - maxcpu = maplen * 8; - if (maxcpu > hostcpus) - maxcpu = hostcpus; + if (flags & VIR_DOMAIN_VCPU_LIVE) { - if (priv->vcpupids != NULL) { - if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], - cpumap, maplen, maxcpu) < 0) + if (nodeGetInfo(dom->conn, &nodeinfo) < 0) goto cleanup; - } else { - qemuReportError(VIR_ERR_NO_SUPPORT, - "%s", _("cpu affinity is not supported")); - goto cleanup; + + hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); + maxcpu = maplen * 8; + if (maxcpu > hostcpus) + maxcpu = hostcpus; + + if (priv->vcpupids != NULL) { + if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], + cpumap, maplen, maxcpu) < 0) + goto cleanup; + } else { + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cpu affinity is not supported")); + goto cleanup; + } + + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to update or add vcpupin xml of " + "a running domain")); + goto cleanup; + } + } - if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to update or add vcpupin xml")); + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + + if (virDomainVcpupinAdd(persistentDef, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to update or add vcpupin xml of " + "a persistent domain")); + goto cleanup; + } + ret = virDomainSaveConfig(driver->configDir, persistentDef); goto cleanup; } @@ -2738,6 +2781,15 @@ cleanup: } static int +qemudDomainPinVcpu(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen) { + return qemudDomainPinVcpuFlags(dom, vcpu, cpumap, maplen, + VIR_DOMAIN_VCPU_LIVE); +} + +static int qemudDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo, @@ -6901,7 +6953,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ - NULL, /* domainPinVcpuFlags */ + qemudDomainPinVcpuFlags, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */

This patch implements the remote protocol to address the new API (virDomainPinVcpuFlags). Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- daemon/remote.c | 37 +++++++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 daemon/remote_dispatch_prototypes.h | 8 +++++++ daemon/remote_dispatch_table.h | 5 ++++ src/remote/remote_driver.c | 40 +++++++++++++++++++++++++++++++++++- src/remote/remote_protocol.c | 16 ++++++++++++++ src/remote/remote_protocol.h | 14 ++++++++++++ src/remote/remote_protocol.x | 10 ++++++++- src/remote_protocol-structs | 9 ++++++++ 9 files changed, 138 insertions(+), 2 deletions(-) Index: libvirt/daemon/remote.c =================================================================== --- libvirt.orig/daemon/remote.c +++ libvirt/daemon/remote.c @@ -2196,6 +2196,43 @@ remoteDispatchDomainPinVcpu (struct qemu } static int +remoteDispatchDomainPinVcpuFlags (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_pin_vcpu_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + int rv; + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) { + virDomainFree(dom); + remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX")); + return -1; + } + + rv = virDomainPinVcpuFlags (dom, args->vcpu, + (unsigned char *) args->cpumap.cpumap_val, + args->cpumap.cpumap_len, + args->flags); + if (rv == -1) { + remoteDispatchConnError(rerr, conn); + virDomainFree(dom); + return -1; + } + virDomainFree(dom); + return 0; +} + +static int remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, Index: libvirt/daemon/remote_dispatch_args.h =================================================================== --- libvirt.orig/daemon/remote_dispatch_args.h +++ libvirt/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_pin_vcpu_flags_args val_remote_domain_pin_vcpu_flags_args; Index: libvirt/daemon/remote_dispatch_prototypes.h =================================================================== --- libvirt.orig/daemon/remote_dispatch_prototypes.h +++ libvirt/daemon/remote_dispatch_prototypes.h @@ -506,6 +506,14 @@ static int remoteDispatchDomainPinVcpu( remote_error *err, remote_domain_pin_vcpu_args *args, void *ret); +static int remoteDispatchDomainPinVcpuFlags( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_pin_vcpu_flags_args *args, + void *ret); static int remoteDispatchDomainReboot( struct qemud_server *server, struct qemud_client *client, Index: libvirt/daemon/remote_dispatch_table.h =================================================================== --- libvirt.orig/daemon/remote_dispatch_table.h +++ libvirt/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainPinVcpuFlags => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainPinVcpuFlags, + .args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, + .ret_filter = (xdrproc_t) xdr_void, +}, Index: libvirt/src/remote/remote_driver.c =================================================================== --- libvirt.orig/src/remote/remote_driver.c +++ libvirt/src/remote/remote_driver.c @@ -3046,6 +3046,44 @@ done: } static int +remoteDomainPinVcpuFlags (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags) +{ + int rv = -1; + remote_domain_pin_vcpu_flags_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + if (maplen > REMOTE_CPUMAP_MAX) { + remoteError(VIR_ERR_RPC, + _("map length greater than maximum: %d > %d"), + maplen, REMOTE_CPUMAP_MAX); + goto done; + } + + make_nonnull_domain (&args.dom, domain); + args.vcpu = vcpu; + args.cpumap.cpumap_len = maplen; + args.cpumap.cpumap_val = (char *) cpumap; + args.flags = flags; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS, + (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteDomainGetVcpus (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -11231,7 +11269,7 @@ static virDriver remote_driver = { remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ remoteDomainPinVcpu, /* domainPinVcpu */ - NULL, /* domainPinVcpuFlags */ + remoteDomainPinVcpuFlags, /* domainPinVcpuFlags */ remoteDomainGetVcpus, /* domainGetVcpus */ remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/remote/remote_protocol.c =================================================================== --- libvirt.orig/src/remote/remote_protocol.c +++ libvirt/src/remote/remote_protocol.c @@ -1521,6 +1521,22 @@ xdr_remote_domain_pin_vcpu_args (XDR *xd } bool_t +xdr_remote_domain_pin_vcpu_flags_args (XDR *xdrs, remote_domain_pin_vcpu_flags_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cpumap.cpumap_val; + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_int (xdrs, &objp->vcpu)) + return FALSE; + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cpumap.cpumap_len, REMOTE_CPUMAP_MAX)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_get_vcpus_args (XDR *xdrs, remote_domain_get_vcpus_args *objp) { Index: libvirt/src/remote/remote_protocol.h =================================================================== --- libvirt.orig/src/remote/remote_protocol.h +++ libvirt/src/remote/remote_protocol.h @@ -841,6 +841,17 @@ struct remote_domain_pin_vcpu_args { }; typedef struct remote_domain_pin_vcpu_args remote_domain_pin_vcpu_args; +struct remote_domain_pin_vcpu_flags_args { + remote_nonnull_domain dom; + int vcpu; + struct { + u_int cpumap_len; + char *cpumap_val; + } cpumap; + u_int flags; +}; +typedef struct remote_domain_pin_vcpu_flags_args remote_domain_pin_vcpu_flags_args; + struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo; @@ -2413,6 +2424,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 210, }; typedef enum remote_procedure remote_procedure; @@ -2566,6 +2578,7 @@ extern bool_t xdr_remote_domain_set_vcp extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*); extern bool_t xdr_remote_domain_get_vcpus_flags_ret (XDR *, remote_domain_get_vcpus_flags_ret*); extern bool_t xdr_remote_domain_pin_vcpu_args (XDR *, remote_domain_pin_vcpu_args*); +extern bool_t xdr_remote_domain_pin_vcpu_flags_args (XDR *, remote_domain_pin_vcpu_flags_args*); extern bool_t xdr_remote_domain_get_vcpus_args (XDR *, remote_domain_get_vcpus_args*); extern bool_t xdr_remote_domain_get_vcpus_ret (XDR *, remote_domain_get_vcpus_ret*); extern bool_t xdr_remote_domain_get_max_vcpus_args (XDR *, remote_domain_get_max_vcpus_args*); @@ -2923,6 +2936,7 @@ extern bool_t xdr_remote_domain_set_vcpu extern bool_t xdr_remote_domain_get_vcpus_flags_args (); extern bool_t xdr_remote_domain_get_vcpus_flags_ret (); extern bool_t xdr_remote_domain_pin_vcpu_args (); +extern bool_t xdr_remote_domain_pin_vcpu_flags_args (); extern bool_t xdr_remote_domain_get_vcpus_args (); extern bool_t xdr_remote_domain_get_vcpus_ret (); extern bool_t xdr_remote_domain_get_max_vcpus_args (); Index: libvirt/src/remote/remote_protocol.x =================================================================== --- libvirt.orig/src/remote/remote_protocol.x +++ libvirt/src/remote/remote_protocol.x @@ -843,6 +843,13 @@ struct remote_domain_pin_vcpu_args { opaque cpumap<REMOTE_CPUMAP_MAX>; }; +struct remote_domain_pin_vcpu_flags_args { + remote_nonnull_domain dom; + int vcpu; + opaque cpumap<REMOTE_CPUMAP_MAX>; + unsigned int flags; +}; + struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo; @@ -2176,7 +2183,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 210 /* * Notice how the entries are grouped in sets of 10 ? Index: libvirt/src/remote_protocol-structs =================================================================== --- libvirt.orig/src/remote_protocol-structs +++ libvirt/src/remote_protocol-structs @@ -528,6 +528,15 @@ struct remote_domain_pin_vcpu_args { char * cpumap_val; } cpumap; }; +struct remote_domain_pin_vcpu_flags_args { + remote_nonnull_domain dom; + int vcpu; + struct { + u_int cpumap_len; + char * cpumap_val; + } cpumap; + u_int flags; +}; struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo;

Index: libvirt/daemon/remote_dispatch_table.h
This file is generated automatically, update src/remote/remote_protocol.x instead.
=================================================================== --- libvirt.orig/daemon/remote_dispatch_table.h +++ libvirt/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainPinVcpuFlags => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainPinVcpuFlags, + .args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, + .ret_filter = (xdrproc_t) xdr_void, +},

This patch adds the new option (--live, --config and --current) to "virsh vcpupin" command. The behavior of above aption is the same as that of "virsh setmem", "virsh setvcpus", and whatnot. When the --config option is specified, the command affects a persistent domain, while --live option is specified, it affects a running (live) domain. The --current option cannot be used with --config or --live at the same time, and when --current is specified, it affects a "current" domain. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- tools/virsh.c | 33 +++++++++++++++++++++++++++++++-- tools/virsh.pod | 8 +++++++- 2 files changed, 38 insertions(+), 3 deletions(-) Index: libvirt/tools/virsh.c =================================================================== --- libvirt.orig/tools/virsh.c +++ libvirt/tools/virsh.c @@ -2721,6 +2721,9 @@ static const vshCmdOptDef opts_vcpupin[] {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"vcpu", VSH_OT_INT, VSH_OFLAG_REQ, N_("vcpu number")}, {"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, N_("host cpu number(s) (comma separated)")}, + {"config", VSH_OT_BOOL, 0, N_("affect next boot")}, + {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, + {"current", VSH_OT_BOOL, 0, N_("affect current domain")}, {NULL, 0, 0, NULL} }; @@ -2737,6 +2740,26 @@ cmdVcpupin(vshControl *ctl, const vshCmd int cpumaplen; int i; enum { expect_num, expect_num_or_comma } state; + int config = vshCommandOptBool(cmd, "config"); + int live = vshCommandOptBool(cmd, "live"); + int current = vshCommandOptBool(cmd, "current"); + int flags = 0; + + if (current) { + if (live || config) { + vshError(ctl, "%s", _("--current must be specified exclusively")); + return FALSE; + } + flags = VIR_DOMAIN_VCPU_CURRENT; + } else { + if (config) + flags |= VIR_DOMAIN_VCPU_CONFIG; + if (live) + flags |= VIR_DOMAIN_VCPU_LIVE; + /* neither option is specified */ + if (!live && !config) + flags = -1; + } if (!vshConnectionUsability(ctl, ctl->conn)) return FALSE; @@ -2833,8 +2856,14 @@ cmdVcpupin(vshControl *ctl, const vshCmd cpulist++; } while (cpulist); - if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) { - ret = FALSE; + if (flags == -1) { + if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) { + ret = FALSE; + } + } else { + if (virDomainPinVcpuFlags(dom, vcpu, cpumap, cpumaplen, flags) != 0) { + ret = FALSE; + } } VIR_FREE(cpumap); Index: libvirt/tools/virsh.pod =================================================================== --- libvirt.orig/tools/virsh.pod +++ libvirt/tools/virsh.pod @@ -749,10 +749,16 @@ values; these two flags cannot both be s Returns basic information about the domain virtual CPUs, like the number of vCPUs, the running time, the affinity to physical processors. -=item B<vcpupin> I<domain-id> I<vcpu> I<cpulist> +=item B<vcpupin> I<domain-id> I<vcpu> I<cpulist> optional I<--live> I<--config> +I<--current> Pin domain VCPUs to host physical CPUs. The I<vcpu> number must be provided and I<cpulist> is a comma separated list of physical CPU numbers. +If I<--live> is specified, affect a running guest. +If I<--config> is specified, affect the next boot of a persistent guest. +If I<--current> is specified, affect the current guest state. +Both I<--live> and I<--config> flags may be given, but I<--current> is exclusive. +If no flag is specified, behavior is different depending on hypervisor. =item B<vncdisplay> I<domain-id>

On Fri, Apr 08, 2011 at 02:14:07PM +0900, Taku Izumi wrote:
Hi all,
This patchset enables us to configure inactive domains' CPU affinity setting.
The basic technique is the same as that of "virsh setmem" command. => http://www.redhat.com/archives/libvir-list/2011-March/msg00013.html
v1 -> v2: - recreate based on 0.9.0 - add "CURRENT" mode
*[PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) *[PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver *[PATCH 3/4] vcpupin: implement the remote protocol to address the new API *[PATCH 4/4] vcpupin: add the new options to "virsh vcpupin" command
Best regards, Taku Izumi
Two suggestions: - when vcpupin an inactive domain, it gives an error message like this: error: Requested operation is not valid: cannot pin vcpus on an inactive domain After applying this series, this is not true anymore. I think a message like this is more helpful: Failed to pin vcpus on inactive domain, please check the --config option. - While it can vcpupin an inactive domain, it seems reasonable to be able to view vcpuinfo of inactive domain, so would a patch to vcpuinfo command be included?

Two suggestions:
- when vcpupin an inactive domain, it gives an error message like this:
error: Requested operation is not valid: cannot pin vcpus on an inactive domain
After applying this series, this is not true anymore. I think a message like this is more helpful:
Failed to pin vcpus on inactive domain, please check the --config option.
I think your pointing out is reasonable, I'll change that message.
- While it can vcpupin an inactive domain, it seems reasonable to be able to view vcpuinfo of inactive domain, so would a patch to vcpuinfo command be included?
I shelve that work. Probably that patch should be separated. Best regards, Taku Izumi
participants (4)
-
Hu Tao
-
Osier Yang
-
Taku Izumi
-
Wen Congyang