ia64/xen-unstable

changeset 7348:067b9aacb6c2

Fix deadlock in XendDomainInfo when a domain is cleaned up. We are renaming
the domain, to make it clear that it is a zombie, but this renaming cannot
check the uniqueness of the new name, because this causes a deadlock with
XendDomain. Instead, we allow the name to be non-unique for the case of
zombie domains.

Change the locking in waitForShutdown and state_set to be robust in the face of
exceptions.

Rename the STATE_VM_ constants to STATE_DOM_.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Wed Oct 12 10:11:35 2005 +0100 (2005-10-12)
parents 00a24908057f
children b3a255e88810
files tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomain.py	Wed Oct 12 10:08:01 2005 +0100
     1.2 +++ b/tools/python/xen/xend/XendDomain.py	Wed Oct 12 10:11:35 2005 +0100
     1.3 @@ -57,7 +57,7 @@ class XendDomain:
     1.4          # So we stuff the XendDomain instance (self) into xroot's components.
     1.5          xroot.add_component("xen.xend.XendDomain", self)
     1.6          self.domains = {}
     1.7 -        self.domains_lock = threading.Condition()
     1.8 +        self.domains_lock = threading.RLock()
     1.9          self.watchReleaseDomain()
    1.10  
    1.11          self.domains_lock.acquire()
    1.12 @@ -318,7 +318,7 @@ class XendDomain:
    1.13              n = len(matching)
    1.14              if n == 1:
    1.15                  return matching[0]
    1.16 -            elif n > 1:
    1.17 +            elif n > 1 and not d.isTerminated():
    1.18                  log.error('Name uniqueness has been violated for name %s!  '
    1.19                            'Recovering by renaming:', name)
    1.20                  for d in matching:
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Wed Oct 12 10:08:01 2005 +0100
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Wed Oct 12 10:11:35 2005 +0100
     2.3 @@ -78,8 +78,8 @@ restart_modes = [
     2.4      "rename-restart"
     2.5      ]
     2.6  
     2.7 -STATE_VM_OK         = "ok"
     2.8 -STATE_VM_TERMINATED = "terminated"
     2.9 +STATE_DOM_OK       = 1
    2.10 +STATE_DOM_SHUTDOWN = 2
    2.11  
    2.12  """Flag for a block device backend domain."""
    2.13  SIF_BLK_BE_DOMAIN = (1<<4)
    2.14 @@ -293,7 +293,7 @@ def parseConfig(config):
    2.15      restart = get_cfg('restart')
    2.16      if restart:
    2.17          def handle_restart(event, val):
    2.18 -            if not event in result:
    2.19 +            if result[event] is None:
    2.20                  result[event] = val
    2.21  
    2.22          if restart == "onreboot":
    2.23 @@ -384,7 +384,7 @@ class XendDomainInfo:
    2.24          self.console_channel = None
    2.25          self.console_mfn = None
    2.26  
    2.27 -        self.state = STATE_VM_OK
    2.28 +        self.state = STATE_DOM_OK
    2.29          self.state_updated = threading.Condition()
    2.30          self.refresh_shutdown_lock = threading.Condition()
    2.31  
    2.32 @@ -708,7 +708,7 @@ class XendDomainInfo:
    2.33                      self.clearRestart()
    2.34  
    2.35                      if reason == 'suspend':
    2.36 -                        self.state_set(STATE_VM_TERMINATED)
    2.37 +                        self.state_set(STATE_DOM_SHUTDOWN)
    2.38                          # Don't destroy the domain.  XendCheckpoint will do
    2.39                          # this once it has finished.
    2.40                      elif reason in ['poweroff', 'reboot']:
    2.41 @@ -821,19 +821,31 @@ class XendDomainInfo:
    2.42  
    2.43      def state_set(self, state):
    2.44          self.state_updated.acquire()
    2.45 -        if self.state != state:
    2.46 -            self.state = state
    2.47 -            self.state_updated.notifyAll()
    2.48 -        self.state_updated.release()
    2.49 +        try:
    2.50 +            if self.state != state:
    2.51 +                self.state = state
    2.52 +                self.state_updated.notifyAll()
    2.53 +        finally:
    2.54 +            self.state_updated.release()
    2.55  
    2.56  
    2.57      ## public:
    2.58  
    2.59      def waitForShutdown(self):
    2.60          self.state_updated.acquire()
    2.61 -        while self.state == STATE_VM_OK:
    2.62 -            self.state_updated.wait()
    2.63 -        self.state_updated.release()
    2.64 +        try:
    2.65 +            while self.state == STATE_DOM_OK:
    2.66 +                self.state_updated.wait()
    2.67 +        finally:
    2.68 +            self.state_updated.release()
    2.69 +
    2.70 +
    2.71 +    def isShutdown(self):
    2.72 +        self.state_updated.acquire()
    2.73 +        try:
    2.74 +            return self.state == STATE_DOM_SHUTDOWN
    2.75 +        finally:
    2.76 +            self.state_updated.release()
    2.77  
    2.78  
    2.79      def __str__(self):
    2.80 @@ -1065,11 +1077,11 @@ class XendDomainInfo:
    2.81  
    2.82          try:
    2.83              if not self.info['name'].startswith(ZOMBIE_PREFIX):
    2.84 -                self.info['name'] = self.generateZombieName()
    2.85 +                self.info['name'] = ZOMBIE_PREFIX + self.info['name']
    2.86          except:
    2.87              log.exception("Renaming Zombie failed.")
    2.88  
    2.89 -        self.state_set(STATE_VM_TERMINATED)
    2.90 +        self.state_set(STATE_DOM_SHUTDOWN)
    2.91  
    2.92  
    2.93      def cleanupVm(self):
    2.94 @@ -1274,7 +1286,7 @@ class XendDomainInfo:
    2.95          log.info("Preserving dead domain %s (%d).", self.info['name'],
    2.96                   self.domid)
    2.97          self.storeDom('xend/shutdown_completed', 'True')
    2.98 -        self.state_set(STATE_VM_TERMINATED)
    2.99 +        self.state_set(STATE_DOM_SHUTDOWN)
   2.100  
   2.101  
   2.102      ## public:
   2.103 @@ -1304,18 +1316,6 @@ class XendDomainInfo:
   2.104                  n += 1
   2.105  
   2.106  
   2.107 -    def generateZombieName(self):
   2.108 -        n = 0
   2.109 -        name = ZOMBIE_PREFIX + self.info['name']
   2.110 -        while True:
   2.111 -            try:
   2.112 -                self.check_name(name)
   2.113 -                return name
   2.114 -            except VmError:
   2.115 -                n += 1
   2.116 -                name = "%s%d-%s" % (ZOMBIE_PREFIX, n, self.info['name'])
   2.117 -
   2.118 -
   2.119      def configure_bootloader(self):
   2.120          if not self.info['bootloader']:
   2.121              return