ia64/xen-unstable

changeset 17609:5c3df1bded82

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@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 08 11:15:58 2008 +0100 (2008-05-08)
parents d7dbae33e81d
children 3a1758f420d3
files tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/tools/python/xen/xend/XendConfig.py	Thu May 08 11:13:51 2008 +0100
     1.2 +++ b/tools/python/xen/xend/XendConfig.py	Thu May 08 11:15:58 2008 +0100
     1.3 @@ -640,46 +640,84 @@ class XendConfig(dict):
     1.4              else:
     1.5                  cfg['cpus'] = str(cfg['cpu'])
     1.6  
     1.7 -        # Convert 'cpus' to list of ints
     1.8 +        # Convert 'cpus' to list of list of ints
     1.9 +        cpus_list = []
    1.10          if 'cpus' in cfg:
    1.11 -            cpus = []
    1.12 +            # Convert the following string to list of ints.
    1.13 +            # The string supports a list of ranges (0-3),
    1.14 +            # seperated by commas, and negation (^1).  
    1.15 +            # Precedence is settled by order of the string:
    1.16 +            #    "0-3,^1"      -> [0,2,3]
    1.17 +            #    "0-3,^1,1"    -> [0,1,2,3]
    1.18 +            def cnv(s):
    1.19 +                l = []
    1.20 +                for c in s.split(','):
    1.21 +                    if c.find('-') != -1:
    1.22 +                        (x, y) = c.split('-')
    1.23 +                        for i in range(int(x), int(y)+1):
    1.24 +                            l.append(int(i))
    1.25 +                    else:
    1.26 +                        # remove this element from the list 
    1.27 +                        if c[0] == '^':
    1.28 +                            l = [x for x in l if x != int(c[1:])]
    1.29 +                        else:
    1.30 +                            l.append(int(c))
    1.31 +                return l
    1.32 +            
    1.33              if type(cfg['cpus']) == list:
    1.34 -                # If sxp_cfg was created from config.sxp,
    1.35 -                # the form of 'cpus' is list of string.
    1.36 -                # Convert 'cpus' to list of ints.
    1.37 -                #    ['1']         -> [1]
    1.38 -                #    ['0','2','3'] -> [0,2,3]
    1.39 +                if len(cfg['cpus']) > 0 and type(cfg['cpus'][0]) == list:
    1.40 +                    # If sxp_cfg was created from config.sxp,
    1.41 +                    # the form of 'cpus' is list of list of string.
    1.42 +                    # Convert 'cpus' to list of list of ints.
    1.43 +                    # Conversion examples:
    1.44 +                    #    [['1']]               -> [[1]]
    1.45 +                    #    [['0','2'],['1','3']] -> [[0,2],[1,3]]
    1.46 +                    try:
    1.47 +                        for c1 in cfg['cpus']:
    1.48 +                            cpus = []
    1.49 +                            for c2 in c1:
    1.50 +                                cpus.append(int(c2))
    1.51 +                            cpus_list.append(cpus)
    1.52 +                    except ValueError, e:
    1.53 +                        raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
    1.54 +                else:
    1.55 +                    # Conversion examples:
    1.56 +                    #    ["1"]               -> [[1]]
    1.57 +                    #    ["0,2","1,3"]       -> [[0,2],[1,3]]
    1.58 +                    #    ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]]
    1.59 +                    try:
    1.60 +                        for c in cfg['cpus']:
    1.61 +                            cpus = cnv(c)
    1.62 +                            cpus_list.append(cpus)
    1.63 +                    except ValueError, e:
    1.64 +                        raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
    1.65 +                
    1.66 +                if len(cpus_list) != cfg['vcpus']:
    1.67 +                    raise XendConfigError('vcpus and the item number of cpus are not same')
    1.68 +            else:
    1.69 +                # Conversion examples:
    1.70 +                #  vcpus=1:
    1.71 +                #    "1"      -> [[1]]
    1.72 +                #    "0-3,^1" -> [[0,2,3]]
    1.73 +                #  vcpus=2:
    1.74 +                #    "1"      -> [[1],[1]]
    1.75 +                #    "0-3,^1" -> [[0,2,3],[0,2,3]]
    1.76                  try:
    1.77 -                    for c in cfg['cpus']:
    1.78 -                        cpus.append(int(c))
    1.79 -                    
    1.80 -                    cfg['cpus'] = cpus
    1.81 +                    cpus = cnv(cfg['cpus'])
    1.82 +                    for v in range(0, cfg['vcpus']):
    1.83 +                        cpus_list.append(cpus)
    1.84                  except ValueError, e:
    1.85                      raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
    1.86 -            else:
    1.87 -                # Convert 'cpus' string to list of ints
    1.88 -                # 'cpus' supports a list of ranges (0-3),
    1.89 -                # seperated by commas, and negation, (^1).  
    1.90 -                # Precedence is settled by order of the 
    1.91 -                # string:
    1.92 -                #    "0-3,^1"      -> [0,2,3]
    1.93 -                #    "0-3,^1,1"    -> [0,1,2,3]
    1.94 -                try:
    1.95 -                    for c in cfg['cpus'].split(','):
    1.96 -                        if c.find('-') != -1:             
    1.97 -                            (x, y) = c.split('-')
    1.98 -                            for i in range(int(x), int(y)+1):
    1.99 -                                cpus.append(int(i))
   1.100 -                        else:
   1.101 -                            # remove this element from the list 
   1.102 -                            if c[0] == '^':
   1.103 -                                cpus = [x for x in cpus if x != int(c[1:])]
   1.104 -                            else:
   1.105 -                                cpus.append(int(c))
   1.106 -                    
   1.107 -                    cfg['cpus'] = cpus
   1.108 -                except ValueError, e:
   1.109 -                    raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
   1.110 +        else:
   1.111 +            # Generation examples:
   1.112 +            #  vcpus=1:
   1.113 +            #    -> [[]]
   1.114 +            #  vcpus=2:
   1.115 +            #    -> [[],[]]
   1.116 +            for v in range(0, cfg['vcpus']):
   1.117 +                cpus_list.append(list())
   1.118 +        
   1.119 +        cfg['cpus'] = cpus_list
   1.120  
   1.121          # Parse cpuid
   1.122          if 'cpuid' in cfg:
     2.1 --- a/tools/python/xen/xend/XendDomain.py	Thu May 08 11:13:51 2008 +0100
     2.2 +++ b/tools/python/xen/xend/XendDomain.py	Thu May 08 11:15:58 2008 +0100
     2.3 @@ -1365,28 +1365,25 @@ class XendDomain:
     2.4              raise XendInvalidDomain(str(domid))
     2.5  
     2.6          # if vcpu is keyword 'all', apply the cpumap to all vcpus
     2.7 -        vcpus = [ vcpu ]
     2.8          if str(vcpu).lower() == "all":
     2.9              vcpus = range(0, int(dominfo.getVCpuCount()))
    2.10 +        else:
    2.11 +            vcpus = [ int(vcpu) ]
    2.12         
    2.13          # set the same cpumask for all vcpus
    2.14          rc = 0
    2.15 -        if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
    2.16 -            for v in vcpus:
    2.17 -                try:
    2.18 -                    rc = xc.vcpu_setaffinity(dominfo.getDomid(), int(v), cpumap)
    2.19 -                except Exception, ex:
    2.20 -                    log.exception(ex)
    2.21 -                    raise XendError("Cannot pin vcpu: %s to cpu: %s - %s" % \
    2.22 -                                    (v, cpumap, str(ex)))
    2.23 -        else:
    2.24 -            # FIXME: if we could define cpu affinity definitions to
    2.25 -            #        each vcpu, reprogram the following processing.
    2.26 -            if str(vcpu).lower() != "all":
    2.27 -                raise XendError("Must specify 'all' to VCPU "
    2.28 -                                "for inactive managed domains")
    2.29 -            dominfo.setCpus(cpumap)
    2.30 -            self.managed_config_save(dominfo)
    2.31 +        cpus = dominfo.getCpus()
    2.32 +        for v in vcpus:
    2.33 +            try:
    2.34 +                if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
    2.35 +                    rc = xc.vcpu_setaffinity(dominfo.getDomid(), v, cpumap)
    2.36 +                cpus[v] = cpumap
    2.37 +            except Exception, ex:
    2.38 +                log.exception(ex)
    2.39 +                raise XendError("Cannot pin vcpu: %d to cpu: %s - %s" % \
    2.40 +                                (v, cpumap, str(ex)))
    2.41 +        dominfo.setCpus(cpus)
    2.42 +        self.managed_config_save(dominfo)
    2.43  
    2.44          return rc
    2.45  
     3.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu May 08 11:13:51 2008 +0100
     3.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu May 08 11:15:58 2008 +0100
     3.3 @@ -1051,8 +1051,8 @@ class XendDomainInfo:
     3.4                                   ['running',  0],
     3.5                                   ['cpu_time', 0.0],
     3.6                                   ['cpu',      -1],
     3.7 -                                 ['cpumap',   self.info['cpus'] and \
     3.8 -                                              self.info['cpus'] or range(64)]])
     3.9 +                                 ['cpumap',   self.info['cpus'][i] and \
    3.10 +                                              self.info['cpus'][i] or range(64)]])
    3.11  
    3.12              return sxpr
    3.13  
    3.14 @@ -1477,6 +1477,13 @@ class XendDomainInfo:
    3.15                  self.info['VCPUs_live'] = vcpus
    3.16                  self._writeDom(self._vcpuDomDetails())
    3.17          else:
    3.18 +            if self.info['VCPUs_max'] > vcpus:
    3.19 +                # decreasing
    3.20 +                del self.info['cpus'][vcpus:]
    3.21 +            elif self.info['VCPUs_max'] < vcpus:
    3.22 +                # increasing
    3.23 +                for c in range(self.info['VCPUs_max'], vcpus):
    3.24 +                    self.info['cpus'].append(list())
    3.25              self.info['VCPUs_max'] = vcpus
    3.26              xen.xend.XendDomain.instance().managed_config_save(self)
    3.27          log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
    3.28 @@ -2071,9 +2078,17 @@ class XendDomainInfo:
    3.29              # repin domain vcpus if a restricted cpus list is provided
    3.30              # this is done prior to memory allocation to aide in memory
    3.31              # distribution for NUMA systems.
    3.32 -            if self.info['cpus'] is not None and len(self.info['cpus']) > 0:
    3.33 +            def has_cpus():
    3.34 +                if self.info['cpus'] is not None:
    3.35 +                    for c in self.info['cpus']:
    3.36 +                        if c:
    3.37 +                            return True
    3.38 +                return False
    3.39 +
    3.40 +            if has_cpus():
    3.41                  for v in range(0, self.info['VCPUs_max']):
    3.42 -                    xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
    3.43 +                    if self.info['cpus'][v]:
    3.44 +                        xc.vcpu_setaffinity(self.domid, v, self.info['cpus'][v])
    3.45              else:
    3.46                  def find_relaxed_node(node_list):
    3.47                      import sys