direct-io.hg

changeset 13085:6e68e8a8cc99

merge with xen-unstable.hg
author awilliam@xenbuild2.aw
date Mon Dec 18 10:56:34 2006 -0700 (2006-12-18)
parents ea2dc4a3c8eb 469478194aef
children b3cd9c4ac056 105ac9be9b3d
files
line diff
     1.1 --- a/.hgignore	Mon Dec 18 10:20:34 2006 -0700
     1.2 +++ b/.hgignore	Mon Dec 18 10:56:34 2006 -0700
     1.3 @@ -229,3 +229,4 @@
     1.4  ^unmodified_drivers/linux-2.6/.*\.cmd$
     1.5  ^unmodified_drivers/linux-2.6/.*\.ko$
     1.6  ^unmodified_drivers/linux-2.6/.*\.mod\.c$
     1.7 +^LibVNCServer.*
     2.1 --- a/config/x86_32.mk	Mon Dec 18 10:20:34 2006 -0700
     2.2 +++ b/config/x86_32.mk	Mon Dec 18 10:56:34 2006 -0700
     2.3 @@ -1,4 +1,5 @@
     2.4  CONFIG_X86 := y
     2.5 +CONFIG_X86_32 := y
     2.6  CONFIG_X86_$(XEN_OS) := y
     2.7  
     2.8  CONFIG_HVM := y
     3.1 --- a/config/x86_64.mk	Mon Dec 18 10:20:34 2006 -0700
     3.2 +++ b/config/x86_64.mk	Mon Dec 18 10:56:34 2006 -0700
     3.3 @@ -1,4 +1,5 @@
     3.4  CONFIG_X86 := y
     3.5 +CONFIG_X86_64 := y
     3.6  CONFIG_X86_$(XEN_OS) := y
     3.7  
     3.8  CONFIG_HVM := y
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c	Mon Dec 18 10:20:34 2006 -0700
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c	Mon Dec 18 10:56:34 2006 -0700
     4.3 @@ -49,8 +49,9 @@ struct xenfb_info
     4.4  	struct timer_list	refresh;
     4.5  	int			dirty;
     4.6  	int			x1, y1, x2, y2;	/* dirty rectangle,
     4.7 -						   protected by mm_lock */
     4.8 -	spinlock_t		mm_lock;
     4.9 +						   protected by dirty_lock */
    4.10 +	spinlock_t		dirty_lock;
    4.11 +	struct mutex		mm_lock;
    4.12  	int			nr_pages;
    4.13  	struct page		**pages;
    4.14  	struct list_head	mappings; /* protected by mm_lock */
    4.15 @@ -64,6 +65,70 @@ struct xenfb_info
    4.16  	struct xenbus_device	*xbdev;
    4.17  };
    4.18  
    4.19 +/*
    4.20 + * How the locks work together
    4.21 + *
    4.22 + * There are two locks: spinlock dirty_lock protecting the dirty
    4.23 + * rectangle, and mutex mm_lock protecting mappings.
    4.24 + *
    4.25 + * The problem is that dirty rectangle and mappings aren't
    4.26 + * independent: the dirty rectangle must cover all faulted pages in
    4.27 + * mappings.  We need to prove that our locking maintains this
    4.28 + * invariant.
    4.29 + *
    4.30 + * There are several kinds of critical regions:
    4.31 + *
    4.32 + * 1. Holding only dirty_lock: xenfb_refresh().  May run in
    4.33 + *    interrupts.  Extends the dirty rectangle.  Trivially preserves
    4.34 + *    invariant.
    4.35 + *
    4.36 + * 2. Holding only mm_lock: xenfb_mmap() and xenfb_vm_close().  Touch
    4.37 + *    only mappings.  The former creates unfaulted pages.  Preserves
    4.38 + *    invariant.  The latter removes pages.  Preserves invariant.
    4.39 + *
    4.40 + * 3. Holding both locks: xenfb_vm_nopage().  Extends the dirty
    4.41 + *    rectangle and updates mappings consistently.  Preserves
    4.42 + *    invariant.
    4.43 + *
    4.44 + * 4. The ugliest one: xenfb_update_screen().  Clear the dirty
    4.45 + *    rectangle and update mappings consistently.
    4.46 + *
    4.47 + *    We can't simply hold both locks, because zap_page_range() cannot
    4.48 + *    be called with a spinlock held.
    4.49 + *
    4.50 + *    Therefore, we first clear the dirty rectangle with both locks
    4.51 + *    held.  Then we unlock dirty_lock and update the mappings.
    4.52 + *    Critical regions that hold only dirty_lock may interfere with
    4.53 + *    that.  This can only be region 1: xenfb_refresh().  But that
    4.54 + *    just extends the dirty rectangle, which can't harm the
    4.55 + *    invariant.
    4.56 + *
    4.57 + * But FIXME: the invariant is too weak.  It misses that the fault
    4.58 + * record in mappings must be consistent with the mapping of pages in
    4.59 + * the associated address space!  do_no_page() updates the PTE after
    4.60 + * xenfb_vm_nopage() returns, i.e. outside the critical region.  This
    4.61 + * allows the following race:
    4.62 + *
    4.63 + * X writes to some address in the Xen frame buffer
    4.64 + * Fault - call do_no_page()
    4.65 + *     call xenfb_vm_nopage()
    4.66 + *         grab mm_lock
    4.67 + *         map->faults++;
    4.68 + *         release mm_lock
    4.69 + *     return back to do_no_page()
    4.70 + * (preempted, or SMP)
    4.71 + * Xen worker thread runs.
    4.72 + *      grab mm_lock
    4.73 + *      look at mappings
    4.74 + *          find this mapping, zaps its pages (but page not in pte yet)
    4.75 + *          clear map->faults
    4.76 + *      releases mm_lock
    4.77 + * (back to X process)
    4.78 + *     put page in X's pte
    4.79 + *
    4.80 + * Oh well, we wont be updating the writes to this page anytime soon.
    4.81 + */
    4.82 +
    4.83  static int xenfb_fps = 20;
    4.84  static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
    4.85  
    4.86 @@ -105,6 +170,7 @@ static int xenfb_queue_full(struct xenfb
    4.87  
    4.88  static void xenfb_update_screen(struct xenfb_info *info)
    4.89  {
    4.90 +	unsigned long flags;
    4.91  	int y1, y2, x1, x2;
    4.92  	struct xenfb_mapping *map;
    4.93  
    4.94 @@ -113,14 +179,16 @@ static void xenfb_update_screen(struct x
    4.95  	if (xenfb_queue_full(info))
    4.96  		return;
    4.97  
    4.98 -	spin_lock(&info->mm_lock);
    4.99 +	mutex_lock(&info->mm_lock);
   4.100  
   4.101 +	spin_lock_irqsave(&info->dirty_lock, flags);
   4.102  	y1 = info->y1;
   4.103  	y2 = info->y2;
   4.104  	x1 = info->x1;
   4.105  	x2 = info->x2;
   4.106  	info->x1 = info->y1 = INT_MAX;
   4.107  	info->x2 = info->y2 = 0;
   4.108 +	spin_unlock_irqrestore(&info->dirty_lock, flags);
   4.109  
   4.110  	list_for_each_entry(map, &info->mappings, link) {
   4.111  		if (!map->faults)
   4.112 @@ -130,7 +198,7 @@ static void xenfb_update_screen(struct x
   4.113  		map->faults = 0;
   4.114  	}
   4.115  
   4.116 -	spin_unlock(&info->mm_lock);
   4.117 +	mutex_unlock(&info->mm_lock);
   4.118  
   4.119  	xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
   4.120  }
   4.121 @@ -213,9 +281,11 @@ static void __xenfb_refresh(struct xenfb
   4.122  static void xenfb_refresh(struct xenfb_info *info,
   4.123  			  int x1, int y1, int w, int h)
   4.124  {
   4.125 -	spin_lock(&info->mm_lock);
   4.126 +	unsigned long flags;
   4.127 +
   4.128 +	spin_lock_irqsave(&info->dirty_lock, flags);
   4.129  	__xenfb_refresh(info, x1, y1, w, h);
   4.130 -	spin_unlock(&info->mm_lock);
   4.131 +	spin_unlock_irqrestore(&info->dirty_lock, flags);
   4.132  }
   4.133  
   4.134  static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
   4.135 @@ -253,12 +323,12 @@ static void xenfb_vm_close(struct vm_are
   4.136  	struct xenfb_mapping *map = vma->vm_private_data;
   4.137  	struct xenfb_info *info = map->info;
   4.138  
   4.139 -	spin_lock(&info->mm_lock);
   4.140 +	mutex_lock(&info->mm_lock);
   4.141  	if (atomic_dec_and_test(&map->map_refs)) {
   4.142  		list_del(&map->link);
   4.143  		kfree(map);
   4.144  	}
   4.145 -	spin_unlock(&info->mm_lock);
   4.146 +	mutex_unlock(&info->mm_lock);
   4.147  }
   4.148  
   4.149  static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
   4.150 @@ -267,13 +337,15 @@ static struct page *xenfb_vm_nopage(stru
   4.151  	struct xenfb_mapping *map = vma->vm_private_data;
   4.152  	struct xenfb_info *info = map->info;
   4.153  	int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
   4.154 +	unsigned long flags;
   4.155  	struct page *page;
   4.156  	int y1, y2;
   4.157  
   4.158  	if (pgnr >= info->nr_pages)
   4.159  		return NOPAGE_SIGBUS;
   4.160  
   4.161 -	spin_lock(&info->mm_lock);
   4.162 +	mutex_lock(&info->mm_lock);
   4.163 +	spin_lock_irqsave(&info->dirty_lock, flags);
   4.164  	page = info->pages[pgnr];
   4.165  	get_page(page);
   4.166  	map->faults++;
   4.167 @@ -283,7 +355,8 @@ static struct page *xenfb_vm_nopage(stru
   4.168  	if (y2 > info->fb_info->var.yres)
   4.169  		y2 = info->fb_info->var.yres;
   4.170  	__xenfb_refresh(info, 0, y1, info->fb_info->var.xres, y2 - y1);
   4.171 -	spin_unlock(&info->mm_lock);
   4.172 +	spin_unlock_irqrestore(&info->dirty_lock, flags);
   4.173 +	mutex_unlock(&info->mm_lock);
   4.174  
   4.175  	if (type)
   4.176  		*type = VM_FAULT_MINOR;
   4.177 @@ -323,9 +396,9 @@ static int xenfb_mmap(struct fb_info *fb
   4.178  	map->info = info;
   4.179  	atomic_set(&map->map_refs, 1);
   4.180  
   4.181 -	spin_lock(&info->mm_lock);
   4.182 +	mutex_lock(&info->mm_lock);
   4.183  	list_add(&map->link, &info->mappings);
   4.184 -	spin_unlock(&info->mm_lock);
   4.185 +	mutex_unlock(&info->mm_lock);
   4.186  
   4.187  	vma->vm_ops = &xenfb_vm_ops;
   4.188  	vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED);
   4.189 @@ -382,7 +455,8 @@ static int __devinit xenfb_probe(struct 
   4.190  	info->xbdev = dev;
   4.191  	info->irq = -1;
   4.192  	info->x1 = info->y1 = INT_MAX;
   4.193 -	spin_lock_init(&info->mm_lock);
   4.194 +	spin_lock_init(&info->dirty_lock);
   4.195 +	mutex_init(&info->mm_lock);
   4.196  	init_waitqueue_head(&info->wq);
   4.197  	init_timer(&info->refresh);
   4.198  	info->refresh.function = xenfb_timer;
     5.1 --- a/tools/ioemu/target-i386-dm/exec-dm.c	Mon Dec 18 10:20:34 2006 -0700
     5.2 +++ b/tools/ioemu/target-i386-dm/exec-dm.c	Mon Dec 18 10:56:34 2006 -0700
     5.3 @@ -128,10 +128,28 @@ char *logfilename = "/tmp/qemu.log";
     5.4  FILE *logfile;
     5.5  int loglevel;
     5.6  
     5.7 +
     5.8 +#if defined(__i386__) || defined(__x86_64__)
     5.9 +#define MAPCACHE
    5.10 +#endif
    5.11 +
    5.12 +#ifdef MAPCACHE
    5.13 +static pthread_mutex_t mapcache_mutex;
    5.14 +#define mapcache_lock() pthread_mutex_lock(&mapcache_mutex)
    5.15 +#define mapcache_unlock() pthread_mutex_unlock(&mapcache_mutex)
    5.16 +#else 
    5.17 +#define mapcache_lock() ( (void)0 )
    5.18 +#define mapcache_unlock() ( (void)0 )
    5.19 +#endif
    5.20 +
    5.21 +
    5.22  void cpu_exec_init(CPUState *env)
    5.23  {
    5.24      CPUState **penv;
    5.25      int cpu_index;
    5.26 +#ifdef MAPCACHE
    5.27 +    pthread_mutexattr_t mxattr; 
    5.28 +#endif
    5.29  
    5.30      env->next_cpu = NULL;
    5.31      penv = &first_cpu;
    5.32 @@ -145,6 +163,14 @@ void cpu_exec_init(CPUState *env)
    5.33  
    5.34      /* alloc dirty bits array */
    5.35      phys_ram_dirty = qemu_malloc(phys_ram_size >> TARGET_PAGE_BITS);
    5.36 +
    5.37 +#ifdef MAPCACHE
    5.38 +    /* setup memory access mutex to protect mapcache */
    5.39 +    pthread_mutexattr_init(&mxattr); 
    5.40 +    pthread_mutexattr_settype(&mxattr, PTHREAD_MUTEX_RECURSIVE);
    5.41 +    pthread_mutex_init(&mapcache_mutex, &mxattr); 
    5.42 +    pthread_mutexattr_destroy(&mxattr); 
    5.43 +#endif
    5.44  }
    5.45  
    5.46  /* enable or disable low levels log */
    5.47 @@ -440,10 +466,7 @@ void cpu_physical_memory_rw(target_phys_
    5.48      uint8_t *ptr;
    5.49      uint32_t val;
    5.50  
    5.51 -#if defined(__i386__) || defined(__x86_64__)
    5.52 -    static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
    5.53 -    pthread_mutex_lock(&mutex);
    5.54 -#endif
    5.55 +    mapcache_lock();
    5.56  
    5.57      while (len > 0) {
    5.58          /* How much can we copy before the next page boundary? */
    5.59 @@ -510,9 +533,7 @@ void cpu_physical_memory_rw(target_phys_
    5.60          addr += l;
    5.61      }
    5.62  
    5.63 -#if defined(__i386__) || defined(__x86_64__)
    5.64 -    pthread_mutex_unlock(&mutex);
    5.65 -#endif
    5.66 +    mapcache_unlock();
    5.67  }
    5.68  #endif
    5.69  
     6.1 --- a/tools/python/xen/xend/XendAPI.py	Mon Dec 18 10:20:34 2006 -0700
     6.2 +++ b/tools/python/xen/xend/XendAPI.py	Mon Dec 18 10:56:34 2006 -0700
     6.3 @@ -663,7 +663,10 @@ class XendAPI:
     6.4              XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
     6.5  
     6.6      def VM_set(self, name, session, vm_ref, value):
     6.7 -        XendDomain.instance().get_vm_by_uuid(vm_ref).info[name] = value
     6.8 +        xd = XendDomain.instance()
     6.9 +        dominfo = xd.get_vm_by_uuid(vm_ref)
    6.10 +        dominfo.info[name] = value
    6.11 +        xd.managed_config_save(dominfo)
    6.12          return xen_api_success_void()
    6.13  
    6.14      # attributes (ro)
     7.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Mon Dec 18 10:20:34 2006 -0700
     7.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Mon Dec 18 10:56:34 2006 -0700
     7.3 @@ -218,18 +218,17 @@ def forkHelper(cmd, fd, inputHandler, cl
     7.4                      log.debug('%s', line)
     7.5                      inputHandler(line, child.tochild)
     7.6  
     7.7 -            thread.join()
     7.8 -
     7.9          except IOError, exn:
    7.10              raise XendError('Error reading from child process for %s: %s' %
    7.11                              (cmd, exn))
    7.12      finally:
    7.13          child.fromchild.close()
    7.14 -        child.childerr.close()
    7.15          if not closeToChild:
    7.16              child.tochild.close()
    7.17 +        thread.join()
    7.18 +        child.childerr.close()
    7.19 +        status = child.wait()
    7.20  
    7.21 -    status = child.wait()
    7.22      if status >> 8 == 127:
    7.23          raise XendError("%s failed: popen failed" % string.join(cmd))
    7.24      elif status != 0:
     8.1 --- a/tools/python/xen/xend/XendConfig.py	Mon Dec 18 10:20:34 2006 -0700
     8.2 +++ b/tools/python/xen/xend/XendConfig.py	Mon Dec 18 10:56:34 2006 -0700
     8.3 @@ -15,6 +15,7 @@
     8.4  # Copyright (C) 2006 XenSource Ltd
     8.5  #============================================================================
     8.6  
     8.7 +import logging
     8.8  import re
     8.9  import time
    8.10  import types
    8.11 @@ -23,10 +24,13 @@ from xen.xend import sxp
    8.12  from xen.xend import uuid
    8.13  from xen.xend.XendError import VmError
    8.14  from xen.xend.XendDevices import XendDevices
    8.15 -from xen.xend.XendLogging import log
    8.16  from xen.xend.PrettyPrint import prettyprintstring
    8.17  from xen.xend.XendConstants import DOM_STATE_HALTED
    8.18  
    8.19 +log = logging.getLogger("xend.XendConfig")
    8.20 +log.setLevel(logging.WARN)
    8.21 +
    8.22 +
    8.23  """
    8.24  XendConfig API
    8.25  
    8.26 @@ -182,18 +186,18 @@ LEGACY_CFG_TYPES = {
    8.27      'shadow_memory': int,
    8.28      'maxmem':        int,
    8.29      'start_time':    float,
    8.30 -    'cpu_cap':         int,
    8.31 -    'cpu_weight':      int,
    8.32 +    'cpu_cap':       int,
    8.33 +    'cpu_weight':    int,
    8.34      'cpu_time':      float,
    8.35 -    'features':        str,
    8.36 -    'localtime':       int,
    8.37 -    'name':        str,
    8.38 -    'on_poweroff': str,
    8.39 -    'on_reboot':   str,
    8.40 -    'on_crash':    str,
    8.41 -    'on_xend_stop': str,
    8.42 +    'features':      str,
    8.43 +    'localtime':     int,
    8.44 +    'name':          str,
    8.45 +    'on_poweroff':   str,
    8.46 +    'on_reboot':     str,
    8.47 +    'on_crash':      str,
    8.48 +    'on_xend_stop':  str,
    8.49      'on_xend_start': str,
    8.50 -    'online_vcpus': int,
    8.51 +    'online_vcpus':  int,
    8.52  }
    8.53  
    8.54  # Values that should be stored in xenstore's /vm/<uuid> that is used
    8.55 @@ -430,8 +434,12 @@ class XendConfig(dict):
    8.56          """
    8.57          cfg = {}
    8.58  
    8.59 -        # First step is to convert deprecated options to
    8.60 -        # current equivalents.
    8.61 +        for key, typ in XENAPI_CFG_TYPES.items():
    8.62 +            val = sxp.child_value(sxp_cfg, key)
    8.63 +            if val is not None:
    8.64 +                cfg[key] = typ(val)
    8.65 +
    8.66 +        # Convert deprecated options to current equivalents.
    8.67          
    8.68          restart = sxp.child_value(sxp_cfg, 'restart')
    8.69          if restart:
    8.70 @@ -574,8 +582,15 @@ class XendConfig(dict):
    8.71          """Read in an SXP Configuration object and
    8.72          populate at much of the Xen API with valid values.
    8.73          """
    8.74 +        log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg))
    8.75 +
    8.76          cfg = self._parse_sxp(sxp_cfg)
    8.77  
    8.78 +        for key, typ in XENAPI_CFG_TYPES.items():
    8.79 +            val = cfg.get(key)
    8.80 +            if val is not None:
    8.81 +                self[key] = typ(val)
    8.82 +
    8.83          # Convert parameters that can be directly mapped from
    8.84          # the Legacy Config to Xen API Config
    8.85          
    8.86 @@ -590,9 +605,13 @@ class XendConfig(dict):
    8.87              except KeyError:
    8.88                  pass
    8.89  
    8.90 -        self['PV_bootloader']      = cfg.get('bootloader',      '')
    8.91 -        self['PV_bootloader_args'] = cfg.get('bootloader_args', '')
    8.92 -        
    8.93 +        def update_with(n, o):
    8.94 +            if not self.get(n):
    8.95 +                self[n] = cfg.get(o, '')
    8.96 +
    8.97 +        update_with('PV_bootloader',      'bootloader')
    8.98 +        update_with('PV_bootloader_args', 'bootloader_args')
    8.99 +
   8.100          image_sxp = sxp.child_value(sxp_cfg, 'image', [])
   8.101          if image_sxp:
   8.102              self.update_with_image_sxp(image_sxp)
   8.103 @@ -635,6 +654,8 @@ class XendConfig(dict):
   8.104          the Xen API.
   8.105          """
   8.106  
   8.107 +        log.debug('_sxp_to_xapi_unsupported(%s)' % scrub_password(sxp_cfg))
   8.108 +
   8.109          # Parse and convert parameters used to configure
   8.110          # the image (as well as HVM images)
   8.111          image_sxp = sxp.child_value(sxp_cfg, 'image', [])
   8.112 @@ -748,6 +769,9 @@ class XendConfig(dict):
   8.113          @param xapi: Xen API VM Struct
   8.114          @type xapi: dict
   8.115          """
   8.116 +
   8.117 +        log.debug('update_with_xenapi_config: %s' % scrub_password(xapi))
   8.118 +
   8.119          for key, val in xapi.items():
   8.120              type_conv = XENAPI_CFG_TYPES.get(key)
   8.121              if type_conv is None:
   8.122 @@ -760,11 +784,8 @@ class XendConfig(dict):
   8.123  
   8.124          self.validate()
   8.125  
   8.126 -    def to_xml(self):
   8.127 -        """Return an XML string representing the configuration."""
   8.128 -        pass
   8.129 -
   8.130 -    def to_sxp(self, domain = None, ignore_devices = False, ignore = []):
   8.131 +    def to_sxp(self, domain = None, ignore_devices = False, ignore = [],
   8.132 +               legacy_only = True):
   8.133          """ Get SXP representation of this config object.
   8.134  
   8.135          Incompat: removed store_mfn, console_mfn
   8.136 @@ -785,6 +806,11 @@ class XendConfig(dict):
   8.137          if domain.getDomid() is not None:
   8.138              sxpr.append(['domid', domain.getDomid()])
   8.139  
   8.140 +        if not legacy_only:
   8.141 +            for name in XENAPI_CFG_TYPES.keys():
   8.142 +                if name in self and self[name] not in (None, []):
   8.143 +                    sxpr.append([name, str(self[name])])
   8.144 +
   8.145          for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items():
   8.146              if self.has_key(xenapi) and self[xenapi] not in (None, []):
   8.147                  if type(self[xenapi]) == bool:
   8.148 @@ -1044,12 +1070,12 @@ class XendConfig(dict):
   8.149          """Returns a backwards compatible image SXP expression that is
   8.150          used in xenstore's /vm/<uuid>/image value and xm list."""
   8.151          image = [self['image'].get('type', 'linux')]
   8.152 -        if self.has_key('kernel_kernel'):
   8.153 -            image.append(['kernel', self['kernel_kernel']])
   8.154 -        if self.has_key('kernel_initrd') and self['kernel_initrd']:
   8.155 -            image.append(['ramdisk', self['kernel_initrd']])
   8.156 -        if self.has_key('kernel_args') and self['kernel_args']:
   8.157 -            image.append(['args', self['kernel_args']])
   8.158 +        if self.has_key('PV_kernel'):
   8.159 +            image.append(['kernel', self['PV_kernel']])
   8.160 +        if self.has_key('PV_ramdisk') and self['PV_ramdisk']:
   8.161 +            image.append(['ramdisk', self['PV_ramdisk']])
   8.162 +        if self.has_key('PV_args') and self['PV_args']:
   8.163 +            image.append(['args', self['PV_args']])
   8.164  
   8.165          for arg, conv in LEGACY_IMAGE_CFG:
   8.166              if self['image'].has_key(arg):
   8.167 @@ -1069,8 +1095,10 @@ class XendConfig(dict):
   8.168          return image
   8.169  
   8.170      def update_with_image_sxp(self, image_sxp):
   8.171 -        # Convert Legacy "image" config to Xen API kernel_*
   8.172 +        # Convert Legacy "image" config to Xen API PV_*
   8.173          # configuration
   8.174 +        log.debug("update_with_image_sxp(%s)" % scrub_password(image_sxp))
   8.175 +
   8.176          self['PV_kernel'] = sxp.child_value(image_sxp, 'kernel','')
   8.177          self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
   8.178          kernel_args = sxp.child_value(image_sxp, 'args', '')
     9.1 --- a/tools/python/xen/xend/XendDomain.py	Mon Dec 18 10:20:34 2006 -0700
     9.2 +++ b/tools/python/xen/xend/XendDomain.py	Mon Dec 18 10:56:34 2006 -0700
     9.3 @@ -26,6 +26,7 @@ import os
     9.4  import stat
     9.5  import shutil
     9.6  import socket
     9.7 +import tempfile
     9.8  import threading
     9.9  
    9.10  import xen.lowlevel.xc
    9.11 @@ -280,16 +281,21 @@ class XendDomain:
    9.12              make_or_raise(domain_config_dir)
    9.13  
    9.14              try:
    9.15 -                sxp_cache_file = open(self._managed_config_path(dom_uuid),'w')
    9.16 -                prettyprint(dominfo.sxpr(), sxp_cache_file, width = 78)
    9.17 -                sxp_cache_file.close()
    9.18 +                fd, fn = tempfile.mkstemp()
    9.19 +                f = os.fdopen(fd, 'w+b')
    9.20 +                try:
    9.21 +                    prettyprint(dominfo.sxpr(legacy_only = False), f,
    9.22 +                                width = 78)
    9.23 +                finally:
    9.24 +                    f.close()
    9.25 +                try:
    9.26 +                    os.rename(fn, self._managed_config_path(dom_uuid))
    9.27 +                except:
    9.28 +                    log.exception("Renaming %s" % fn)
    9.29 +                    os.remove(fn)
    9.30              except:
    9.31                  log.exception("Error occurred saving configuration file " +
    9.32                                "to %s" % domain_config_dir)
    9.33 -                try:
    9.34 -                    self._managed_domain_remove(dom_uuid)
    9.35 -                except:
    9.36 -                    pass
    9.37                  raise XendError("Failed to save configuration file to: %s" %
    9.38                                  domain_config_dir)
    9.39          else:
    10.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Dec 18 10:20:34 2006 -0700
    10.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Dec 18 10:56:34 2006 -0700
    10.3 @@ -1800,9 +1800,10 @@ class XendDomainInfo:
    10.4          log.trace("XendDomainInfo.update done on domain %s: %s",
    10.5                    str(self.domid), self.info)
    10.6  
    10.7 -    def sxpr(self, ignore_store = False):
    10.8 +    def sxpr(self, ignore_store = False, legacy_only = True):
    10.9          result = self.info.to_sxp(domain = self,
   10.10 -                                   ignore_devices = ignore_store)
   10.11 +                                  ignore_devices = ignore_store,
   10.12 +                                  legacy_only = legacy_only)
   10.13  
   10.14          if not ignore_store and self.dompath:
   10.15              vnc_port = self.readDom('console/vnc-port')
    11.1 --- a/tools/python/xen/xend/server/netif.py	Mon Dec 18 10:20:34 2006 -0700
    11.2 +++ b/tools/python/xen/xend/server/netif.py	Mon Dec 18 10:56:34 2006 -0700
    11.3 @@ -140,7 +140,7 @@ class NetifController(DevController):
    11.4  
    11.5          script = os.path.join(xroot.network_script_dir,
    11.6                                config.get('script', xroot.get_vif_script()))
    11.7 -        typ = config.get('type')
    11.8 +        typ     = config.get('type')
    11.9          bridge  = config.get('bridge')
   11.10          mac     = config.get('mac')
   11.11          vifname = config.get('vifname')
    12.1 --- a/tools/python/xen/xend/server/vfbif.py	Mon Dec 18 10:20:34 2006 -0700
    12.2 +++ b/tools/python/xen/xend/server/vfbif.py	Mon Dec 18 10:56:34 2006 -0700
    12.3 @@ -1,4 +1,5 @@
    12.4  from xen.xend.server.DevController import DevController
    12.5 +from xen.xend.XendLogging import log
    12.6  
    12.7  from xen.xend.XendError import VmError
    12.8  import xen.xend
    12.9 @@ -12,6 +13,9 @@ def spawn_detached(path, args, env):
   12.10      else:
   12.11          os.waitpid(p, 0)
   12.12          
   12.13 +CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused',
   12.14 +                  'display', 'xauthority']
   12.15 +
   12.16  class VfbifController(DevController):
   12.17      """Virtual frame buffer controller. Handles all vfb devices for a domain.
   12.18      Note that we only support a single vfb per domain at the moment.
   12.19 @@ -19,28 +23,42 @@ class VfbifController(DevController):
   12.20  
   12.21      def __init__(self, vm):
   12.22          DevController.__init__(self, vm)
   12.23 -        self.config = {}
   12.24          
   12.25      def getDeviceDetails(self, config):
   12.26          """@see DevController.getDeviceDetails"""
   12.27 -        devid = 0
   12.28 -        back = {}
   12.29 -        front = {}
   12.30 -        return (devid, back, front)
   12.31 +
   12.32 +        back = dict([(k, config[k]) for k in CONFIG_ENTRIES
   12.33 +                     if config.has_key(k)])
   12.34 +
   12.35 +        return (0, back, {})
   12.36 +
   12.37  
   12.38      def getDeviceConfiguration(self, devid):
   12.39 -        r = DevController.getDeviceConfiguration(self, devid)
   12.40 -        for (k,v) in self.config.iteritems():
   12.41 -            r[k] = v
   12.42 -        return r
   12.43 -    
   12.44 +        result = DevController.getDeviceConfiguration(self, devid)
   12.45 +
   12.46 +        devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
   12.47 +        return dict([(CONFIG_ENTRIES[i], devinfo[i])
   12.48 +                     for i in range(len(CONFIG_ENTRIES))
   12.49 +                     if devinfo[i] is not None])
   12.50 +
   12.51 +
   12.52      def createDevice(self, config):
   12.53          DevController.createDevice(self, config)
   12.54 -        self.config = config
   12.55          std_args = [ "--domid", "%d" % self.vm.getDomid(),
   12.56                       "--title", self.vm.getName() ]
   12.57          t = config.get("type", None)
   12.58          if t == "vnc":
   12.59 +            passwd = None
   12.60 +            if config.has_key("vncpasswd"):
   12.61 +                passwd = config["vncpasswd"]
   12.62 +            else:
   12.63 +                passwd = xen.xend.XendRoot.instance().get_vncpasswd_default()
   12.64 +            if passwd:
   12.65 +                self.vm.storeVm("vncpasswd", passwd)
   12.66 +                log.debug("Stored a VNC password for vfb access")
   12.67 +            else:
   12.68 +                log.debug("No VNC passwd configured for vfb access")
   12.69 +
   12.70              # Try to start the vnc backend
   12.71              args = [xen.util.auxbin.pathTo("xen-vncfb")]
   12.72              if config.has_key("vncunused"):
    13.1 --- a/tools/python/xen/xm/XenAPI.py	Mon Dec 18 10:20:34 2006 -0700
    13.2 +++ b/tools/python/xen/xm/XenAPI.py	Mon Dec 18 10:56:34 2006 -0700
    13.3 @@ -83,20 +83,24 @@ class Session(xen.util.xmlrpclib2.Server
    13.4  
    13.5  
    13.6      def xenapi_request(self, methodname, params):
    13.7 -        full_params = (self._session,) + params
    13.8 -        return _parse_result(getattr(self, methodname)(*full_params))
    13.9 +        if methodname.startswith('login'):
   13.10 +            self._login(methodname, params)
   13.11 +            return None
   13.12 +        else:
   13.13 +            full_params = (self._session,) + params
   13.14 +            return _parse_result(getattr(self, methodname)(*full_params))
   13.15  
   13.16  
   13.17 -    def _login(self, method, username, password):
   13.18 +    def _login(self, method, params):
   13.19          self._session = _parse_result(
   13.20 -            getattr(self, 'session.%s' % method)(username, password))
   13.21 +            getattr(self, 'session.%s' % method)(*params))
   13.22  
   13.23  
   13.24      def __getattr__(self, name):
   13.25          if name == 'xenapi':
   13.26              return _Dispatcher(self.xenapi_request, None)
   13.27          elif name.startswith('login'):
   13.28 -            return lambda u, p: self._login(name, u, p)
   13.29 +            return lambda *params: self._login(name, params)
   13.30          else:
   13.31              return xen.util.xmlrpclib2.ServerProxy.__getattr__(self, name)
   13.32  
    14.1 --- a/tools/python/xen/xm/create.py	Mon Dec 18 10:20:34 2006 -0700
    14.2 +++ b/tools/python/xen/xm/create.py	Mon Dec 18 10:56:34 2006 -0700
    14.3 @@ -284,7 +284,7 @@ gopts.var('usbport', val='PATH',
    14.4            use="""Add a physical USB port to a domain, as specified by the path
    14.5            to that port.  This option may be repeated to add more than one port.""")
    14.6  
    14.7 -gopts.var('vfb', val="type={vnc,sdl},vncunused=1,vncdisplay=N,vnclisten=ADDR,display=DISPLAY,xauthority=XAUTHORITY",
    14.8 +gopts.var('vfb', val="type={vnc,sdl},vncunused=1,vncdisplay=N,vnclisten=ADDR,display=DISPLAY,xauthority=XAUTHORITY,vncpasswd=PASSWORD",
    14.9            fn=append_value, default=[],
   14.10            use="""Make the domain a framebuffer backend.
   14.11            The backend type should be either sdl or vnc.
   14.12 @@ -584,7 +584,7 @@ def configure_vfbs(config_devs, vals):
   14.13              d['type'] = 'sdl'
   14.14          for (k,v) in d.iteritems():
   14.15              if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
   14.16 -                          'xauthority', 'type' ]:
   14.17 +                          'xauthority', 'type', 'vncpasswd' ]:
   14.18                  err("configuration option %s unknown to vfbs" % k)
   14.19              config.append([k,v])
   14.20          if not d.has_key("display") and os.environ.has_key("DISPLAY"):
    15.1 --- a/tools/python/xen/xm/main.py	Mon Dec 18 10:20:34 2006 -0700
    15.2 +++ b/tools/python/xen/xm/main.py	Mon Dec 18 10:56:34 2006 -0700
    15.3 @@ -558,7 +558,7 @@ class Shell(cmd.Cmd):
    15.4                  ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
    15.5                                                                     tuple(x)),
    15.6                                     words[0], words[1:])
    15.7 -                if ok and res != '':
    15.8 +                if ok and res is not None and res != '':
    15.9                      pprint.pprint(res)
   15.10              else:
   15.11                  print '*** Unknown command: %s' % words[0]
   15.12 @@ -1556,7 +1556,11 @@ def detach(args, command, deviceClass):
   15.13  
   15.14  
   15.15  def xm_block_detach(args):
   15.16 -    detach(args, 'block-detach', 'vbd')
   15.17 +    try:
   15.18 +        detach(args, 'block-detach', 'vbd')
   15.19 +        return
   15.20 +    except:
   15.21 +        pass
   15.22      detach(args, 'block-detach', 'tap')
   15.23  
   15.24  
   15.25 @@ -1798,7 +1802,7 @@ def _run_cmd(cmd, cmd_name, args):
   15.26      except OptionError, e:
   15.27          err(str(e))
   15.28          _usage(cmd_name)
   15.29 -        print e.usage()
   15.30 +        print e.usage
   15.31      except security.ACMError, e:
   15.32          err(str(e))
   15.33      except:
    16.1 --- a/tools/xenfb/vncfb.c	Mon Dec 18 10:20:34 2006 -0700
    16.2 +++ b/tools/xenfb/vncfb.c	Mon Dec 18 10:56:34 2006 -0700
    16.3 @@ -148,6 +148,10 @@ static int xk2linux[0x10000] = {
    16.4  	[XK_plus] = KEY_EQUAL,
    16.5  };
    16.6  
    16.7 +static int btnmap[] = {
    16.8 +	BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK
    16.9 +};
   16.10 +
   16.11  static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
   16.12  {
   16.13  	/*
   16.14 @@ -184,8 +188,11 @@ static void on_ptr_event(int buttonMask,
   16.15  		down = buttonMask & (1 << i);
   16.16  		if (down == last_down)
   16.17  			continue;
   16.18 -		/* FIXME this assumes buttons are numbered the same; verify they are */
   16.19 -		if (xenfb_send_key(xenfb, down != 0, BTN_MOUSE + i) < 0)
   16.20 +		if (i >= sizeof(btnmap) / sizeof(*btnmap))
   16.21 +			break;
   16.22 +		if (btnmap[i] == 0)
   16.23 +			break;
   16.24 +		if (xenfb_send_key(xenfb, down != 0, btnmap[i]) < 0)
   16.25  			fprintf(stderr, "Button %d %s lost (%s)\n",
   16.26  				i, down ? "down" : "up", strerror(errno));
   16.27  	}
   16.28 @@ -205,15 +212,10 @@ static void on_ptr_event(int buttonMask,
   16.29  	last_y = y;
   16.30  }
   16.31  
   16.32 -static void xenstore_write_vncport(int port, int domid)
   16.33 +static void xenstore_write_vncport(struct xs_handle *xsh, int port, int domid)
   16.34  {
   16.35 -	char *buf = NULL, *path;
   16.36 +	char *buf, *path;
   16.37  	char portstr[10];
   16.38 -	struct xs_handle *xsh = NULL;
   16.39 -
   16.40 -	xsh = xs_daemon_open();
   16.41 -	if (xsh == NULL)
   16.42 -		return;
   16.43  
   16.44  	path = xs_get_domain_path(xsh, domid);
   16.45  	if (path == NULL) {
   16.46 @@ -241,6 +243,56 @@ static void xenstore_write_vncport(int p
   16.47  }
   16.48  
   16.49  
   16.50 +static int xenstore_read_vncpasswd(struct xs_handle *xsh, int domid, char *pwbuf, int pwbuflen)
   16.51 +{
   16.52 +	char buf[256], *path, *uuid = NULL, *passwd = NULL;
   16.53 +	unsigned int len, rc = 0;
   16.54 +
   16.55 +	if (xsh == NULL) {
   16.56 +		return -1;
   16.57 +	}
   16.58 +
   16.59 +	path = xs_get_domain_path(xsh, domid);
   16.60 +	if (path == NULL) {
   16.61 +		fprintf(stderr, "xs_get_domain_path() error\n");
   16.62 +		return -1;
   16.63 +	}
   16.64 +
   16.65 +	snprintf(buf, 256, "%s/vm", path);
   16.66 +	uuid = xs_read(xsh, XBT_NULL, buf, &len);
   16.67 +	if (uuid == NULL) {
   16.68 +		fprintf(stderr, "xs_read(): uuid get error\n");
   16.69 +		free(path);
   16.70 +		return -1;
   16.71 +	}
   16.72 +
   16.73 +	snprintf(buf, 256, "%s/vncpasswd", uuid);
   16.74 +	passwd = xs_read(xsh, XBT_NULL, buf, &len);
   16.75 +	if (passwd == NULL) {
   16.76 +		free(uuid);
   16.77 +		free(path);
   16.78 +		return rc;
   16.79 +	}
   16.80 +
   16.81 +	strncpy(pwbuf, passwd, pwbuflen-1);
   16.82 +	pwbuf[pwbuflen-1] = '\0';
   16.83 +
   16.84 +	fprintf(stderr, "Got a VNC password read from XenStore\n");
   16.85 +
   16.86 +	passwd[0] = '\0';
   16.87 +	snprintf(buf, 256, "%s/vncpasswd", uuid);
   16.88 +	if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
   16.89 +		fprintf(stderr, "xs_write() vncpasswd failed\n");
   16.90 +		rc = -1;
   16.91 +	}
   16.92 +
   16.93 +	free(passwd);
   16.94 +	free(uuid);
   16.95 +	free(path);
   16.96 +
   16.97 +	return rc;
   16.98 +}
   16.99 +
  16.100  static void vnc_update(struct xenfb *xenfb, int x, int y, int w, int h)
  16.101  {
  16.102  	rfbScreenInfoPtr server = xenfb->user_data;
  16.103 @@ -274,6 +326,10 @@ int main(int argc, char **argv)
  16.104  	char portstr[10];
  16.105  	char *endp;
  16.106  	int r;
  16.107 +	struct xs_handle *xsh;
  16.108 +	char vncpasswd[1024];
  16.109 +
  16.110 +	vncpasswd[0] = '\0';
  16.111  
  16.112  	while ((opt = getopt_long(argc, argv, "d:p:t:u", options,
  16.113  				  NULL)) != -1) {
  16.114 @@ -346,6 +402,19 @@ int main(int argc, char **argv)
  16.115  		exit(1);
  16.116  	}
  16.117  
  16.118 +	xsh = xs_daemon_open();
  16.119 +	if (xsh == NULL) {
  16.120 +	        fprintf(stderr, "cannot open connection to xenstore\n");
  16.121 +		exit(1);
  16.122 +	}
  16.123 +
  16.124 +
  16.125 +	if (xenstore_read_vncpasswd(xsh, domid, vncpasswd, sizeof(vncpasswd)/sizeof(char)) < 0) {
  16.126 +		fprintf(stderr, "cannot read VNC password from xenstore\n");
  16.127 +		exit(1);
  16.128 +	}
  16.129 +	  
  16.130 +
  16.131  	server = rfbGetScreen(&fake_argc, fake_argv, 
  16.132  			      xenfb->width, xenfb->height,
  16.133  			      8, 3, xenfb->depth / 8);
  16.134 @@ -360,6 +429,21 @@ int main(int argc, char **argv)
  16.135          if (unused)
  16.136  		server->autoPort = true;
  16.137  
  16.138 +	if (vncpasswd[0]) {
  16.139 +		char **passwds = malloc(sizeof(char**)*2);
  16.140 +		if (!passwds) {
  16.141 +			fprintf(stderr, "cannot allocate memory (%s)\n", strerror(errno));
  16.142 +			exit(1);
  16.143 +		}
  16.144 +		fprintf(stderr, "Registered password\n");
  16.145 +		passwds[0] = vncpasswd;
  16.146 +		passwds[1] = NULL;
  16.147 +
  16.148 +		server->authPasswdData = passwds;
  16.149 +		server->passwordCheck = rfbCheckPasswordByList;
  16.150 +	} else {
  16.151 +		fprintf(stderr, "Running with no password\n");
  16.152 +	}
  16.153  	server->serverFormat.redShift = 16;
  16.154  	server->serverFormat.greenShift = 8;
  16.155  	server->serverFormat.blueShift = 0;
  16.156 @@ -372,7 +456,7 @@ int main(int argc, char **argv)
  16.157  
  16.158  	rfbRunEventLoop(server, -1, true);
  16.159  
  16.160 -        xenstore_write_vncport(server->port, domid);
  16.161 +        xenstore_write_vncport(xsh, server->port, domid);
  16.162  
  16.163  	for (;;) {
  16.164  		FD_ZERO(&readfds);
    17.1 --- a/tools/xm-test/lib/XmTestLib/acm.py	Mon Dec 18 10:20:34 2006 -0700
    17.2 +++ b/tools/xm-test/lib/XmTestLib/acm.py	Mon Dec 18 10:56:34 2006 -0700
    17.3 @@ -57,6 +57,8 @@ def ACMLabelResources(resources):
    17.4  
    17.5  # Applications may label resources explicitly by calling this function
    17.6  def ACMLabelResource(resource, label='red'):
    17.7 +    if not isACMEnabled():
    17.8 +        return
    17.9      if acm_verbose:
   17.10          print "labeling resource %s with label %s" % (resource, label)
   17.11      if not ACM_LABEL_RESOURCES: