# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1210241758 -3600
# Node ID 5c3df1bded8249219dfae4f5a9820636f73aa944
# Parent d7dbae33e81d45c86a0a02cc1537144351e38df8
xend: Improve "cpus" parameter to be able to define CPU affinities for each VCPU
If we define the form of list of string to "cpus" parameter,
different CPU affinities are set for each VCPU as follows.
# grep cpus /etc/xen/vm1
cpus = ["2", "3"]
vcpus = 2
# xm create vm1
Using config file "/etc/xen/vm1".
Started domain vm1
# xm vcpu-list vm1
Name ID VCPU CPU State Time(s)
CPU Affinity
vm1 1 0 2 r-- 3.5 2
vm1 1 1 3 -b- 3.2 3
If we define the form of string to "cpus" parameter as before,
a same CPU affinity is set for each VCPU as follows.
# grep cpus /etc/xen/vm2
cpus = "2,3"
vcpus = 2
# xm create vm2
Using config file "/etc/xen/vm2".
Started domain vm2
# xm vcpu-list vm2
Name ID VCPU CPU State Time(s)
CPU Affinity
vm2 2 0 3 -b- 3.0
2-3
vm2 2 1 2 r-- 2.6
2-3
Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
---
tools/python/xen/xend/XendConfig.py | 108 +++++++++++++++++++++-----------
tools/python/xen/xend/XendDomain.py | 31 ++++-----
tools/python/xen/xend/XendDomainInfo.py | 23 +++++-
3 files changed, 106 insertions(+), 56 deletions(-)
diff -r d7dbae33e81d -r 5c3df1bded82 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Thu May 08 11:13:51 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py Thu May 08 11:15:58 2008 +0100
@@ -640,46 +640,84 @@ class XendConfig(dict):
else:
cfg['cpus'] = str(cfg['cpu'])
- # Convert 'cpus' to list of ints
+ # Convert 'cpus' to list of list of ints
+ cpus_list = []
if 'cpus' in cfg:
- cpus = []
+ # Convert the following string to list of ints.
+ # The string supports a list of ranges (0-3),
+ # seperated by commas, and negation (^1).
+ # Precedence is settled by order of the string:
+ # "0-3,^1" -> [0,2,3]
+ # "0-3,^1,1" -> [0,1,2,3]
+ def cnv(s):
+ l = []
+ for c in s.split(','):
+ if c.find('-') != -1:
+ (x, y) = c.split('-')
+ for i in range(int(x), int(y)+1):
+ l.append(int(i))
+ else:
+ # remove this element from the list
+ if c[0] == '^':
+ l = [x for x in l if x != int(c[1:])]
+ else:
+ l.append(int(c))
+ return l
+
if type(cfg['cpus']) == list:
- # If sxp_cfg was created from config.sxp,
- # the form of 'cpus' is list of string.
- # Convert 'cpus' to list of ints.
- # ['1'] -> [1]
- # ['0','2','3'] -> [0,2,3]
+ if len(cfg['cpus']) > 0 and type(cfg['cpus'][0]) == list:
+ # If sxp_cfg was created from config.sxp,
+ # the form of 'cpus' is list of list of string.
+ # Convert 'cpus' to list of list of ints.
+ # Conversion examples:
+ # [['1']] -> [[1]]
+ # [['0','2'],['1','3']] -> [[0,2],[1,3]]
+ try:
+ for c1 in cfg['cpus']:
+ cpus = []
+ for c2 in c1:
+ cpus.append(int(c2))
+ cpus_list.append(cpus)
+ except ValueError, e:
+ raise XendConfigError('cpus = %s: %s' % (cfg['cpus'],
e))
+ else:
+ # Conversion examples:
+ # ["1"] -> [[1]]
+ # ["0,2","1,3"] -> [[0,2],[1,3]]
+ # ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]]
+ try:
+ for c in cfg['cpus']:
+ cpus = cnv(c)
+ cpus_list.append(cpus)
+ except ValueError, e:
+ raise XendConfigError('cpus = %s: %s' % (cfg['cpus'],
e))
+
+ if len(cpus_list) != cfg['vcpus']:
+ raise XendConfigError('vcpus and the item number of cpus
are not same')
+ else:
+ # Conversion examples:
+ # vcpus=1:
+ # "1" -> [[1]]
+ # "0-3,^1" -> [[0,2,3]]
+ # vcpus=2:
+ # "1" -> [[1],[1]]
+ # "0-3,^1" -> [[0,2,3],[0,2,3]]
try:
- for c in cfg['cpus']:
- cpus.append(int(c))
-
- cfg['cpus'] = cpus
+ cpus = cnv(cfg['cpus'])
+ for v in range(0, cfg['vcpus']):
+ cpus_list.append(cpus)
except ValueError, e:
raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
- else:
- # Convert 'cpus' string to list of ints
- # 'cpus' supports a list of ranges (0-3),
- # seperated by commas, and negation, (^1).
- # Precedence is settled by order of the
- # string:
- # "0-3,^1" -> [0,2,3]
- # "0-3,^1,1" -> [0,1,2,3]
- try:
- for c in cfg['cpus'].split(','):
- if c.find('-') != -1:
- (x, y) = c.split('-')
- for i in range(int(x), int(y)+1):
- cpus.append(int(i))
- else:
- # remove this element from the list
- if c[0] == '^':
- cpus = [x for x in cpus if x != int(c[1:])]
- else:
- cpus.append(int(c))
-
- cfg['cpus'] = cpus
- except ValueError, e:
- raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
+ else:
+ # Generation examples:
+ # vcpus=1:
+ # -> [[]]
+ # vcpus=2:
+ # -> [[],[]]
+ for v in range(0, cfg['vcpus']):
+ cpus_list.append(list())
+
+ cfg['cpus'] = cpus_list
# Parse cpuid
if 'cpuid' in cfg:
diff -r d7dbae33e81d -r 5c3df1bded82 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Thu May 08 11:13:51 2008 +0100
+++ b/tools/python/xen/xend/XendDomain.py Thu May 08 11:15:58 2008 +0100
@@ -1365,28 +1365,25 @@ class XendDomain:
raise XendInvalidDomain(str(domid))
# if vcpu is keyword 'all', apply the cpumap to all vcpus
- vcpus = [ vcpu ]
if str(vcpu).lower() == "all":
vcpus = range(0, int(dominfo.getVCpuCount()))
+ else:
+ vcpus = [ int(vcpu) ]
# set the same cpumask for all vcpus
rc = 0
- if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
- for v in vcpus:
- try:
- rc = xc.vcpu_setaffinity(dominfo.getDomid(), int(v),
cpumap)
- except Exception, ex:
- log.exception(ex)
- raise XendError("Cannot pin vcpu: %s to cpu: %s - %s" % \
- (v, cpumap, str(ex)))
- else:
- # FIXME: if we could define cpu affinity definitions to
- # each vcpu, reprogram the following processing.
- if str(vcpu).lower() != "all":
- raise XendError("Must specify 'all' to VCPU "
- "for inactive managed domains")
- dominfo.setCpus(cpumap)
- self.managed_config_save(dominfo)
+ cpus = dominfo.getCpus()
+ for v in vcpus:
+ try:
+ if dominfo._stateGet() in (DOM_STATE_RUNNING,
DOM_STATE_PAUSED):
+ rc = xc.vcpu_setaffinity(dominfo.getDomid(), v, cpumap)
+ cpus[v] = cpumap
+ except Exception, ex:
+ log.exception(ex)
+ raise XendError("Cannot pin vcpu: %d to cpu: %s - %s" % \
+ (v, cpumap, str(ex)))
+ dominfo.setCpus(cpus)
+ self.managed_config_save(dominfo)
return rc
diff -r d7dbae33e81d -r 5c3df1bded82 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu May 08 11:13:51 2008 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu May 08 11:15:58 2008 +0100
@@ -1051,8 +1051,8 @@ class XendDomainInfo:
['running', 0],
['cpu_time', 0.0],
['cpu', -1],
- ['cpumap', self.info['cpus'] and \
- self.info['cpus'] or range(64)]])
+ ['cpumap', self.info['cpus'][i] and \
+ self.info['cpus'][i] or
range(64)]])
return sxpr
@@ -1477,6 +1477,13 @@ class XendDomainInfo:
self.info['VCPUs_live'] = vcpus
self._writeDom(self._vcpuDomDetails())
else:
+ if self.info['VCPUs_max'] > vcpus:
+ # decreasing
+ del self.info['cpus'][vcpus:]
+ elif self.info['VCPUs_max'] < vcpus:
+ # increasing
+ for c in range(self.info['VCPUs_max'], vcpus):
+ self.info['cpus'].append(list())
self.info['VCPUs_max'] = vcpus
xen.xend.XendDomain.instance().managed_config_save(self)
log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
@@ -2071,9 +2078,17 @@ class XendDomainInfo:
# repin domain vcpus if a restricted cpus list is provided
# this is done prior to memory allocation to aide in memory
# distribution for NUMA systems.
- if self.info['cpus'] is not None and len(self.info['cpus']) > 0:
+ def has_cpus():
+ if self.info['cpus'] is not None:
+ for c in self.info['cpus']:
+ if c:
+ return True
+ return False
+
+ if has_cpus():
for v in range(0, self.info['VCPUs_max']):
- xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
+ if self.info['cpus'][v]:
+ xc.vcpu_setaffinity(self.domid, v,
self.info['cpus'][v])
else:
def find_relaxed_node(node_list):
import sys
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|