ia64/xen-unstable

changeset 18576:591734b38585

merge with xen-unstable.hg
author Isaku Yamahata <yamahata@valinux.co.jp>
date Fri Oct 03 11:49:07 2008 +0900 (2008-10-03)
parents c8511a5e9a57 80365bc6df42
children 788ed94f8fe4
files
line diff
     1.1 --- a/tools/blktap/lib/xs_api.c	Thu Oct 02 17:27:57 2008 +0900
     1.2 +++ b/tools/blktap/lib/xs_api.c	Fri Oct 03 11:49:07 2008 +0900
     1.3 @@ -132,7 +132,7 @@ int xs_printf(struct xs_handle *h, const
     1.4  		return ENOMEM;
     1.5  	}
     1.6  
     1.7 -	ret = xs_write(h, XBT_NULL, path, buf, strlen(buf)+1);
     1.8 +	ret = xs_write(h, XBT_NULL, path, buf, strlen(buf));
     1.9  	
    1.10  	free(buf);
    1.11  	free(path);
     2.1 --- a/tools/libxc/xc_ptrace.c	Thu Oct 02 17:27:57 2008 +0900
     2.2 +++ b/tools/libxc/xc_ptrace.c	Fri Oct 03 11:49:07 2008 +0900
     2.3 @@ -112,17 +112,16 @@ static int
     2.4  get_online_cpumap(int xc_handle, struct xen_domctl_getdomaininfo *d,
     2.5                    uint64_t *cpumap)
     2.6  {
     2.7 -    int i, online, retval;
     2.8 +    int i, online;
     2.9  
    2.10      *cpumap = 0;
    2.11      for (i = 0; i <= d->max_vcpu_id; i++) {
    2.12 -        if ((retval = fetch_regs(xc_handle, i, &online)))
    2.13 -            return retval;
    2.14 +        fetch_regs(xc_handle, i, &online);
    2.15          if (online)
    2.16              *cpumap |= (1 << i);
    2.17      }
    2.18 -
    2.19 -    return 0;
    2.20 +    
    2.21 +    return (*cpumap == 0) ? -1 : 0;
    2.22  }
    2.23  
    2.24  /*
     3.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Oct 02 17:27:57 2008 +0900
     3.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Oct 03 11:49:07 2008 +0900
     3.3 @@ -142,7 +142,9 @@ def recreate(info, priv):
     3.4      xeninfo['is_control_domain'] = priv
     3.5      xeninfo['is_a_template'] = False
     3.6      domid = xeninfo['domid']
     3.7 -
     3.8 +    uuid1 = uuid.fromString(xeninfo['uuid'])
     3.9 +    needs_reinitialising = False
    3.10 +    
    3.11      dompath = GetDomainPath(domid)
    3.12      if not dompath:
    3.13          raise XendError('No domain path in store for existing '
    3.14 @@ -151,12 +153,42 @@ def recreate(info, priv):
    3.15      log.info("Recreating domain %d, UUID %s. at %s" %
    3.16               (domid, xeninfo['uuid'], dompath))
    3.17  
    3.18 -    vmpath = xstransact.Read("/vm_path", str(domid))
    3.19 +    # need to verify the path and uuid if not Domain-0
    3.20 +    # if the required uuid and vm aren't set, then that means
    3.21 +    # we need to recreate the dom with our own values
    3.22 +    #
    3.23 +    # NOTE: this is probably not desirable, really we should just
    3.24 +    #       abort or ignore, but there may be cases where xenstore's
    3.25 +    #       entry disappears (eg. xenstore-rm /)
    3.26 +    #
    3.27 +    try:
    3.28 +        vmpath = xstransact.Read(dompath, "vm")
    3.29 +        if not vmpath:
    3.30 +            if not priv:
    3.31 +                log.warn('/local/domain/%d/vm is missing. recreate is '
    3.32 +                         'confused, trying our best to recover' % domid)
    3.33 +            needs_reinitialising = True
    3.34 +            raise XendError('reinit')
    3.35 +        
    3.36 +        uuid2_str = xstransact.Read(vmpath, "uuid")
    3.37 +        if not uuid2_str:
    3.38 +            log.warn('%s/uuid/ is missing. recreate is confused, '
    3.39 +                     'trying our best to recover' % vmpath)
    3.40 +            needs_reinitialising = True
    3.41 +            raise XendError('reinit')
    3.42 +        
    3.43 +        uuid2 = uuid.fromString(uuid2_str)
    3.44 +        if uuid1 != uuid2:
    3.45 +            log.warn('UUID in /vm does not match the UUID in /dom/%d.'
    3.46 +                     'Trying out best to recover' % domid)
    3.47 +            needs_reinitialising = True
    3.48 +    except XendError:
    3.49 +        pass # our best shot at 'goto' in python :)
    3.50  
    3.51      vm = XendDomainInfo(xeninfo, domid, dompath, augment = True, priv = priv,
    3.52                          vmpath = vmpath)
    3.53 -
    3.54 -    if not vmpath:
    3.55 +    
    3.56 +    if needs_reinitialising:
    3.57          vm._recreateDom()
    3.58          vm._removeVm()
    3.59          vm._storeVmDetails()
    3.60 @@ -1269,8 +1301,11 @@ class XendDomainInfo:
    3.61      def _recreateDomFunc(self, t):
    3.62          t.remove()
    3.63          t.mkdir()
    3.64 -        t.set_permissions({'dom' : self.domid})
    3.65 +        t.set_permissions({'dom' : self.domid, 'read' : True})
    3.66          t.write('vm', self.vmpath)
    3.67 +        for i in [ 'device', 'control', 'error' ]:
    3.68 +            t.mkdir(i)
    3.69 +            t.set_permissions(i, {'dom' : self.domid})
    3.70  
    3.71      def _storeDomDetails(self):
    3.72          to_store = {
    3.73 @@ -1776,7 +1811,6 @@ class XendDomainInfo:
    3.74          self._releaseDevices()
    3.75          # Remove existing vm node in xenstore
    3.76          self._removeVm()
    3.77 -        self._removeVmPath()
    3.78          new_dom_info = self.info.copy()
    3.79          new_dom_info['name_label'] = self.info['name_label']
    3.80          new_dom_info['uuid'] = self.info['uuid']
    3.81 @@ -2357,7 +2391,6 @@ class XendDomainInfo:
    3.82  
    3.83          paths = self._prepare_phantom_paths()
    3.84  
    3.85 -        self._removeVmPath()
    3.86          if self.dompath is not None:
    3.87              try:
    3.88                  xc.domain_destroy_hook(self.domid)
    3.89 @@ -2660,15 +2693,6 @@ class XendDomainInfo:
    3.90                  log.info("Dev still active but hit max loop timeout")
    3.91                  break
    3.92  
    3.93 -    def _storeVmPath(self):
    3.94 -        log.info("storeVmPath(%s) => %s", self.domid, self.vmpath)
    3.95 -        if self.domid is not None:
    3.96 -            xstransact.Write('/vm_path', str(self.domid), self.vmpath)
    3.97 -
    3.98 -    def _removeVmPath(self):
    3.99 -        if self.domid is not None:
   3.100 -            xstransact.Remove('/vm_path/%s' % str(self.domid))
   3.101 -
   3.102      def _storeVmDetails(self):
   3.103          to_store = {}
   3.104  
   3.105 @@ -2693,7 +2717,6 @@ class XendDomainInfo:
   3.106  
   3.107          self._writeVm(to_store)
   3.108          self._setVmPermissions()
   3.109 -        self._storeVmPath()
   3.110  
   3.111      def _setVmPermissions(self):
   3.112          """Allow the guest domain to read its UUID.  We don't allow it to
     4.1 --- a/tools/python/xen/xend/image.py	Thu Oct 02 17:27:57 2008 +0900
     4.2 +++ b/tools/python/xen/xend/image.py	Fri Oct 03 11:49:07 2008 +0900
     4.3 @@ -418,7 +418,7 @@ class ImageHandler:
     4.4              os.close(null)
     4.5              os.close(logfd)
     4.6          sentinel_write.close()
     4.7 -        self.vm.storeVm("image/device-model-pid", self.pid)
     4.8 +        self.vm.storeDom("image/device-model-pid", self.pid)
     4.9          log.info("device model pid: %d", self.pid)
    4.10          # we would very much prefer not to have a thread here and instead
    4.11          #  have a callback but sadly we don't have Twisted in xend
    4.12 @@ -502,7 +502,7 @@ class ImageHandler:
    4.13          if fifo_fd >= 0:
    4.14              self._openSentinel(sentinel_path_fifo)
    4.15              os.close(fifo_fd)
    4.16 -            self.pid = self.vm._gatherVm(('image/device-model-pid', int))
    4.17 +            self.pid = self.vm._gatherDom(('image/device-model-pid', int))
    4.18              log.debug("%s device model rediscovered, pid %s sentinel fifo %s",
    4.19                      name, self.pid, sentinel_path_fifo)
    4.20              self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,())
     5.1 --- a/xen/arch/x86/hvm/hvm.c	Thu Oct 02 17:27:57 2008 +0900
     5.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Oct 03 11:49:07 2008 +0900
     5.3 @@ -2339,21 +2339,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
     5.4          if ( a.index >= HVM_NR_PARAMS )
     5.5              return -EINVAL;
     5.6  
     5.7 -        if ( a.domid == DOMID_SELF )
     5.8 -        {
     5.9 -            d = rcu_lock_current_domain();
    5.10 -        }
    5.11 -        else
    5.12 -        {
    5.13 -            if ( (d = rcu_lock_domain_by_id(a.domid)) == NULL )
    5.14 -                return -ESRCH;
    5.15 -            if ( !IS_PRIV_FOR(current->domain, d) )
    5.16 -            {
    5.17 -                rc = -EPERM;
    5.18 -                goto param_fail;
    5.19 -            }
    5.20 -        }
    5.21 -
    5.22 +        rc = rcu_lock_target_domain_by_id(a.domid, &d);
    5.23 +        if ( rc != 0 )
    5.24 +            return rc;
    5.25  
    5.26          rc = -EINVAL;
    5.27          if ( !is_hvm_domain(d) )
    5.28 @@ -2521,20 +2509,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
    5.29          if ( copy_from_guest(&a, arg, 1) )
    5.30              return -EFAULT;
    5.31  
    5.32 -        if ( a.domid == DOMID_SELF )
    5.33 -        {
    5.34 -            d = rcu_lock_current_domain();
    5.35 -        }
    5.36 -        else
    5.37 -        {
    5.38 -            if ( (d = rcu_lock_domain_by_id(a.domid)) == NULL )
    5.39 -                return -ESRCH;
    5.40 -            if ( !IS_PRIV_FOR(current->domain, d) )
    5.41 -            {
    5.42 -                rc = -EPERM;
    5.43 -                goto param_fail2;
    5.44 -            }
    5.45 -        }
    5.46 +        rc = rcu_lock_target_domain_by_id(a.domid, &d);
    5.47 +        if ( rc != 0 )
    5.48 +            return rc;
    5.49  
    5.50          rc = -EINVAL;
    5.51          if ( !is_hvm_domain(d) )
    5.52 @@ -2570,20 +2547,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
    5.53          if ( copy_from_guest(&a, arg, 1) )
    5.54              return -EFAULT;
    5.55  
    5.56 -        if ( a.domid == DOMID_SELF )
    5.57 -        {
    5.58 -            d = rcu_lock_current_domain();
    5.59 -        }
    5.60 -        else
    5.61 -        {
    5.62 -            if ( (d = rcu_lock_domain_by_id(a.domid)) == NULL )
    5.63 -                return -ESRCH;
    5.64 -            if ( !IS_PRIV_FOR(current->domain, d) )
    5.65 -            {
    5.66 -                rc = -EPERM;
    5.67 -                goto param_fail3;
    5.68 -            }
    5.69 -        }
    5.70 +        rc = rcu_lock_target_domain_by_id(a.domid, &d);
    5.71 +        if ( rc != 0 )
    5.72 +            return rc;
    5.73  
    5.74          rc = -EINVAL;
    5.75          if ( !is_hvm_domain(d) )
    5.76 @@ -2637,20 +2603,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
    5.77          if ( copy_from_guest(&a, arg, 1) )
    5.78              return -EFAULT;
    5.79  
    5.80 -        if ( a.domid == DOMID_SELF )
    5.81 -        {
    5.82 -            d = rcu_lock_current_domain();
    5.83 -        }
    5.84 -        else
    5.85 -        {
    5.86 -            if ( (d = rcu_lock_domain_by_id(a.domid)) == NULL )
    5.87 -                return -ESRCH;
    5.88 -            if ( !IS_PRIV_FOR(current->domain, d) )
    5.89 -            {
    5.90 -                rc = -EPERM;
    5.91 -                goto param_fail4;
    5.92 -            }
    5.93 -        }
    5.94 +        rc = rcu_lock_target_domain_by_id(a.domid, &d);
    5.95 +        if ( rc != 0 )
    5.96 +            return rc;
    5.97  
    5.98          rc = -EINVAL;
    5.99          if ( !is_hvm_domain(d) )
     6.1 --- a/xen/arch/x86/mm.c	Thu Oct 02 17:27:57 2008 +0900
     6.2 +++ b/xen/arch/x86/mm.c	Fri Oct 03 11:49:07 2008 +0900
     6.3 @@ -3550,6 +3550,8 @@ DEFINE_XEN_GUEST_HANDLE(e820entry_t);
     6.4  long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
     6.5  {
     6.6      struct page_info *page = NULL;
     6.7 +    int rc;
     6.8 +
     6.9      switch ( op )
    6.10      {
    6.11      case XENMEM_add_to_physmap:
    6.12 @@ -3561,20 +3563,9 @@ long arch_memory_op(int op, XEN_GUEST_HA
    6.13          if ( copy_from_guest(&xatp, arg, 1) )
    6.14              return -EFAULT;
    6.15  
    6.16 -        if ( xatp.domid == DOMID_SELF )
    6.17 -        {
    6.18 -            d = rcu_lock_current_domain();
    6.19 -        }
    6.20 -        else
    6.21 -        {
    6.22 -            if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL )
    6.23 -                return -ESRCH;
    6.24 -            if ( !IS_PRIV_FOR(current->domain, d) )
    6.25 -            {
    6.26 -                rcu_unlock_domain(d);
    6.27 -                return -EPERM;
    6.28 -            }
    6.29 -        }
    6.30 +        rc = rcu_lock_target_domain_by_id(xatp.domid, &d);
    6.31 +        if ( rc != 0 )
    6.32 +            return rc;
    6.33  
    6.34          if ( xsm_add_to_physmap(current->domain, d) )
    6.35          {
    6.36 @@ -3661,20 +3652,9 @@ long arch_memory_op(int op, XEN_GUEST_HA
    6.37          if ( copy_from_guest(&xrfp, arg, 1) )
    6.38              return -EFAULT;
    6.39  
    6.40 -        if ( xrfp.domid == DOMID_SELF )
    6.41 -        {
    6.42 -            d = rcu_lock_current_domain();
    6.43 -        }
    6.44 -        else
    6.45 -        {
    6.46 -            if ( (d = rcu_lock_domain_by_id(xrfp.domid)) == NULL )
    6.47 -                return -ESRCH;
    6.48 -            if ( !IS_PRIV_FOR(current->domain, d) )
    6.49 -            {
    6.50 -                rcu_unlock_domain(d);
    6.51 -                return -EPERM;
    6.52 -            }
    6.53 -        }
    6.54 +        rc = rcu_lock_target_domain_by_id(xrfp.domid, &d);
    6.55 +        if ( rc != 0 )
    6.56 +            return rc;
    6.57  
    6.58          if ( xsm_remove_from_physmap(current->domain, d) )
    6.59          {
    6.60 @@ -3708,20 +3688,9 @@ long arch_memory_op(int op, XEN_GUEST_HA
    6.61          if ( fmap.map.nr_entries > ARRAY_SIZE(d->arch.e820) )
    6.62              return -EINVAL;
    6.63  
    6.64 -        if ( fmap.domid == DOMID_SELF )
    6.65 -        {
    6.66 -            d = rcu_lock_current_domain();
    6.67 -        }
    6.68 -        else
    6.69 -        {
    6.70 -            if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL )
    6.71 -                return -ESRCH;
    6.72 -            if ( !IS_PRIV_FOR(current->domain, d) )
    6.73 -            {
    6.74 -                rcu_unlock_domain(d);
    6.75 -                return -EPERM;
    6.76 -            }
    6.77 -        }
    6.78 +        rc = rcu_lock_target_domain_by_id(fmap.domid, &d);
    6.79 +        if ( rc != 0 )
    6.80 +            return rc;
    6.81  
    6.82          rc = xsm_domain_memory_map(d);
    6.83          if ( rc )
     7.1 --- a/xen/common/domain.c	Thu Oct 02 17:27:57 2008 +0900
     7.2 +++ b/xen/common/domain.c	Fri Oct 03 11:49:07 2008 +0900
     7.3 @@ -332,6 +332,25 @@ struct domain *rcu_lock_domain_by_id(dom
     7.4      return NULL;
     7.5  }
     7.6  
     7.7 +int rcu_lock_target_domain_by_id(domid_t dom, struct domain **d)
     7.8 +{
     7.9 +    if ( dom == DOMID_SELF )
    7.10 +    {
    7.11 +        *d = rcu_lock_current_domain();
    7.12 +        return 0;
    7.13 +    }
    7.14 +
    7.15 +    if ( (*d = rcu_lock_domain_by_id(dom)) == NULL )
    7.16 +        return -ESRCH;
    7.17 +
    7.18 +    if ( !IS_PRIV_FOR(current->domain, *d) )
    7.19 +    {
    7.20 +        rcu_unlock_domain(*d);
    7.21 +        return -EPERM;
    7.22 +    }
    7.23 +
    7.24 +    return 0;
    7.25 +}
    7.26  
    7.27  int domain_kill(struct domain *d)
    7.28  {
     8.1 --- a/xen/common/event_channel.c	Thu Oct 02 17:27:57 2008 +0900
     8.2 +++ b/xen/common/event_channel.c	Fri Oct 03 11:49:07 2008 +0900
     8.3 @@ -129,20 +129,9 @@ static long evtchn_alloc_unbound(evtchn_
     8.4      domid_t        dom = alloc->dom;
     8.5      long           rc;
     8.6  
     8.7 -    if ( dom == DOMID_SELF )
     8.8 -    {
     8.9 -        d = rcu_lock_current_domain();
    8.10 -    }
    8.11 -    else
    8.12 -    {
    8.13 -        if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
    8.14 -            return -ESRCH;
    8.15 -        if ( !IS_PRIV_FOR(current->domain, d) )
    8.16 -        {
    8.17 -            rcu_unlock_domain(d);
    8.18 -            return -EPERM;
    8.19 -        }
    8.20 -    }
    8.21 +    rc = rcu_lock_target_domain_by_id(dom, &d);
    8.22 +    if ( rc )
    8.23 +        return rc;
    8.24  
    8.25      spin_lock(&d->evtchn_lock);
    8.26  
    8.27 @@ -663,20 +652,9 @@ static long evtchn_status(evtchn_status_
    8.28      struct evtchn   *chn;
    8.29      long             rc = 0;
    8.30  
    8.31 -    if ( dom == DOMID_SELF )
    8.32 -    {
    8.33 -        d = rcu_lock_current_domain();
    8.34 -    }
    8.35 -    else
    8.36 -    {
    8.37 -        if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
    8.38 -            return -ESRCH;
    8.39 -        if ( !IS_PRIV_FOR(current->domain, d) )
    8.40 -        {
    8.41 -            rcu_unlock_domain(d);
    8.42 -            return -EPERM;
    8.43 -        }
    8.44 -    }
    8.45 +    rc = rcu_lock_target_domain_by_id(dom, &d);
    8.46 +    if ( rc )
    8.47 +        return rc;
    8.48  
    8.49      spin_lock(&d->evtchn_lock);
    8.50  
    8.51 @@ -824,20 +802,9 @@ static long evtchn_reset(evtchn_reset_t 
    8.52      struct domain *d;
    8.53      int i, rc;
    8.54  
    8.55 -    if ( dom == DOMID_SELF )
    8.56 -    {
    8.57 -        d = rcu_lock_current_domain();
    8.58 -    }
    8.59 -    else
    8.60 -    {
    8.61 -        if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
    8.62 -            return -ESRCH;
    8.63 -        if ( !IS_PRIV_FOR(current->domain, d) )
    8.64 -        {
    8.65 -            rc = -EPERM;
    8.66 -            goto out;
    8.67 -        }
    8.68 -    }
    8.69 +    rc = rcu_lock_target_domain_by_id(dom, &d);
    8.70 +    if ( rc )
    8.71 +        return rc;
    8.72  
    8.73      rc = xsm_evtchn_reset(current->domain, d);
    8.74      if ( rc )
     9.1 --- a/xen/common/memory.c	Thu Oct 02 17:27:57 2008 +0900
     9.2 +++ b/xen/common/memory.c	Fri Oct 03 11:49:07 2008 +0900
     9.3 @@ -222,21 +222,9 @@ static long translate_gpfn_list(
     9.4           !guest_handle_subrange_okay(op.mfn_list, *progress, op.nr_gpfns-1) )
     9.5          return -EFAULT;
     9.6  
     9.7 -    if ( op.domid == DOMID_SELF )
     9.8 -    {
     9.9 -        d = rcu_lock_current_domain();
    9.10 -    }
    9.11 -    else
    9.12 -    {
    9.13 -        if ( (d = rcu_lock_domain_by_id(op.domid)) == NULL )
    9.14 -            return -ESRCH;
    9.15 -        if ( !IS_PRIV_FOR(current->domain, d) )
    9.16 -        {
    9.17 -            rcu_unlock_domain(d);
    9.18 -            return -EPERM;
    9.19 -        }
    9.20 -    }
    9.21 -
    9.22 +    rc = rcu_lock_target_domain_by_id(op.domid, &d);
    9.23 +    if ( rc )
    9.24 +        return rc;
    9.25  
    9.26      if ( !paging_mode_translate(d) )
    9.27      {
    9.28 @@ -595,20 +583,9 @@ long do_memory_op(unsigned long cmd, XEN
    9.29          if ( copy_from_guest(&domid, arg, 1) )
    9.30              return -EFAULT;
    9.31  
    9.32 -        if ( likely(domid == DOMID_SELF) )
    9.33 -        {
    9.34 -            d = rcu_lock_current_domain();
    9.35 -        }
    9.36 -        else
    9.37 -        {
    9.38 -            if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
    9.39 -                return -ESRCH;
    9.40 -            if ( !IS_PRIV_FOR(current->domain, d) )
    9.41 -            {
    9.42 -                rcu_unlock_domain(d);
    9.43 -                return -EPERM;
    9.44 -            }
    9.45 -        }
    9.46 +        rc = rcu_lock_target_domain_by_id(domid, &d);
    9.47 +        if ( rc )
    9.48 +            return rc;
    9.49  
    9.50          rc = xsm_memory_stat_reservation(current->domain, d);
    9.51          if ( rc )
    10.1 --- a/xen/include/xen/sched.h	Thu Oct 02 17:27:57 2008 +0900
    10.2 +++ b/xen/include/xen/sched.h	Fri Oct 03 11:49:07 2008 +0900
    10.3 @@ -364,6 +364,13 @@ int construct_dom0(
    10.4   */
    10.5  struct domain *rcu_lock_domain_by_id(domid_t dom);
    10.6  
    10.7 +/*
    10.8 + * As above function, but accounts for current domain context:
    10.9 + *  - Translates target DOMID_SELF into caller's domain id; and
   10.10 + *  - Checks that caller has permission to act on the target domain.
   10.11 + */
   10.12 +int rcu_lock_target_domain_by_id(domid_t dom, struct domain **d);
   10.13 +
   10.14  /* Finish a RCU critical region started by rcu_lock_domain_by_id(). */
   10.15  static inline void rcu_unlock_domain(struct domain *d)
   10.16  {