WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] blktap2: add blktap2 device class and device control

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] blktap2: add blktap2 device class and device controller
From: "Ryan O'Connor" <rjo@xxxxxxxxx>
Date: Tue, 30 Jun 2009 17:49:44 -0700
Cc: dmeyer@xxxxxxxxx, kanno.masaki@xxxxxxxxxxxxxx, keir.fraser@xxxxxxxxxxxxx
Delivery-date: Tue, 30 Jun 2009 17:51:13 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Ryan O'Connor <rjo@xxxxxxxxx>
# Date 1246409081 25200
# Node ID 6295171d4ccc60f80f0411217d9b1c7d8543c804
# Parent  7397608bce877b151ee507413a8e228092947ee4
blktap2: add blktap2 device class and device controller

blktap2 devices must be handled differently than blktap2 devices. blktap2
devices require a sysfs write to close the underlying device, as well as extra
sysfs writes when the domU is paused/unpaused. The differences between blktap1
and blktap2 are great enough to warrant the creation of a new device class,
'tap2', and device controller for blktap2 devices.

  * add a new device controller (Blktap2Controller) and device class (tap2) for
    blktap2 devices
  * move blktap2 specific code from DevController to Blktap2Controller
  * if possible, check xenstore to determine block device class
  * use vmpath (/vm/<uuid>/) when releasing devices
  * modify linux hotplug cleanup script to handle blktap2 device removal

Signed-off-by: Ryan O'Connor <rjo@xxxxxxxxx>

diff -r 7397608bce87 -r 6295171d4ccc tools/hotplug/Linux/xen-hotplug-cleanup
--- a/tools/hotplug/Linux/xen-hotplug-cleanup   Mon Jun 29 15:50:32 2009 +0100
+++ b/tools/hotplug/Linux/xen-hotplug-cleanup   Tue Jun 30 17:44:41 2009 -0700
@@ -18,6 +18,13 @@ vm=$(xenstore_read_default "/local/domai
 # construct /vm/UUID/device/DEVCLASS/DEVID
 if [ "$vm" != "" ]; then
   vm_dev="$vm/device/${path_array[1]}/${path_array[3]}"
+
+  # if the vm path does not exist and the device class is 'vbd' then we may 
have
+  # a tap2 device
+  if [ ! $(xenstore-read "vm_dev" 2>/dev/null) ] \
+       && [ "${path_array[1]}" = "vbd" ]; then
+    vm_dev="$vm/device/tap2/${path_array[3]}"
+  fi
 else
   vm_dev=
 fi
diff -r 7397608bce87 -r 6295171d4ccc tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Mon Jun 29 15:50:32 2009 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Tue Jun 30 17:44:41 2009 -0700
@@ -1114,7 +1114,7 @@ class XendConfig(dict):
                             controller = domain.getDeviceController(cls)
                             configs = controller.configurations(txn)
                             for config in configs:
-                                if sxp.name(config) in ('vbd', 'tap'):
+                                if sxp.name(config) in ('vbd', 'tap', 'tap2'):
                                     dev_uuid = sxp.child_value(config, 'uuid')
                                     dev_type, dev_cfg = 
self['devices'][dev_uuid]
                                     if sxp.child_value(config, 'bootable', 
None) is None:
@@ -1179,7 +1179,7 @@ class XendConfig(dict):
     def device_duplicate_check(self, dev_type, dev_info, defined_config, 
config):
         defined_devices_sxpr = self.all_devices_sxpr(target = defined_config)
         
-        if dev_type == 'vbd' or dev_type == 'tap':
+        if dev_type == 'vbd' or dev_type == 'tap' or dev_type == 'tap2':
             dev_uname = dev_info.get('uname')
             blkdev_name = dev_info.get('dev')
             devid = self._blkdev_name_to_number(blkdev_name)
@@ -1187,7 +1187,7 @@ class XendConfig(dict):
                 return
             
             for o_dev_type, o_dev_info in defined_devices_sxpr:
-                if o_dev_type == 'vbd' or o_dev_type == 'tap':
+                if o_dev_type == 'vbd' or o_dev_type == 'tap' or o_dev_type == 
'tap2':
                     blkdev_file = blkdev_uname_to_file(dev_uname)
                     o_dev_uname = sxp.child_value(o_dev_info, 'uname')
                     if o_dev_uname != None:
@@ -1369,7 +1369,7 @@ class XendConfig(dict):
                 else:
                     dev_info['driver'] = 'paravirtualised'
 
-            if dev_type == 'tap':
+            if dev_type == 'tap' or dev_type == 'tap2':
                 if dev_info['uname'].split(':')[1] not in blktap_disk_types:
                     raise XendConfigError("tap:%s not a valid disk type" %
                                     dev_info['uname'].split(':')[1])
@@ -1406,7 +1406,7 @@ class XendConfig(dict):
                         # Compat hack -- mark first disk bootable
                         dev_info['bootable'] = int(not target[param])
                     target[param].append(dev_uuid)
-            elif dev_type == 'tap':
+            elif dev_type == 'tap' or dev_type == 'tap2':
                 if 'vbd_refs' not in target:
                     target['vbd_refs'] = []
                 if dev_uuid not in target['vbd_refs']:
@@ -1504,7 +1504,7 @@ class XendConfig(dict):
                 target['devices'][dev_uuid] = (dev_type, dev_info)
                 target['vif_refs'].append(dev_uuid)
             
-            elif dev_type in ('vbd', 'tap'):
+            elif dev_type in ('vbd', 'tap', 'tap2'):
                 dev_info['type'] = cfg_xenapi.get('type', 'Disk')
                 if dev_info['type'] == 'CD':
                     old_vbd_type = 'cdrom'
diff -r 7397608bce87 -r 6295171d4ccc tools/python/xen/xend/XendDevices.py
--- a/tools/python/xen/xend/XendDevices.py      Mon Jun 29 15:50:32 2009 +0100
+++ b/tools/python/xen/xend/XendDevices.py      Tue Jun 30 17:44:41 2009 -0700
@@ -20,7 +20,7 @@
 #
 
 from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, 
vscsiif
-from xen.xend.server.BlktapController import BlktapController
+from xen.xend.server.BlktapController import BlktapController, 
Blktap2Controller
 from xen.xend.server.ConsoleController import ConsoleController
 
 
@@ -42,6 +42,7 @@ class XendDevices:
         'ioports': iopif.IOPortsController,
         'irq': irqif.IRQController,
         'tap': BlktapController,
+        'tap2': Blktap2Controller,
         'vfb': vfbif.VfbifController,
         'vkbd': vfbif.VkbdifController,
         'console': ConsoleController,
diff -r 7397608bce87 -r 6295171d4ccc tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Mon Jun 29 15:50:32 2009 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Tue Jun 30 17:44:41 2009 -0700
@@ -538,12 +538,11 @@ class XendDomainInfo:
         @raise XendError: Failed pausing a domain
         """
         try:
-            bepath="/local/domain/0/backend/"
             if(self.domid):
-                
-                dev =  xstransact.List(bepath + 'vbd' + "/%d" % (self.domid,))
+                # get all blktap2 devices
+                dev =  xstransact.List(self.vmpath + 'device/tap2')
                 for x in dev:
-                    path = self.getDeviceController('vbd').readBackend(x, 
'params')
+                    path = self.getDeviceController('tap2').readBackend(x, 
'params')
                     if path and path.startswith('/dev/xen/blktap-2'):
                         #Figure out the sysfs path.
                         pattern = re.compile('/dev/xen/blktap-2/tapdev(\d+)$')
@@ -569,11 +568,10 @@ class XendDomainInfo:
         @raise XendError: Failed unpausing a domain
         """
         try:
-            bepath="/local/domain/0/backend/"
             if(self.domid):
-                dev =  xstransact.List(bepath + "vbd" + "/%d" % (self.domid,))
+                dev =  xstransact.List(self.vmpath + 'device/tap2')
                 for x in dev:
-                    path = self.getDeviceController('vbd').readBackend(x, 
'params')
+                    path = self.getDeviceController('tap2').readBackend(x, 
'params')
                     if path and path.startswith('/dev/xen/blktap-2'):
                         #Figure out the sysfs path.
                         pattern = re.compile('/dev/xen/blktap-2/tapdev(\d+)$')
@@ -812,6 +810,11 @@ class XendDomainInfo:
             try:
                 dev_config_dict['devid'] = devid = \
                     self._createDevice(dev_type, dev_config_dict)
+                if dev_type == 'tap2':
+                    # createDevice may create a blktap1 device if blktap2 is 
not
+                    # installed or if the blktap driver is not supported in
+                    # blktap1
+                    dev_type = self.getBlockDeviceClass(devid)
                 self._waitForDevice(dev_type, devid)
             except VmError, ex:
                 del self.info['devices'][dev_uuid]
@@ -821,7 +824,7 @@ class XendDomainInfo:
                 elif dev_type == 'vscsi':
                     for dev in dev_config_dict['devs']:
                         XendAPIStore.deregister(dev['uuid'], 'DSCSI')
-                elif dev_type == 'tap':
+                elif dev_type == 'tap' or dev_type == 'tap2':
                     self.info['vbd_refs'].remove(dev_uuid)
                 else:
                     self.info['%s_refs' % dev_type].remove(dev_uuid)
@@ -1200,9 +1203,10 @@ class XendDomainInfo:
         if self.domid is not None:
             
             #new blktap implementation may need a sysfs write after everything 
is torn down.
-            dev = 
self.getDeviceController(deviceClass).convertToDeviceNumber(devid)
-            path = self.getDeviceController(deviceClass).readBackend(dev, 
'params')                
-            if path and path.startswith('/dev/xen/blktap-2'):
+
+            if deviceClass == 'tap2':
+                dev = 
self.getDeviceController(deviceClass).convertToDeviceNumber(devid)
+                path = self.getDeviceController(deviceClass).readBackend(dev, 
'params')
                 frontpath = 
self.getDeviceController(deviceClass).frontendPath(dev)
                 backpath = xstransact.Read(frontpath, "backend")
                 
thread.start_new_thread(self.getDeviceController(deviceClass).finishDeviceCleanup,
 (backpath, path))
@@ -1238,7 +1242,7 @@ class XendDomainInfo:
                     dev_info = self._getDeviceInfo_vif(mac)
                 else:
                     _, dev_info = sxprs[dev]
-            else:  # 'vbd' or 'tap'
+            else:  # 'vbd' or 'tap' or 'tap2'
                 dev_info = self._getDeviceInfo_vbd(dev)
                 # To remove the UUID of the device from refs,
                 # deviceClass must be always 'vbd'.
@@ -1267,7 +1271,7 @@ class XendDomainInfo:
             sxprs = []
             dev_num = 0
             for dev_type, dev_info in self.info.all_devices_sxpr():
-                if (deviceClass == 'vbd' and dev_type not in ['vbd', 'tap']) 
or \
+                if (deviceClass == 'vbd' and dev_type not in ['vbd', 'tap', 
'tap2']) or \
                    (deviceClass != 'vbd' and dev_type != deviceClass):
                     continue
 
@@ -1295,12 +1299,27 @@ class XendDomainInfo:
             return sxprs
 
     def getBlockDeviceClass(self, devid):
-        # To get a device number from the devid,
-        # we temporarily use the device controller of VBD.
-        dev = self.getDeviceController('vbd').convertToDeviceNumber(devid)
-        dev_info = self._getDeviceInfo_vbd(dev)
-        if dev_info:
-            return dev_info[0]
+        # if the domain is running we can get the device class from xenstore.
+        # This is more accurate, as blktap1 devices show up as blktap2 devices
+        # in the config.
+        if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED, 
DOM_STATE_CRASHED):
+            # All block devices have a vbd frontend, so we know the frontend 
path
+            dev = self.getDeviceController('vbd').convertToDeviceNumber(devid)
+            frontendPath = "%s/device/vbd/%s" % (self.dompath, dev)
+            for devclass in XendDevices.valid_devices():
+                for dev in xstransact.List("%s/device/%s" % (self.vmpath, 
devclass)):
+                    devFrontendPath = 
xstransact.Read("%s/device/%s/%s/frontend" % (self.vmpath, devclass, dev))
+                    if frontendPath == devFrontendPath:
+                        return devclass
+            
+        else: # the domain is not active so we must get the device class
+              # from the config
+            # To get a device number from the devid,
+            # we temporarily use the device controller of VBD.
+            dev = self.getDeviceController('vbd').convertToDeviceNumber(devid)
+            dev_info = self._getDeviceInfo_vbd(dev)
+            if dev_info:
+                return dev_info[0]
 
     def _getDeviceInfo_vif(self, mac):
         for dev_type, dev_info in self.info.all_devices_sxpr():
@@ -1311,7 +1330,7 @@ class XendDomainInfo:
 
     def _getDeviceInfo_vbd(self, devid):
         for dev_type, dev_info in self.info.all_devices_sxpr():
-            if dev_type != 'vbd' and dev_type != 'tap':
+            if dev_type != 'vbd' and dev_type != 'tap' and dev_type != 'tap2':
                 continue
             dev = sxp.child_value(dev_info, 'dev')
             dev = dev.split(':')[0]
@@ -2256,26 +2275,19 @@ class XendDomainInfo:
             log.debug("No device model")
 
         log.debug("Releasing devices")
-        t = xstransact("%s/device" % self.dompath)
+        t = xstransact("%s/device" % self.vmpath)
         try:
             for devclass in XendDevices.valid_devices():
                 for dev in t.list(devclass):
                     try:
-                        true_devclass = devclass
-                        if devclass == 'vbd':
-                            # In the case of "vbd", the true device class
-                            # may possibly be "tap". Just in case, verify
-                            # device class.
-                            devid = dev.split('/')[-1]
-                            true_devclass = self.getBlockDeviceClass(devid)
                         log.debug("Removing %s", dev);
-                        self.destroyDevice(true_devclass, dev, False);
+                        self.destroyDevice(devclass, dev, False);
                     except:
                         # Log and swallow any exceptions in removal --
                         # there's nothing more we can do.
                         log.exception("Device release failed: %s; %s; %s",
                                       self.info['name_label'],
-                                      true_devclass, dev)
+                                      devclass, dev)
         finally:
             t.abort()
 
@@ -2948,7 +2960,7 @@ class XendDomainInfo:
 
             fn = blkdev_uname_to_file(disk)
             taptype = blkdev_uname_to_taptype(disk)
-            mounted = devtype == 'tap' and taptype != 'aio' and taptype != 
'sync' and not os.stat(fn).st_rdev
+            mounted = devtype in ['tap', 'tap2'] and taptype != 'aio' and 
taptype != 'sync' and not os.stat(fn).st_rdev
             if mounted:
                 # This is a file, not a device.  pygrub can cope with a
                 # file if it's raw, but if it's QCOW or other such formats
@@ -3052,7 +3064,8 @@ class XendDomainInfo:
             diff = time.time() - start
             vbds = self.getDeviceController('vbd').deviceIDs()
             taps = self.getDeviceController('tap').deviceIDs()
-            for i in vbds + taps:
+            tap2s = self.getDeviceController('tap2').deviceIDs()
+            for i in vbds + taps + tap2s:
                 test = 1
                 log.info("Dev %s still active, looping...", i)
                 time.sleep(0.1)
@@ -3635,7 +3648,7 @@ class XendDomainInfo:
         """
         xenapi_vbd['image'] = vdi_image_path
         if vdi_image_path.startswith('tap'):
-            dev_uuid = self.info.device_add('tap', cfg_xenapi = xenapi_vbd)
+            dev_uuid = self.info.device_add('tap2', cfg_xenapi = xenapi_vbd)
         else:
             dev_uuid = self.info.device_add('vbd', cfg_xenapi = xenapi_vbd)
             
@@ -3647,7 +3660,7 @@ class XendDomainInfo:
             _, config = self.info['devices'][dev_uuid]
             
             if vdi_image_path.startswith('tap'):
-                dev_control = self.getDeviceController('tap')
+                dev_control = self.getDeviceController('tap2')
             else:
                 dev_control = self.getDeviceController('vbd')
 
diff -r 7397608bce87 -r 6295171d4ccc 
tools/python/xen/xend/server/BlktapController.py
--- a/tools/python/xen/xend/server/BlktapController.py  Mon Jun 29 15:50:32 
2009 +0100
+++ b/tools/python/xen/xend/server/BlktapController.py  Tue Jun 30 17:44:41 
2009 -0700
@@ -24,7 +24,7 @@ blktap_disk_types = [
     'ioemu',
     'tapdisk',
     ]
- 
+
 def doexec(args, inputtext=None):
     """Execute a subprocess, then return its return code, stdout and stderr"""
     proc = popen2.Popen3(args, True)
@@ -49,8 +49,7 @@ def parseDeviceString(device):
 
     return minor, device, control
 
-
-
+# blktap1 device controller
 class BlktapController(BlkifController):
     def __init__(self, vm):
         BlkifController.__init__(self, vm)
@@ -59,11 +58,6 @@ class BlktapController(BlkifController):
         """@see DevController#frontendRoot"""
         
         return "%s/device/vbd" % self.vm.getDomainPath()
-
-    def devicePath(self, devid):
-        """@see DevController#devicePath"""
-        
-        return "%s/device/vbd/%s" % (self.vm.vmpath, devid)
 
     def getDeviceDetails(self, config):
         (devid, back, front) = BlkifController.getDeviceDetails(self, config)
@@ -123,6 +117,20 @@ class BlktapController(BlkifController):
 
         return (devid, back, front)
 
+class Blktap2Controller(BlktapController):
+    def __init__(self, vm):
+        BlktapController.__init__(self, vm)
+
+    def backendPath(self, backdom, devid):
+        if self.deviceClass == 'tap2':
+            deviceClass = 'vbd'
+        else:
+            deviceClass = 'tap'
+        return "%s/backend/%s/%s/%d" % (backdom.getDomainPath(),
+                                        deviceClass,
+                                        self.vm.getDomid(), devid)
+
+
     def createDevice(self, config):
 
         uname = config.get('required_uname', '')
@@ -140,12 +148,16 @@ class BlktapController(BlkifController):
         stderr.close();
         if( out.find("blktap2") >= 0 ):
             blktap2_installed=1;
-           
+
         if typ in ('tap'):
-            if subtyp in ('tapdisk'):                                          
+            if subtyp in ('tapdisk'):
                 if params in ('ioemu', 'qcow2', 'vmdk', 'sync') or not 
blktap2_installed:
-                    log.warn('WARNING: using deprecated blktap module');
-                    return BlkifController.createDevice(self, config);
+                    # pass this device off to BlktapController
+                    log.warn('WARNING: using deprecated blktap module')
+                    self.deviceClass = 'tap'
+                    devid = BlktapController.createDevice(self, config)
+                    self.deviceClass = 'tap2'
+                    return devid
 
         cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file) ]
         (rc,stdout,stderr) = doexec(cmd)
@@ -165,7 +177,32 @@ class BlktapController(BlkifController):
         #device is configured.  Then continue to create the device
         config.update({'uname' : 'phy:' + device.rstrip()})
 
-        self.deviceClass='vbd'
         devid = BlkifController.createDevice(self, config)
-        self.deviceClass='tap'
         return devid
+
+    # The new blocktap implementation requires a sysfs signal to close
+    # out disks.  This function is called from a thread when the
+    # domain is detached from the disk.
+    def finishDeviceCleanup(self, backpath, path):
+        """Perform any device specific cleanup
+
+        @backpath backend xenstore path.
+        @path frontend device path
+
+        """
+
+        #Figure out what we're going to wait on.
+        self.waitForBackend_destroy(backpath)
+
+        #Figure out the sysfs path.
+        pattern = re.compile('/dev/xen/blktap-2/tapdev(\d+)$')
+        ctrlid = pattern.search(path)
+        ctrl = '/sys/class/blktap2/blktap' + ctrlid.group(1)
+
+        #Close out the disk
+        f = open(ctrl + '/remove', 'w')
+        f.write('remove');
+        f.close()
+
+        return
+
diff -r 7397608bce87 -r 6295171d4ccc 
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py     Mon Jun 29 15:50:32 
2009 +0100
+++ b/tools/python/xen/xend/server/DevController.py     Tue Jun 30 17:44:41 
2009 -0700
@@ -238,34 +238,6 @@ class DevController:
             # xstransact.Remove(self.devicePath()) ?? Below is the same ?
             self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev))
 
-    # The new blocktap implementation requires a sysfs signal to close
-    # out disks.  This function is called from a thread when the
-    # domain is detached from the disk.
-    def finishDeviceCleanup(self, backpath, path):
-        """Perform any device specific cleanup
-
-        @backpath backend xenstore path.
-        @path frontend device path
-
-        """
-        
-        if path and path.startswith('/dev/xen/blktap-2'):
-            
-            #Figure out what we're going to wait on.
-            self.waitForBackend_destroy(backpath)            
-
-            #Figure out the sysfs path.
-            pattern = re.compile('/dev/xen/blktap-2/tapdev(\d+)$')
-            ctrlid = pattern.search(path)
-            ctrl = '/sys/class/blktap2/blktap' + ctrlid.group(1)
-            
-            #Close out the disk
-            f = open(ctrl + '/remove', 'w')
-            f.write('remove');
-            f.close()
-
-        return
-
     def configurations(self, transaction = None):
         return map(lambda x: self.configuration(x, transaction), 
self.deviceIDs(transaction))
 
@@ -575,7 +547,6 @@ class DevController:
             
         backpath = self.readVm(devid, "backend")
 
-
         if backpath:
             statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
             ev = Event()
diff -r 7397608bce87 -r 6295171d4ccc tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Mon Jun 29 15:50:32 2009 +0100
+++ b/tools/python/xen/xm/create.py     Tue Jun 30 17:44:41 2009 -0700
@@ -718,7 +718,7 @@ def configure_disks(config_devs, vals):
     """
     for (uname, dev, mode, backend, protocol) in vals.disk:
         if uname.startswith('tap:'):
-            cls = 'tap'
+            cls = 'tap2'
         else:
             cls = 'vbd'
 
diff -r 7397608bce87 -r 6295171d4ccc tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Mon Jun 29 15:50:32 2009 +0100
+++ b/tools/python/xen/xm/main.py       Tue Jun 30 17:44:41 2009 -0700
@@ -2371,7 +2371,7 @@ def parse_block_configuration(args):
     dom = args[0]
 
     if args[1].startswith('tap:'):
-        cls = 'tap'
+        cls = 'tap2'
     else:
         cls = 'vbd'
 
@@ -2706,7 +2706,9 @@ def xm_block_detach(args):
         dom = args[0]
         dev = args[1]
         dc = server.xend.domain.getBlockDeviceClass(dom, dev)
-        if dc == "tap":
+        if dc == "tap2":
+            detach(args, 'tap2')
+        elif dc == "tap":
             detach(args, 'tap')
         else:
             detach(args, 'vbd')

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel