ia64/xen-unstable

changeset 1329:1adc57be9bfa

bitkeeper revision 1.879.2.1 (4092738fCfvp-pu-UzwhXsHdzHbYPw)

Completed first cut of new blkdev i/o world.
author kaf24@scramble.cl.cam.ac.uk
date Fri Apr 30 15:41:03 2004 +0000 (2004-04-30)
parents 7178b507e88b
children c31e790d45bd
files .rootkeys tools/examples/xc_dom_create.py tools/xend/lib/blkif.py tools/xend/lib/console.py tools/xend/lib/domain_controller.h tools/xend/lib/main.py tools/xend/lib/manager.py xen/common/event_channel.c xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/common.h xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/control.c xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/interface.c xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/vbd.c xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/main.c xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/vbd.c xenolinux-2.4.26-sparse/include/asm-xen/io.h
line diff
     1.1 --- a/.rootkeys	Wed Apr 28 14:08:16 2004 +0000
     1.2 +++ b/.rootkeys	Fri Apr 30 15:41:03 2004 +0000
     1.3 @@ -102,6 +102,7 @@ 3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xen
     1.4  4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
     1.5  40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
     1.6  4055ad95Se-FqttgxollqOAAHB94zA tools/xend/lib/__init__.py
     1.7 +4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend/lib/blkif.py
     1.8  4055ad97wMLUj0BZT0e_T0EwQN0Bvw tools/xend/lib/console.py
     1.9  4048c0ddsF0WrU7HUzTvg1MJoCIfWg tools/xend/lib/domain_controller.h
    1.10  4054a301VEag2GwrBrFBna5U1BGlLA tools/xend/lib/main.py
     2.1 --- a/tools/examples/xc_dom_create.py	Wed Apr 28 14:08:16 2004 +0000
     2.2 +++ b/tools/examples/xc_dom_create.py	Fri Apr 30 15:41:03 2004 +0000
     2.3 @@ -1,7 +1,7 @@
     2.4  #!/usr/bin/env python
     2.5  
     2.6  import string, sys, os, time, socket, getopt, signal, syslog
     2.7 -import Xc, xenctl.utils, xenctl.console_client
     2.8 +import Xc, xenctl.utils, xenctl.console_client, re
     2.9  
    2.10  config_dir  = '/etc/xc/'
    2.11  config_file = xc_config_file = config_dir + 'defaults'
    2.12 @@ -195,6 +195,15 @@ output('VM cmdline         : "%s"' % cmd
    2.13  if dryrun:
    2.14      sys.exit(1)
    2.15  
    2.16 +##### HACK HACK HACK
    2.17 +##### Until everyone moves to the new I/O world, and a more robust domain
    2.18 +##### controller (xend), we use this little trick to discover whether we
    2.19 +##### are in a testing environment for new I/O stuff.
    2.20 +new_io_world = True
    2.21 +for line in os.popen('cat /proc/interrupts').readlines():
    2.22 +    if re.search('blkdev', line):
    2.23 +        new_io_world = False
    2.24 +
    2.25  ##### Code beyond this point is actually used to manage the mechanics of
    2.26  ##### starting (and watching if necessary) guest virtual machines.
    2.27  
    2.28 @@ -228,14 +237,14 @@ def make_domain():
    2.29  
    2.30      cmsg = 'new_control_interface(dom='+str(id)+', console_port='+str(console_port)+')'
    2.31  
    2.32 -    xend_response = xenctl.utils.xend_control_message(cmsg)
    2.33 +    cons_response = xenctl.utils.xend_control_message(cmsg)
    2.34  
    2.35 -    if not xend_response['success']:
    2.36 +    if not cons_response['success']:
    2.37  	print "Error creating initial event channel"
    2.38 -	print "Error type: " + xend_response['error_type']
    2.39 -	if xend_response['error_type'] == 'exception':
    2.40 -	    print "Exception type: " + xend_response['exception_type']
    2.41 -	    print "Exception value: " + xend_response['exception_value']
    2.42 +	print "Error type: " + cons_response['error_type']
    2.43 +	if cons_response['error_type'] == 'exception':
    2.44 +	    print "Exception type: " + cons_response['exception_type']
    2.45 +	    print "Exception value: " + cons_response['exception_value']
    2.46  	xc.domain_destroy ( dom=id )
    2.47  	sys.exit()
    2.48  
    2.49 @@ -248,7 +257,7 @@ def make_domain():
    2.50              sys.exit()
    2.51      else:
    2.52  
    2.53 -        ret = eval('xc.%s_build ( dom=id, image=image, ramdisk=ramdisk, cmdline=cmdline, control_evtchn=xend_response["remote_port"] )' % builder_fn)
    2.54 +        ret = eval('xc.%s_build ( dom=id, image=image, ramdisk=ramdisk, cmdline=cmdline, control_evtchn=cons_response["remote_port"] )' % builder_fn)
    2.55          if ret < 0:
    2.56              print "Error building Linux guest OS: "
    2.57              print "Return code = " + str(ret)
    2.58 @@ -259,6 +268,18 @@ def make_domain():
    2.59  
    2.60      # set the expertise level appropriately
    2.61      xenctl.utils.VBD_EXPERT_MODE = vbd_expert
    2.62 +
    2.63 +    if new_io_world:
    2.64 +        cmsg = 'new_block_interface(dom='+str(id)+')'
    2.65 +        xend_response = xenctl.utils.xend_control_message(cmsg)
    2.66 +        if not xend_response['success']:
    2.67 +            print "Error creating block interface"
    2.68 +            print "Error type: " + xend_response['error_type']
    2.69 +            if xend_response['error_type'] == 'exception':
    2.70 +                print "Exception type: " + xend_response['exception_type']
    2.71 +                print "Exception val:  " + xend_response['exception_value']
    2.72 +            xc.domain_destroy ( dom=id )
    2.73 +            sys.exit()
    2.74      
    2.75      for ( uname, virt_name, rw ) in vbd_list:
    2.76  	virt_dev = xenctl.utils.blkdev_name_to_number( virt_name )
    2.77 @@ -269,42 +290,70 @@ def make_domain():
    2.78  	    xc.domain_destroy ( dom=id )
    2.79  	    sys.exit()
    2.80  
    2.81 -        # check that setting up this VBD won't violate the sharing
    2.82 -        # allowed by the current VBD expertise level
    2.83 -        if xenctl.utils.vd_extents_validate(segments, rw=='w' or rw=='rw') < 0:
    2.84 -            xc.domain_destroy( dom = id )
    2.85 -            sys.exit()
    2.86 +        if new_io_world:
    2.87 +            if len(segments) > 1:
    2.88 +                print "New I/O world cannot deal with multi-extent vdisks"
    2.89 +                xc.domain_destroy ( dom=id )
    2.90 +                sys.exit()
    2.91 +            seg = segments[0]
    2.92 +            cmsg = 'new_block_device(dom=' + str(id) + \
    2.93 +                   ',handle=0,vdev=' + str(virt_dev) + \
    2.94 +                   ',pdev=' + str(seg['device']) + \
    2.95 +                   ',start_sect=' + str(seg['start_sector']) + \
    2.96 +                   ',nr_sect=' + str(seg['nr_sectors']) + \
    2.97 +                   ',readonly=' + str(not re.match('w',rw)) + ')'
    2.98 +            xend_response = xenctl.utils.xend_control_message(cmsg)
    2.99 +            if not xend_response['success']:
   2.100 +                print "Error creating virtual block device"
   2.101 +                print "Error type: " + xend_response['error_type']
   2.102 +                if xend_response['error_type'] == 'exception':
   2.103 +                    print "Exception type: " + xend_response['exception_type']
   2.104 +                    print "Exception val:  " + xend_response['exception_value']
   2.105 +                xc.domain_destroy ( dom=id )
   2.106 +                sys.exit()
   2.107 +        else:
   2.108 +            # check that setting up this VBD won't violate the sharing
   2.109 +            # allowed by the current VBD expertise level
   2.110 +            if xenctl.utils.vd_extents_validate(segments,
   2.111 +                                                rw=='w' or rw=='rw') < 0:
   2.112 +                xc.domain_destroy( dom = id )
   2.113 +                sys.exit()
   2.114              
   2.115 -	if xc.vbd_create( dom=id, vbd=virt_dev, writeable= rw=='w' or rw=='rw' ):
   2.116 -	    print "Error creating VBD vbd=%d writeable=%d\n" % (virt_dev,rw)
   2.117 -	    xc.domain_destroy ( dom=id )
   2.118 -	    sys.exit()
   2.119 +            if xc.vbd_create( dom=id, vbd=virt_dev,
   2.120 +                              writeable= rw=='w' or rw=='rw' ):
   2.121 +                print "Error creating VBD %d (writeable=%d)\n" % (virt_dev,rw)
   2.122 +                xc.domain_destroy ( dom=id )
   2.123 +                sys.exit()
   2.124  	
   2.125 -        if xc.vbd_setextents( dom=id,
   2.126 -                              vbd=virt_dev,
   2.127 -                              extents=segments):
   2.128 -            print "Error populating VBD vbd=%d\n" % virt_dev
   2.129 -            xc.domain_destroy ( dom=id )
   2.130 -            sys.exit()
   2.131 +            if xc.vbd_setextents( dom=id,
   2.132 +                                  vbd=virt_dev,
   2.133 +                                  extents=segments):
   2.134 +                print "Error populating VBD vbd=%d\n" % virt_dev
   2.135 +                xc.domain_destroy ( dom=id )
   2.136 +                sys.exit()
   2.137  
   2.138 -    # setup virtual firewall rules for all aliases
   2.139 -    for ip in vfr_ipaddr:
   2.140 -	xenctl.utils.setup_vfr_rules_for_vif( id, 0, ip )
   2.141 +    if not new_io_world:
   2.142 +        # setup virtual firewall rules for all aliases
   2.143 +        for ip in vfr_ipaddr:
   2.144 +            xenctl.utils.setup_vfr_rules_for_vif( id, 0, ip )
   2.145  
   2.146 -    # check for physical device access
   2.147 -    for (pci_bus, pci_dev, pci_func) in pci_device_list:
   2.148 -        if xc.physdev_pci_access_modify(
   2.149 -            dom=id, bus=pci_bus, dev=pci_dev, func=pci_func, enable=1 ) < 0:
   2.150 -            print "Non-fatal error enabling PCI device access."
   2.151 -        else:
   2.152 -            print "Enabled PCI access (%d:%d:%d)." % (pci_bus,pci_dev,pci_func)
   2.153 +    if new_io_world:
   2.154 +        # check for physical device access
   2.155 +        for (pci_bus, pci_dev, pci_func) in pci_device_list:
   2.156 +            if xc.physdev_pci_access_modify(
   2.157 +                dom=id, bus=pci_bus, dev=pci_dev,
   2.158 +                func=pci_func, enable=1 ) < 0:
   2.159 +                print "Non-fatal error enabling PCI device access."
   2.160 +            else:
   2.161 +                print "Enabled PCI access (%d:%d:%d)." % \
   2.162 +                      (pci_bus,pci_dev,pci_func)
   2.163  
   2.164      if xc.domain_start( dom=id ) < 0:
   2.165          print "Error starting domain"
   2.166          xc.domain_destroy ( dom=id )
   2.167          sys.exit()
   2.168  
   2.169 -    return (id, xend_response['console_port'])
   2.170 +    return (id, cons_response['console_port'])
   2.171  # end of make_domain()
   2.172  
   2.173  def mkpidfile():
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/xend/lib/blkif.py	Fri Apr 30 15:41:03 2004 +0000
     3.3 @@ -0,0 +1,143 @@
     3.4 +
     3.5 +#################################################################
     3.6 +## xend/blkif.py -- Block-interface management functions for Xend
     3.7 +## Copyright (c) 2004, K A Fraser (University of Cambridge)
     3.8 +#################################################################
     3.9 +
    3.10 +import errno, re, os, select, signal, socket, struct, sys
    3.11 +import xend.main, xend.console, xend.manager, xend.utils, Xc
    3.12 +
    3.13 +CMSG_BLKIF_BE = 1
    3.14 +CMSG_BLKIF_FE = 2
    3.15 +CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
    3.16 +CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
    3.17 +CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
    3.18 +CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
    3.19 +CMSG_BLKIF_BE_CREATE      = 0
    3.20 +CMSG_BLKIF_BE_DESTROY     = 1
    3.21 +CMSG_BLKIF_BE_CONNECT     = 2
    3.22 +CMSG_BLKIF_BE_DISCONNECT  = 3
    3.23 +CMSG_BLKIF_BE_VBD_CREATE  = 4
    3.24 +CMSG_BLKIF_BE_VBD_DESTROY = 5
    3.25 +CMSG_BLKIF_BE_VBD_GROW    = 6
    3.26 +CMSG_BLKIF_BE_VBD_SHRINK  = 7
    3.27 +
    3.28 +pendmsg = None
    3.29 +pendaddr = None
    3.30 +
    3.31 +def backend_tx_req(msg):
    3.32 +    port = xend.main.dom0_port
    3.33 +    if port.space_to_write_request():
    3.34 +        port.write_request(msg)
    3.35 +        port.notify()
    3.36 +    else:
    3.37 +        xend.blkif.pendmsg = msg
    3.38 +
    3.39 +def backend_rx_req(port, msg):
    3.40 +    port.write_response(msg)
    3.41 +
    3.42 +def backend_rx_rsp(port, msg):
    3.43 +    subtype = (msg.get_header())['subtype']
    3.44 +    print "Received blkif-be response, subtype %d" % subtype
    3.45 +    if subtype == CMSG_BLKIF_BE_CREATE:
    3.46 +        rsp = { 'success': True }
    3.47 +        xend.main.send_management_response(rsp, xend.blkif.pendaddr)
    3.48 +    elif subtype == CMSG_BLKIF_BE_CONNECT:
    3.49 +        (dom,hnd,evtchn,frame,st) = struct.unpack("QIILI", msg.get_payload())
    3.50 +        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
    3.51 +        msg = xend.utils.message(CMSG_BLKIF_FE, \
    3.52 +                                 CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, 0)
    3.53 +        msg.append_payload(struct.pack("III",0,2,blkif.evtchn['port2']))
    3.54 +        blkif.ctrlif_tx_req(xend.main.port_list[blkif.key], msg)
    3.55 +    elif subtype == CMSG_BLKIF_BE_VBD_CREATE:
    3.56 +        (dom,hnd,vdev,ro,st) = struct.unpack("QIHII", msg.get_payload())
    3.57 +        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
    3.58 +        (pdev, start_sect, nr_sect, readonly) = blkif.devices[vdev]
    3.59 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW, 0)
    3.60 +        msg.append_payload(struct.pack("QIHHHQQI",dom,0,vdev,0, \
    3.61 +                                       pdev,start_sect,nr_sect,0))
    3.62 +        backend_tx_req(msg)
    3.63 +    elif subtype == CMSG_BLKIF_BE_VBD_GROW:
    3.64 +        rsp = { 'success': True }
    3.65 +        xend.main.send_management_response(rsp, xend.blkif.pendaddr)
    3.66 +
    3.67 +def backend_do_work(port):
    3.68 +    global pendmsg
    3.69 +    if pendmsg and port.space_to_write_request():
    3.70 +        port.write_request(pendmsg)
    3.71 +        pendmsg = None
    3.72 +        return True
    3.73 +    return False
    3.74 +
    3.75 +
    3.76 +class interface:
    3.77 +
    3.78 +    # Dictionary of all block-device interfaces.
    3.79 +    list = {}
    3.80 +
    3.81 +
    3.82 +    # NB. 'key' is an opaque value that has no meaning in this class.
    3.83 +    def __init__(self, dom, key):
    3.84 +        self.dom     = dom
    3.85 +        self.key     = key
    3.86 +        self.devices = {}
    3.87 +        self.pendmsg = None
    3.88 +        interface.list[key] = self
    3.89 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE, 0)
    3.90 +        msg.append_payload(struct.pack("QII",dom,0,0))
    3.91 +        xend.blkif.pendaddr = xend.main.mgmt_req_addr
    3.92 +        backend_tx_req(msg)
    3.93 +
    3.94 +    # Attach a device to the specified interface
    3.95 +    def attach_device(self, vdev, pdev, start_sect, nr_sect, readonly):
    3.96 +        if self.devices.has_key(vdev):
    3.97 +            return False
    3.98 +        self.devices[vdev] = (pdev, start_sect, nr_sect, readonly)
    3.99 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE, 0)
   3.100 +        msg.append_payload(struct.pack("QIHII",self.dom,0,vdev,readonly,0))
   3.101 +        xend.blkif.pendaddr = xend.main.mgmt_req_addr
   3.102 +        backend_tx_req(msg)
   3.103 +        return True
   3.104 +
   3.105 +
   3.106 +    # Completely destroy this interface.
   3.107 +    def destroy(self):
   3.108 +        del interface.list[self.key]
   3.109 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY, 0)
   3.110 +        msg.append_payload(struct.pack("QII",self.dom,0,0))
   3.111 +        backend_tx_req(msg)        
   3.112 +
   3.113 +
   3.114 +    # The parameter @port is the control-interface event channel. This method
   3.115 +    # returns True if messages were written to the control interface.
   3.116 +    def ctrlif_transmit_work(self, port):
   3.117 +        if self.pendmsg and port.space_to_write_request():
   3.118 +            port.write_request(self.pendmsg)
   3.119 +            self.pendmsg = None
   3.120 +            return True
   3.121 +        return False
   3.122 +
   3.123 +    def ctrlif_tx_req(self, port, msg):
   3.124 +        if port.space_to_write_request():
   3.125 +            port.write_request(msg)
   3.126 +            port.notify()
   3.127 +        else:
   3.128 +            self.pendmsg = msg
   3.129 +
   3.130 +    def ctrlif_rx_req(self, port, msg):
   3.131 +        port.write_response(msg)
   3.132 +        subtype = (msg.get_header())['subtype']
   3.133 +        if subtype == CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
   3.134 +            msg = xend.utils.message(CMSG_BLKIF_FE, \
   3.135 +                                     CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, 0)
   3.136 +            msg.append_payload(struct.pack("III",0,1,0))
   3.137 +            self.ctrlif_tx_req(port, msg)
   3.138 +        elif subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT:
   3.139 +            (hnd,frame) = struct.unpack("IL", msg.get_payload())
   3.140 +            xc = Xc.new()
   3.141 +            self.evtchn = xc.evtchn_bind_interdomain(dom1=0,dom2=self.dom)
   3.142 +            msg = xend.utils.message(CMSG_BLKIF_BE, \
   3.143 +                                     CMSG_BLKIF_BE_CONNECT, 0)
   3.144 +            msg.append_payload(struct.pack("QIILI",self.dom,0, \
   3.145 +                                           self.evtchn['port1'],frame,0))
   3.146 +            backend_tx_req(msg)
     4.1 --- a/tools/xend/lib/console.py	Wed Apr 28 14:08:16 2004 +0000
     4.2 +++ b/tools/xend/lib/console.py	Fri Apr 30 15:41:03 2004 +0000
     4.3 @@ -5,7 +5,7 @@
     4.4  #############################################################
     4.5  
     4.6  import errno, re, os, select, signal, socket, struct, sys
     4.7 -
     4.8 +import xend.blkif, xend.main, xend.manager, xend.utils, Xc
     4.9  
    4.10  ##
    4.11  ## interface:
    4.12 @@ -16,7 +16,7 @@ import errno, re, os, select, signal, so
    4.13  ##   CONNECTED: sending/receiving console data on TCP port 'self.port'
    4.14  ##
    4.15  ##  A dictionary of all active interfaces, indexed by TCP socket descriptor,
    4.16 -##  is accessible as 'interface.interface_list'.
    4.17 +##  is accessible as 'interface.list_by_fd'.
    4.18  ##
    4.19  ##  NB. When a class instance is to be destroyed you *must* call the 'close'
    4.20  ##  method. Otherwise a stale reference will eb left in the interface list.
    4.21 @@ -30,7 +30,11 @@ class interface:
    4.22  
    4.23  
    4.24      # Dictionary of all active (non-closed) console interfaces.
    4.25 -    interface_list = {}
    4.26 +    list_by_fd = {}
    4.27 +
    4.28 +
    4.29 +    # Dictionary of all console interfaces, closed and open.
    4.30 +    list = {}
    4.31  
    4.32  
    4.33      # NB. 'key' is an opaque value that has no meaning in this class.
    4.34 @@ -38,6 +42,9 @@ class interface:
    4.35          self.status = interface.CLOSED
    4.36          self.port   = port
    4.37          self.key    = key
    4.38 +        self.rbuf   = xend.utils.buffer()
    4.39 +        self.wbuf   = xend.utils.buffer()
    4.40 +        interface.list[key] = self
    4.41  
    4.42  
    4.43      # Is this interface closed (inactive)?
    4.44 @@ -58,14 +65,14 @@ class interface:
    4.45      # Close the interface, if it is not closed already.
    4.46      def close(self):
    4.47          if not self.closed():
    4.48 -            del interface.interface_list[self.sock.fileno()]
    4.49 +            del interface.list_by_fd[self.sock.fileno()]
    4.50              self.sock.close()
    4.51              del self.sock
    4.52              self.status = interface.CLOSED
    4.53  
    4.54  
    4.55      # Move the interface into the 'listening' state. Opens a new listening
    4.56 -    # socket and updates 'interface_list'.
    4.57 +    # socket and updates 'list_by_fd'.
    4.58      def listen(self):
    4.59          # Close old socket (if any), and create a fresh one.
    4.60          self.close()
    4.61 @@ -80,7 +87,7 @@ class interface:
    4.62  
    4.63              # Announce the new status of thsi interface.
    4.64              self.status = interface.LISTENING
    4.65 -            interface.interface_list[self.sock.fileno()] = self
    4.66 +            interface.list_by_fd[self.sock.fileno()] = self
    4.67  
    4.68          except:
    4.69              # In case of trouble ensure we get rid of dangling socket reference
    4.70 @@ -105,7 +112,69 @@ class interface:
    4.71          # Publish the new socket and the new interface state.
    4.72          self.sock = sock
    4.73          self.status = interface.CONNECTED
    4.74 -        interface.interface_list[self.sock.fileno()] = self
    4.75 +        interface.list_by_fd[self.sock.fileno()] = self
    4.76          return 1
    4.77  
    4.78  
    4.79 +    # Completely sestroy a console interface.
    4.80 +    def destroy(self):
    4.81 +        self.close()
    4.82 +        del interface.list[self.key]
    4.83 +
    4.84 +
    4.85 +    # Do work triggered by resource availability on a console-interface socket.
    4.86 +    def socket_work(self):
    4.87 +        # If the interface is listening, check for pending connections.
    4.88 +        if self.listening():
    4.89 +            self.connect()
    4.90 +
    4.91 +        # All done if the interface is not connected.
    4.92 +        if not self.connected():
    4.93 +            return
    4.94 +
    4.95 +        # Send as much pending data as possible via the socket.
    4.96 +        while not self.rbuf.empty():
    4.97 +            try:
    4.98 +                bytes = self.sock.send(self.rbuf.peek())
    4.99 +                if bytes > 0:
   4.100 +                    self.rbuf.discard(bytes)
   4.101 +            except socket.error, error:
   4.102 +                pass
   4.103 +
   4.104 +        # Read as much data as is available. Don't worry about
   4.105 +        # overflowing our buffer: it's more important to read the
   4.106 +        # incoming data stream and detect errors or closure of the
   4.107 +        # remote end in a timely manner.
   4.108 +        try:
   4.109 +            while 1:
   4.110 +                data = self.sock.recv(2048)
   4.111 +                # Return of zero means the remote end has disconnected.
   4.112 +                # We therefore return the console interface to listening.
   4.113 +                if not data:
   4.114 +                    self.listen()
   4.115 +                    break
   4.116 +                self.wbuf.write(data)
   4.117 +        except socket.error, error:
   4.118 +            # Assume that most errors mean that the connection is dead.
   4.119 +            # In such cases we return the interface to 'listening' state.
   4.120 +            if error[0] != errno.EAGAIN:
   4.121 +                print "Better return to listening"
   4.122 +                self.listen()
   4.123 +                print "New status: " + str(self.status)
   4.124 +
   4.125 +
   4.126 +    # The parameter @port is the control-interface event channel. This method
   4.127 +    # returns True if messages were written to the control interface.
   4.128 +    def ctrlif_transmit_work(self, port):
   4.129 +        work_done = False
   4.130 +        while not self.wbuf.empty() and port.space_to_write_request():
   4.131 +            msg = xend.utils.message(0, 0, 0)
   4.132 +            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
   4.133 +            port.write_request(msg)
   4.134 +            work_done = True
   4.135 +        return work_done
   4.136 +
   4.137 +
   4.138 +    def ctrlif_rx_req(self, port, msg):
   4.139 +        self.rbuf.write(msg.get_payload())
   4.140 +        port.write_response(msg)
     5.1 --- a/tools/xend/lib/domain_controller.h	Wed Apr 28 14:08:16 2004 +0000
     5.2 +++ b/tools/xend/lib/domain_controller.h	Fri Apr 30 15:41:03 2004 +0000
     5.3 @@ -76,8 +76,8 @@ typedef struct {
     5.4  
     5.5  /* Messages from guest to domain controller. */
     5.6  #define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
     5.7 -#define CMSG_BLKIF_FE_INTERFACE_UP              33
     5.8 -#define CMSG_BLKIF_FE_INTERFACE_DOWN            34
     5.9 +#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
    5.10 +#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
    5.11  
    5.12  /* These are used by both front-end and back-end drivers. */
    5.13  #define blkif_vdev_t   u16
    5.14 @@ -91,13 +91,13 @@ typedef struct {
    5.15   *   1. The shared-memory frame is available for reuse.
    5.16   *   2. Any unacknowledged messgaes pending on the interface were dropped.
    5.17   */
    5.18 -#define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist.      */
    5.19 -#define BLKIF_INTERFACE_STATUS_DOWN      1 /* Interface exists but is down. */
    5.20 -#define BLKIF_INTERFACE_STATUS_UP        2 /* Interface exists and is up.   */
    5.21 +#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
    5.22 +#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
    5.23 +#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
    5.24  typedef struct {
    5.25      unsigned int handle;
    5.26      unsigned int status;
    5.27 -    unsigned int evtchn; /* status == BLKIF_INTERFACE_STATUS_UP */
    5.28 +    unsigned int evtchn; /* status == BLKIF_INTERFACE_STATUS_CONNECTED */
    5.29  } blkif_fe_interface_status_changed_t;
    5.30  
    5.31  /*
    5.32 @@ -109,30 +109,37 @@ typedef struct {
    5.33   *  If the driver goes DOWN while interfaces are still UP, the domain
    5.34   *  will automatically take the interfaces DOWN.
    5.35   */
    5.36 -#define BLKIF_DRIVER_STATUS_DOWN         0
    5.37 -#define BLKIF_DRIVER_STATUS_UP           1
    5.38 +#define BLKIF_DRIVER_STATUS_DOWN   0
    5.39 +#define BLKIF_DRIVER_STATUS_UP     1
    5.40  typedef struct {
    5.41      unsigned int status; /* BLKIF_DRIVER_STATUS_??? */
    5.42  } blkif_fe_driver_status_changed_t;
    5.43  
    5.44  /*
    5.45 - * CMSG_BLKIF_FE_INTERFACE_UP:
    5.46 - *  If successful, the domain controller will acknowledge with a STATUS_UP
    5.47 - *  message.
    5.48 + * CMSG_BLKIF_FE_INTERFACE_CONNECT:
    5.49 + *  If successful, the domain controller will acknowledge with a
    5.50 + *  STATUS_CONNECTED message.
    5.51   */
    5.52  typedef struct {
    5.53      unsigned int  handle;
    5.54      unsigned long shmem_frame;
    5.55 -} blkif_fe_interface_up_t;
    5.56 +} blkif_fe_interface_connect_t;
    5.57  
    5.58  /*
    5.59 - * CMSG_BLKIF_FE_INTERFACE_DOWN:
    5.60 - *  If successful, the domain controller will acknowledge with a STATUS_DOWN
    5.61 - *  message.
    5.62 + * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
    5.63 + *  If successful, the domain controller will acknowledge with a
    5.64 + *  STATUS_DISCONNECTED message.
    5.65   */
    5.66  typedef struct {
    5.67 +    /* IN */
    5.68      unsigned int handle;
    5.69 -} blkif_fe_interface_down_t;
    5.70 +    /* OUT */
    5.71 +    /*
    5.72 +     * Tells driver how many interfaces it should expect to immediately
    5.73 +     * receive notifications about.
    5.74 +     */
    5.75 +    unsigned int nr_interfaces;
    5.76 +} blkif_fe_interface_disconnect_t;
    5.77  
    5.78  
    5.79  /******************************************************************************
    5.80 @@ -142,10 +149,12 @@ typedef struct {
    5.81  /* Messages from domain controller. */
    5.82  #define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
    5.83  #define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
    5.84 -#define CMSG_BLKIF_BE_VBD_CREATE  2  /* Create a new VBD for an interface.   */
    5.85 -#define CMSG_BLKIF_BE_VBD_DESTROY 3  /* Delete a VBD from an interface.      */
    5.86 -#define CMSG_BLKIF_BE_VBD_GROW    4  /* Append an extent to a given VBD.     */
    5.87 -#define CMSG_BLKIF_BE_VBD_SHRINK  5  /* Remove last extent from a given VBD. */
    5.88 +#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
    5.89 +#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
    5.90 +#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
    5.91 +#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
    5.92 +#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
    5.93 +#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
    5.94  
    5.95  /* Messages to domain controller. */
    5.96  #define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
    5.97 @@ -167,53 +176,83 @@ typedef struct {
    5.98  /* The following are specific error returns. */
    5.99  #define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
   5.100  #define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
   5.101 -#define BLKIF_BE_STATUS_VBD_EXISTS          4
   5.102 -#define BLKIF_BE_STATUS_VBD_NOT_FOUND       5
   5.103 -#define BLKIF_BE_STATUS_OUT_OF_MEMORY       6
   5.104 -#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    7
   5.105 -#define BLKIF_BE_STATUS_MAPPING_ERROR       8
   5.106 +#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
   5.107 +#define BLKIF_BE_STATUS_VBD_EXISTS          5
   5.108 +#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
   5.109 +#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
   5.110 +#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
   5.111 +#define BLKIF_BE_STATUS_MAPPING_ERROR       9
   5.112  
   5.113  /* This macro can be used to create an array of descriptive error strings. */
   5.114 -#define BLKIF_BE_STATUS_ERRORS {   \
   5.115 -    "Okay",                        \
   5.116 -    "Non-specific error",          \
   5.117 -    "Interface already exists",    \
   5.118 -    "Interface not found",         \
   5.119 -    "VBD already exists",          \
   5.120 -    "VBD not found",               \
   5.121 -    "Out of memory",               \
   5.122 -    "Extent not found for VBD",    \
   5.123 +#define BLKIF_BE_STATUS_ERRORS {    \
   5.124 +    "Okay",                         \
   5.125 +    "Non-specific error",           \
   5.126 +    "Interface already exists",     \
   5.127 +    "Interface not found",          \
   5.128 +    "Interface is still connected", \
   5.129 +    "VBD already exists",           \
   5.130 +    "VBD not found",                \
   5.131 +    "Out of memory",                \
   5.132 +    "Extent not found for VBD",     \
   5.133      "Could not map domain memory" }
   5.134  
   5.135  /*
   5.136   * CMSG_BLKIF_BE_CREATE:
   5.137   *  When the driver sends a successful response then the interface is fully
   5.138 - *  set up. The controller will send an UP notification to the front-end
   5.139 + *  created. The controller will send a DOWN notification to the front-end
   5.140   *  driver.
   5.141   */
   5.142  typedef struct { 
   5.143      /* IN */
   5.144      domid_t        domid;             /* Domain attached to new interface.   */
   5.145      unsigned int   blkif_handle;      /* Domain-specific interface handle.   */
   5.146 +    /* OUT */
   5.147 +    unsigned int   status;
   5.148 +} blkif_be_create_t; 
   5.149 +
   5.150 +/*
   5.151 + * CMSG_BLKIF_BE_DESTROY:
   5.152 + *  When the driver sends a successful response then the interface is fully
   5.153 + *  torn down. The controller will send a DESTROYED notification to the
   5.154 + *  front-end driver.
   5.155 + */
   5.156 +typedef struct { 
   5.157 +    /* IN */
   5.158 +    domid_t        domid;             /* Identify interface to be destroyed. */
   5.159 +    unsigned int   blkif_handle;      /* ...ditto...                         */
   5.160 +    /* OUT */
   5.161 +    unsigned int   status;
   5.162 +} blkif_be_destroy_t; 
   5.163 +
   5.164 +/*
   5.165 + * CMSG_BLKIF_BE_CONNECT:
   5.166 + *  When the driver sends a successful response then the interface is fully
   5.167 + *  connected. The controller will send a CONNECTED notification to the
   5.168 + *  front-end driver.
   5.169 + */
   5.170 +typedef struct { 
   5.171 +    /* IN */
   5.172 +    domid_t        domid;             /* Domain attached to new interface.   */
   5.173 +    unsigned int   blkif_handle;      /* Domain-specific interface handle.   */
   5.174      unsigned int   evtchn;            /* Event channel for notifications.    */
   5.175      unsigned long  shmem_frame;       /* Page cont. shared comms window.     */
   5.176      /* OUT */
   5.177      unsigned int   status;
   5.178 -} blkif_be_create_t; 
   5.179 +} blkif_be_connect_t; 
   5.180  
   5.181  /*
   5.182 - * CMSG_BLKIF_BE_DESTROY:
   5.183 + * CMSG_BLKIF_BE_DISCONNECT:
   5.184   *  When the driver sends a successful response then the interface is fully
   5.185 - *  torn down. The controller will send a DOWN notification to the front-end
   5.186 + *  disconnected. The controller will send a DOWN notification to the front-end
   5.187   *  driver.
   5.188   */
   5.189  typedef struct { 
   5.190      /* IN */
   5.191 -    domid_t        domid;             /* Identify interface to be destroyed. */
   5.192 -    unsigned int   blkif_handle;      /* ...ditto...                         */
   5.193 +    domid_t        domid;             /* Domain attached to new interface.   */
   5.194 +    unsigned int   blkif_handle;      /* Domain-specific interface handle.   */
   5.195      /* OUT */
   5.196      unsigned int   status;
   5.197 -} blkif_be_destroy_t; 
   5.198 +} blkif_be_disconnect_t; 
   5.199  
   5.200  /* CMSG_BLKIF_BE_VBD_CREATE */
   5.201  typedef struct { 
   5.202 @@ -264,7 +303,14 @@ typedef struct {
   5.203   *  will automatically send DOWN notifications.
   5.204   */
   5.205  typedef struct {
   5.206 +    /* IN */
   5.207      unsigned int status; /* BLKIF_DRIVER_STATUS_??? */
   5.208 +    /* OUT */
   5.209 +    /*
   5.210 +     * Tells driver how many interfaces it should expect to immediately
   5.211 +     * receive notifications about.
   5.212 +     */
   5.213 +    unsigned int nr_interfaces;
   5.214  } blkif_be_driver_status_changed_t;
   5.215  
   5.216  #endif /* __DOMAIN_CONTROLLER_H__ */
     6.1 --- a/tools/xend/lib/main.py	Wed Apr 28 14:08:16 2004 +0000
     6.2 +++ b/tools/xend/lib/main.py	Fri Apr 30 15:41:03 2004 +0000
     6.3 @@ -5,7 +5,7 @@
     6.4  ###########################################################
     6.5  
     6.6  import errno, re, os, pwd, select, signal, socket, struct, sys, time
     6.7 -import xend.console, xend.manager, xend.utils, Xc
     6.8 +import xend.blkif, xend.console, xend.manager, xend.utils, Xc
     6.9  
    6.10  
    6.11  # The following parameters could be placed in a configuration file.
    6.12 @@ -16,13 +16,35 @@ CONTROL_DIR  = '/var/run/xend'
    6.13  UNIX_SOCK    = 'management_sock' # relative to CONTROL_DIR
    6.14  
    6.15  
    6.16 +CMSG_CONSOLE  = 0
    6.17 +CMSG_BLKIF_BE = 1
    6.18 +CMSG_BLKIF_FE = 2
    6.19 +
    6.20 +
    6.21 +def port_from_dom(dom):
    6.22 +    global port_list
    6.23 +    for idx, port in port_list.items():
    6.24 +        if port.remote_dom == dom:
    6.25 +            return port
    6.26 +    return None
    6.27 +
    6.28 +
    6.29 +def send_management_response(response, addr):
    6.30 +    try:
    6.31 +        response = str(response)
    6.32 +        print "Mgmt_rsp[%s]: %s" % (addr, response)
    6.33 +        management_interface.sendto(response, addr)
    6.34 +    except socket.error, error:
    6.35 +        pass
    6.36 +
    6.37 +
    6.38  def daemon_loop():
    6.39      # Could we do this more nicely? The xend.manager functions need access
    6.40      # to this global state to do their work.
    6.41 -    global control_list, notifier
    6.42 +    global port_list, notifier, management_interface, mgmt_req_addr, dom0_port
    6.43  
    6.44 -    # List of all control interfaces, indexed by local event-channel port.
    6.45 -    control_list = {}
    6.46 +    # Lists of all interfaces, indexed by local event-channel port.
    6.47 +    port_list = {}
    6.48  
    6.49      xc = Xc.new()
    6.50  
    6.51 @@ -46,13 +68,10 @@ def daemon_loop():
    6.52  
    6.53      # The DOM0 control interface is not set up via the management interface.
    6.54      # Note that console messages don't come our way (actually, only driver
    6.55 -    # back-ends should use the DOM0 control interface) -- the console
    6.56 -    # structures are dummies.
    6.57 +    # back-ends should use the DOM0 control interface).
    6.58      dom0_port = xend.utils.port(0)
    6.59 -    xend.main.notifier.bind(dom0_port.local_port)
    6.60 -    xend.main.control_list[dom0_port.local_port] =          \
    6.61 -      (dom0_port, xend.utils.buffer(), xend.utils.buffer(), \
    6.62 -       xend.console.interface(0, dom0_port.local_port))
    6.63 +    notifier.bind(dom0_port.local_port)
    6.64 +    port_list[dom0_port.local_port] = dom0_port
    6.65  
    6.66      ##
    6.67      ## MAIN LOOP
    6.68 @@ -68,10 +87,10 @@ def daemon_loop():
    6.69          waitset = select.poll()
    6.70          waitset.register(management_interface, select.POLLIN)
    6.71          waitset.register(notifier, select.POLLIN)
    6.72 -        for idx, (port, rbuf, wbuf, con_if) in control_list.items():
    6.73 +        for idx, con_if in xend.console.interface.list_by_fd.items():
    6.74              if not con_if.closed():
    6.75                  pflags = select.POLLIN
    6.76 -                if not rbuf.empty() and con_if.connected():
    6.77 +                if not con_if.rbuf.empty() and con_if.connected():
    6.78                      pflags = select.POLLIN | select.POLLOUT
    6.79                  waitset.register(con_if.sock.fileno(), pflags)
    6.80  
    6.81 @@ -82,16 +101,16 @@ def daemon_loop():
    6.82          # These should consist of executable Python statements that call
    6.83          # well-known management functions (e.g., new_control_interface(dom=9)).
    6.84          try:
    6.85 -            data, addr = management_interface.recvfrom(2048)
    6.86 +            data, mgmt_req_addr = management_interface.recvfrom(2048)
    6.87          except socket.error, error:
    6.88              if error[0] != errno.EAGAIN:
    6.89                  raise
    6.90          else:
    6.91 -            if addr:
    6.92 +            if mgmt_req_addr:
    6.93                  # Evaluate the request in an exception-trapping sandbox.
    6.94                  try:
    6.95 -                    print "Mgmt_req[%s]: %s" % (addr, data)
    6.96 -                    response = str(eval('xend.manager.'+data))
    6.97 +                    print "Mgmt_req[%s]: %s" % (mgmt_req_addr, data)
    6.98 +                    response = eval('xend.manager.'+data)
    6.99  
   6.100                  except:
   6.101                      # Catch all exceptions and turn into an error response:
   6.102 @@ -107,69 +126,20 @@ def daemon_loop():
   6.103                      response = str(response)
   6.104  
   6.105                  # Try to send a response to the requester.
   6.106 -                try:
   6.107 -                    print "Mgmt_rsp[%s]: %s" % (addr, response)
   6.108 -                    management_interface.sendto(response, addr)
   6.109 -                except socket.error, error:
   6.110 -                    pass
   6.111 +                if response:
   6.112 +                    send_management_response(response, mgmt_req_addr)
   6.113                  
   6.114          # Do work for every console interface that hit in the poll set.
   6.115          for (fd, events) in fdset:
   6.116 -            if not xend.console.interface.interface_list.has_key(fd):
   6.117 -                continue
   6.118 -            con_if = xend.console.interface.interface_list[fd]
   6.119 -
   6.120 -            # If the interface is listening, check for pending connections.
   6.121 -            if con_if.listening():
   6.122 -                con_if.connect()
   6.123 -
   6.124 -            # All done if the interface is not connected.
   6.125 -            if not con_if.connected():
   6.126 -                continue
   6.127 -            (port, rbuf, wbuf, con_if) = control_list[con_if.key]
   6.128 -
   6.129 -            # Send as much pending data as possible via the socket.
   6.130 -            while not rbuf.empty():
   6.131 -                try:
   6.132 -                    bytes = con_if.sock.send(rbuf.peek())
   6.133 -                    if bytes > 0:
   6.134 -                        rbuf.discard(bytes)
   6.135 -                except socket.error, error:
   6.136 -                    pass
   6.137 -
   6.138 -            # Read as much data as is available. Don't worry about
   6.139 -            # overflowing our buffer: it's more important to read the
   6.140 -            # incoming data stream and detect errors or closure of the
   6.141 -            # remote end in a timely manner.
   6.142 -            try:
   6.143 -                while 1:
   6.144 -                    data = con_if.sock.recv(2048)
   6.145 -                    # Return of zero means the remote end has disconnected.
   6.146 -                    # We therefore return the console interface to listening.
   6.147 -                    if not data:
   6.148 -                        con_if.listen()
   6.149 -                        break
   6.150 -                    wbuf.write(data)
   6.151 -            except socket.error, error:
   6.152 -                # Assume that most errors mean that the connection is dead.
   6.153 -                # In such cases we return the interface to 'listening' state.
   6.154 -                if error[0] != errno.EAGAIN:
   6.155 -                    print "Better return to listening"
   6.156 -                    con_if.listen()
   6.157 -                    print "New status: " + str(con_if.status)
   6.158 -
   6.159 -            # We may now have pending data to send via the relevant
   6.160 -            # inter-domain control interface. If so then we send all we can
   6.161 -            # and notify the remote end.
   6.162 -            work_done = False
   6.163 -            while not wbuf.empty() and port.space_to_write_request():
   6.164 -                msg = xend.utils.message(0, 0, 0)
   6.165 -                msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
   6.166 -                port.write_request(msg)
   6.167 -                work_done = True
   6.168 -            if work_done:
   6.169 -                port.notify()
   6.170 -
   6.171 +            if xend.console.interface.list_by_fd.has_key(fd):
   6.172 +                con_if = xend.console.interface.list_by_fd[fd]
   6.173 +                con_if.socket_work()
   6.174 +                # We may now have pending data to send via the control
   6.175 +                # interface. If so then send all we can and notify the remote.
   6.176 +                port = port_list[con_if.key]
   6.177 +                if con_if.ctrlif_transmit_work(port):
   6.178 +                    port.notify()
   6.179 +                    
   6.180          # Process control-interface notifications from other guest OSes.
   6.181          while 1:            
   6.182              # Grab a notification, if there is one.
   6.183 @@ -178,42 +148,69 @@ def daemon_loop():
   6.184                  break
   6.185              (idx, type) = notification
   6.186  
   6.187 -            if not control_list.has_key(idx):
   6.188 +            if not port_list.has_key(idx):
   6.189                  continue
   6.190  
   6.191 -            (port, rbuf, wbuf, con_if) = control_list[idx]
   6.192 +            port = port_list[idx]
   6.193              work_done = False
   6.194  
   6.195 +            con_if = False
   6.196 +            if xend.console.interface.list.has_key(idx):
   6.197 +                con_if = xend.console.interface.list[idx]
   6.198 +
   6.199 +            blk_if = False
   6.200 +            if xend.blkif.interface.list.has_key(idx):
   6.201 +                blk_if = xend.blkif.interface.list[idx]
   6.202 +
   6.203              # If we pick up a disconnect notification then we do any necessary
   6.204              # cleanup.
   6.205              if type == notifier.EXCEPTION:
   6.206                  ret = xc.evtchn_status(idx)
   6.207                  if ret['status'] == 'unbound':
   6.208                      notifier.unbind(idx)
   6.209 -                    con_if.close()
   6.210 -                    del control_list[idx], port, rbuf, wbuf, con_if
   6.211 +                    del port_list[idx], port
   6.212 +                    if con_if:
   6.213 +                        con_if.destroy()
   6.214 +                        del con_if
   6.215 +                    if blk_if:
   6.216 +                        blk_if.destroy()
   6.217 +                        del blk_if
   6.218                      continue
   6.219  
   6.220 -            # Read incoming requests. Currently assume that request
   6.221 -            # message always containb console data.
   6.222 +            # Process incoming requests.
   6.223              while port.request_to_read():
   6.224                  msg = port.read_request()
   6.225 -                rbuf.write(msg.get_payload())
   6.226 -                port.write_response(msg)
   6.227                  work_done = True
   6.228 +                type = (msg.get_header())['type']
   6.229 +                if type == CMSG_CONSOLE and con_if:
   6.230 +                    con_if.ctrlif_rx_req(port, msg)
   6.231 +                elif type == CMSG_BLKIF_FE and blk_if:
   6.232 +                    blk_if.ctrlif_rx_req(port, msg)
   6.233 +                elif type == CMSG_BLKIF_BE and port == dom0_port:
   6.234 +                    xend.blkif.backend_rx_req(port, msg)
   6.235 +                else:
   6.236 +                    port.write_response(msg)
   6.237  
   6.238 -            # Incoming responses are currently thrown on the floor.
   6.239 +            # Process incoming responses.
   6.240              while port.response_to_read():
   6.241                  msg = port.read_response()
   6.242                  work_done = True
   6.243 +                type = (msg.get_header())['type']
   6.244 +                if type == CMSG_BLKIF_BE and port == dom0_port:
   6.245 +                    xend.blkif.backend_rx_rsp(port, msg)
   6.246  
   6.247 -            # Send as much pending console data as there is room for.
   6.248 -            while not wbuf.empty() and port.space_to_write_request():
   6.249 -                msg = xend.utils.message(0, 0, 0)
   6.250 -                msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
   6.251 -                port.write_request(msg)
   6.252 +            # Send console data.
   6.253 +            if con_if and con_if.ctrlif_transmit_work(port):
   6.254                  work_done = True
   6.255  
   6.256 +            # Send blkif messages.
   6.257 +            if blk_if and blk_if.ctrlif_transmit_work(port):
   6.258 +                work_done = True
   6.259 +
   6.260 +            # Back-end block-device work.
   6.261 +            if port == dom0_port and xend.blkif.backend_do_work(port):
   6.262 +                work_done = True
   6.263 +                
   6.264              # Finally, notify the remote end of any work that we did.
   6.265              if work_done:
   6.266                  port.notify()
     7.1 --- a/tools/xend/lib/manager.py	Wed Apr 28 14:08:16 2004 +0000
     7.2 +++ b/tools/xend/lib/manager.py	Fri Apr 30 15:41:03 2004 +0000
     7.3 @@ -4,13 +4,13 @@
     7.4  ## Copyright (c) 2004, K A Fraser (University of Cambridge)
     7.5  #############################################################
     7.6  
     7.7 -import xend.console, xend.main, xend.utils
     7.8 +import xend.blkif, xend.console, xend.main, xend.utils
     7.9  
    7.10  
    7.11  ##
    7.12  ## new_control_interface:
    7.13 -##  Create a new control interface with the specified domain 'dom'.
    7.14 -##  The console port may also be specified; otehrwise a suitable port is
    7.15 +##  Create a new control interface with the specified domain @dom.
    7.16 +##  The console port may also be specified; otherwise a suitable port is
    7.17  ##  automatically allocated.
    7.18  ##
    7.19  def new_control_interface(dom, console_port=-1):
    7.20 @@ -26,9 +26,8 @@ def new_control_interface(dom, console_p
    7.21      con_if = xend.console.interface(console_port, port.local_port)
    7.22      con_if.listen()
    7.23  
    7.24 -    # Add control state to the master list.
    7.25 -    xend.main.control_list[port.local_port] = \
    7.26 -      (port, xend.utils.buffer(), xend.utils.buffer(), con_if)
    7.27 +    # Update the master port list.
    7.28 +    xend.main.port_list[port.local_port] = port
    7.29  
    7.30      # Construct the successful response to be returned to the requester.
    7.31      response = { 'success': True }
    7.32 @@ -36,3 +35,81 @@ def new_control_interface(dom, console_p
    7.33      response['remote_port']  = port.remote_port
    7.34      response['console_port'] = console_port
    7.35      return response
    7.36 +
    7.37 +
    7.38 +##
    7.39 +## new_block_interface:
    7.40 +##  Create a new block interface for the specified domain @dom.
    7.41 +##
    7.42 +def new_block_interface(dom, handle=-1):
    7.43 +    # By default we create an interface with handle zero.
    7.44 +    if handle < 0:
    7.45 +        handle = 0
    7.46 +
    7.47 +    # We only support one interface per domain, which must have handle zero.
    7.48 +    if handle != 0:
    7.49 +        response = { 'success': False }
    7.50 +        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
    7.51 +                                 'is supported)' % handle
    7.52 +        return response
    7.53 +
    7.54 +    # Find local event-channel port associated with the specified domain.
    7.55 +    port = xend.main.port_from_dom(dom)
    7.56 +    if not port:
    7.57 +        response = { 'success': False }
    7.58 +        response['error_type'] = 'Unknown domain %d' % dom
    7.59 +        return response
    7.60 +
    7.61 +    # The interface must not already exist.
    7.62 +    if xend.blkif.interface.list.has_key(port.local_port):
    7.63 +        response = { 'success': False }
    7.64 +        response['error_type'] = 'Interface (dom=%d,handle=%d) already ' + \
    7.65 +                                 'exists' % (dom, handle)
    7.66 +        return response
    7.67 +
    7.68 +    # Create the new interface. Initially no virtual devices are attached.
    7.69 +    xend.blkif.interface(dom, port.local_port)
    7.70 +
    7.71 +    # Response is deferred until back-end driver sends acknowledgement.
    7.72 +    return None
    7.73 +
    7.74 +
    7.75 +##
    7.76 +## new_block_device:
    7.77 +##  Attach a new virtual block device to the specified block interface
    7.78 +##  (@dom, @handle). The new device is identified by @vdev, and maps to
    7.79 +##  the real block extent (@pdev, @start_sect, @nr_sect). If @readonly then
    7.80 +##  write requests to @vdev will be rejected.
    7.81 +##
    7.82 +def new_block_device(dom, handle, vdev, pdev, start_sect, nr_sect, readonly):
    7.83 +    # We only support one interface per domain, which must have handle zero.
    7.84 +    if handle != 0:
    7.85 +        response = { 'success': False }
    7.86 +        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
    7.87 +                                 'is supported)' % handle
    7.88 +        return response
    7.89 +
    7.90 +    # Find local event-channel port associated with the specified domain.
    7.91 +    port = xend.main.port_from_dom(dom)
    7.92 +    if not port:
    7.93 +        response = { 'success': False }
    7.94 +        response['error_type'] = 'Unknown domain %d' % dom
    7.95 +        return response
    7.96 +        
    7.97 +    # The interface must exist.
    7.98 +    if not xend.blkif.interface.list.has_key(port.local_port):
    7.99 +        response = { 'success': False }
   7.100 +        response['error_type'] = 'Interface (dom=%d,handle=%d) does not ' + \
   7.101 +                                 'exists' % (dom, handle)
   7.102 +        return response
   7.103 +
   7.104 +    # The virtual device must not yet exist.
   7.105 +    blkif = xend.blkif.interface.list[port.local_port]
   7.106 +    if not blkif.attach_device(vdev, pdev, start_sect, nr_sect, readonly):
   7.107 +        response = { 'success': False }
   7.108 +        response['error_type'] = 'Vdevice (dom=%d,handle=%d,vdevice=%d) ' + \
   7.109 +                                 'already exists' % (dom, handle, vdev)
   7.110 +        return response
   7.111 +
   7.112 +    # Response is deferred until back-end driver sends acknowledgement.
   7.113 +    return None
     8.1 --- a/xen/common/event_channel.c	Wed Apr 28 14:08:16 2004 +0000
     8.2 +++ b/xen/common/event_channel.c	Fri Apr 30 15:41:03 2004 +0000
     8.3 @@ -109,15 +109,18 @@ static long evtchn_bind_interdomain(evtc
     8.4          goto out;
     8.5      }
     8.6  
     8.7 +    /* 'Allocate' port1 before searching for a free port2. */
     8.8 +    p1->event_channel[port1].state = ECS_INTERDOMAIN;
     8.9 +
    8.10      if ( (port2 = get_free_port(p2)) < 0 )
    8.11      {
    8.12 +        p1->event_channel[port1].state = ECS_FREE;
    8.13          rc = port2;
    8.14          goto out;
    8.15      }
    8.16  
    8.17      p1->event_channel[port1].u.remote.dom  = p2;
    8.18      p1->event_channel[port1].u.remote.port = (u16)port2;
    8.19 -    p1->event_channel[port1].state         = ECS_INTERDOMAIN;
    8.20  
    8.21      p2->event_channel[port2].u.remote.dom  = p1;
    8.22      p2->event_channel[port2].u.remote.port = (u16)port1;
     9.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/common.h	Wed Apr 28 14:08:16 2004 +0000
     9.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/common.h	Fri Apr 30 15:41:03 2004 +0000
     9.3 @@ -41,6 +41,12 @@ typedef struct blkif_st {
     9.4      rb_root_t        vbd_rb;        /* Mapping from 16-bit vdevices to VBDs. */
     9.5      spinlock_t       vbd_lock;      /* Protects VBD mapping. */
     9.6      /* Private fields. */
     9.7 +    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
     9.8 +    /*
     9.9 +     * DISCONNECT response is deferred until pending requests are ack'ed.
    9.10 +     * We therefore need to store the id from the original request.
    9.11 +     */
    9.12 +    u8               disconnect_rspid;
    9.13      struct blkif_st *hash_next;
    9.14      struct list_head blkdev_list;
    9.15      spinlock_t       blk_ring_lock;
    9.16 @@ -49,13 +55,15 @@ typedef struct blkif_st {
    9.17  
    9.18  void blkif_create(blkif_be_create_t *create);
    9.19  void blkif_destroy(blkif_be_destroy_t *destroy);
    9.20 -void __blkif_destroy(blkif_t *blkif);
    9.21 +void blkif_connect(blkif_be_connect_t *connect);
    9.22 +int  blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id);
    9.23 +void __blkif_disconnect_complete(blkif_t *blkif);
    9.24  blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
    9.25  #define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
    9.26  #define blkif_put(_b)                             \
    9.27      do {                                          \
    9.28          if ( atomic_dec_and_test(&(_b)->refcnt) ) \
    9.29 -            __blkif_destroy(_b);                  \
    9.30 +            __blkif_disconnect_complete(_b);      \
    9.31      } while (0)
    9.32  
    9.33  /* An entry in a list of xen_extents. */
    10.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/control.c	Wed Apr 28 14:08:16 2004 +0000
    10.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/control.c	Fri Apr 30 15:41:03 2004 +0000
    10.3 @@ -10,6 +10,8 @@
    10.4  
    10.5  static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
    10.6  {
    10.7 +    DPRINTK("Received blkif backend message, subtype=%d\n", msg->subtype);
    10.8 +    
    10.9      switch ( msg->subtype )
   10.10      {
   10.11      case CMSG_BLKIF_BE_CREATE:
   10.12 @@ -22,6 +24,17 @@ static void blkif_ctrlif_rx(ctrl_msg_t *
   10.13              goto parse_error;
   10.14          blkif_destroy((blkif_be_destroy_t *)&msg->msg[0]);
   10.15          break;        
   10.16 +    case CMSG_BLKIF_BE_CONNECT:
   10.17 +        if ( msg->length != sizeof(blkif_be_connect_t) )
   10.18 +            goto parse_error;
   10.19 +        blkif_connect((blkif_be_connect_t *)&msg->msg[0]);
   10.20 +        break;        
   10.21 +    case CMSG_BLKIF_BE_DISCONNECT:
   10.22 +        if ( msg->length != sizeof(blkif_be_disconnect_t) )
   10.23 +            goto parse_error;
   10.24 +        if ( !blkif_disconnect((blkif_be_disconnect_t *)&msg->msg[0],msg->id) )
   10.25 +            return; /* Sending the response is deferred until later. */
   10.26 +        break;        
   10.27      case CMSG_BLKIF_BE_VBD_CREATE:
   10.28          if ( msg->length != sizeof(blkif_be_vbd_create_t) )
   10.29              goto parse_error;
   10.30 @@ -50,6 +63,8 @@ static void blkif_ctrlif_rx(ctrl_msg_t *
   10.31      return;
   10.32  
   10.33   parse_error:
   10.34 +    DPRINTK("Parse error while reading message subtype %d, len %d\n",
   10.35 +            msg->subtype, msg->length);
   10.36      msg->length = 0;
   10.37      ctrl_if_send_response(msg);
   10.38  }
    11.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/interface.c	Wed Apr 28 14:08:16 2004 +0000
    11.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/interface.c	Fri Apr 30 15:41:03 2004 +0000
    11.3 @@ -14,60 +14,153 @@
    11.4  
    11.5  static kmem_cache_t *blkif_cachep;
    11.6  static blkif_t      *blkif_hash[BLKIF_HASHSZ];
    11.7 -static spinlock_t    blkif_hash_lock;
    11.8  
    11.9  blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
   11.10  {
   11.11 -    blkif_t      *blkif;
   11.12 -    unsigned long flags;
   11.13 -    
   11.14 -    spin_lock_irqsave(&blkif_hash_lock, flags);
   11.15 -    blkif = blkif_hash[BLKIF_HASH(domid, handle)];
   11.16 -    while ( blkif != NULL )
   11.17 -    {
   11.18 -        if ( (blkif->domid == domid) && (blkif->handle == handle) )
   11.19 -        {
   11.20 -            blkif_get(blkif);
   11.21 -            break;
   11.22 -        }
   11.23 +    blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
   11.24 +    while ( (blkif != NULL) && 
   11.25 +            ((blkif->domid != domid) || (blkif->handle != handle)) )
   11.26          blkif = blkif->hash_next;
   11.27 -    }
   11.28 -    spin_unlock_irqrestore(&blkif_hash_lock, flags);
   11.29 -
   11.30      return blkif;
   11.31  }
   11.32  
   11.33 -void __blkif_destroy(blkif_t *blkif)
   11.34 +void __blkif_disconnect_complete(blkif_t *blkif)
   11.35  {
   11.36 -    free_irq(blkif->irq, NULL);
   11.37 +    ctrl_msg_t            cmsg;
   11.38 +    blkif_be_disconnect_t disc;
   11.39 +
   11.40 +    /*
   11.41 +     * These can't be done in __blkif_disconnect() because at that point there
   11.42 +     * may be outstanding requests at the disc whose asynchronous responses
   11.43 +     * must still be notified to the remote driver.
   11.44 +     */
   11.45      unbind_evtchn_from_irq(blkif->evtchn);
   11.46      vfree(blkif->blk_ring_base);
   11.47 -    destroy_all_vbds(blkif);
   11.48 -    kmem_cache_free(blkif_cachep, blkif);    
   11.49 +
   11.50 +    /* Construct the deferred response message. */
   11.51 +    cmsg.type         = CMSG_BLKIF_BE;
   11.52 +    cmsg.subtype      = CMSG_BLKIF_BE_DISCONNECT;
   11.53 +    cmsg.id           = blkif->disconnect_rspid;
   11.54 +    cmsg.length       = sizeof(blkif_be_disconnect_t);
   11.55 +    disc.domid        = blkif->domid;
   11.56 +    disc.blkif_handle = blkif->handle;
   11.57 +    disc.status       = BLKIF_BE_STATUS_OKAY;
   11.58 +    memcpy(cmsg.msg, &disc, sizeof(disc));
   11.59 +
   11.60 +    /*
   11.61 +     * Make sure message is constructed /before/ status change, because
   11.62 +     * after the status change the 'blkif' structure could be deallocated at
   11.63 +     * any time. Also make sure we send the response /after/ status change,
   11.64 +     * as otherwise a subsequent CONNECT request could spuriously fail if
   11.65 +     * another CPU doesn't see the status change yet.
   11.66 +     */
   11.67 +    mb();
   11.68 +    if ( blkif->status != DISCONNECTING )
   11.69 +        BUG();
   11.70 +    blkif->status = DISCONNECTED;
   11.71 +    mb();
   11.72 +
   11.73 +    /* Send the successful response. */
   11.74 +    ctrl_if_send_response(&cmsg);
   11.75  }
   11.76  
   11.77  void blkif_create(blkif_be_create_t *create)
   11.78  {
   11.79      domid_t       domid  = create->domid;
   11.80      unsigned int  handle = create->blkif_handle;
   11.81 -    unsigned int  evtchn = create->evtchn;
   11.82 -    unsigned long shmem_frame = create->shmem_frame;
   11.83 -    unsigned long flags;
   11.84      blkif_t     **pblkif, *blkif;
   11.85 -    struct vm_struct *vma;
   11.86 -    pgprot_t      prot;
   11.87 -    int           error;
   11.88  
   11.89 -    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
   11.90 +    if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_ATOMIC)) == NULL )
   11.91      {
   11.92 +        DPRINTK("Could not create blkif: out of memory\n");
   11.93          create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   11.94          return;
   11.95      }
   11.96  
   11.97 -    if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL )
   11.98 +    memset(blkif, 0, sizeof(*blkif));
   11.99 +    blkif->domid  = domid;
  11.100 +    blkif->handle = handle;
  11.101 +    blkif->status = DISCONNECTED;
  11.102 +    spin_lock_init(&blkif->vbd_lock);
  11.103 +    spin_lock_init(&blkif->blk_ring_lock);
  11.104 +    atomic_set(&blkif->refcnt, 0);
  11.105 +
  11.106 +    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
  11.107 +    while ( *pblkif != NULL )
  11.108 +    {
  11.109 +        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
  11.110 +        {
  11.111 +            DPRINTK("Could not create blkif: already exists\n");
  11.112 +            create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
  11.113 +            kmem_cache_free(blkif_cachep, blkif);
  11.114 +            return;
  11.115 +        }
  11.116 +        pblkif = &(*pblkif)->hash_next;
  11.117 +    }
  11.118 +
  11.119 +    blkif->hash_next = *pblkif;
  11.120 +    *pblkif = blkif;
  11.121 +
  11.122 +    DPRINTK("Successfully created blkif\n");
  11.123 +    create->status = BLKIF_BE_STATUS_OKAY;
  11.124 +}
  11.125 +
  11.126 +void blkif_destroy(blkif_be_destroy_t *destroy)
  11.127 +{
  11.128 +    domid_t       domid  = destroy->domid;
  11.129 +    unsigned int  handle = destroy->blkif_handle;
  11.130 +    blkif_t     **pblkif, *blkif;
  11.131 +
  11.132 +    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
  11.133 +    while ( (blkif = *pblkif) != NULL )
  11.134      {
  11.135 -        create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
  11.136 -        goto fail1;
  11.137 +        if ( (blkif->domid == domid) && (blkif->handle == handle) )
  11.138 +        {
  11.139 +            if ( blkif->status != DISCONNECTED )
  11.140 +                goto still_connected;
  11.141 +            goto destroy;
  11.142 +        }
  11.143 +        pblkif = &blkif->hash_next;
  11.144 +    }
  11.145 +
  11.146 +    destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
  11.147 +    return;
  11.148 +
  11.149 + still_connected:
  11.150 +    destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
  11.151 +    return;
  11.152 +
  11.153 + destroy:
  11.154 +    *pblkif = blkif->hash_next;
  11.155 +    destroy_all_vbds(blkif);
  11.156 +    kmem_cache_free(blkif_cachep, blkif);
  11.157 +    destroy->status = BLKIF_BE_STATUS_OKAY;
  11.158 +}
  11.159 +
  11.160 +void blkif_connect(blkif_be_connect_t *connect)
  11.161 +{
  11.162 +    domid_t       domid  = connect->domid;
  11.163 +    unsigned int  handle = connect->blkif_handle;
  11.164 +    unsigned int  evtchn = connect->evtchn;
  11.165 +    unsigned long shmem_frame = connect->shmem_frame;
  11.166 +    struct vm_struct *vma;
  11.167 +    pgprot_t      prot;
  11.168 +    int           error;
  11.169 +    blkif_t      *blkif;
  11.170 +
  11.171 +    blkif = blkif_find_by_handle(domid, handle);
  11.172 +    if ( unlikely(blkif == NULL) )
  11.173 +    {
  11.174 +        DPRINTK("blkif_connect attempted for non-existent blkif (%llu,%u)\n", 
  11.175 +                connect->domid, connect->blkif_handle); 
  11.176 +        connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
  11.177 +        return;
  11.178 +    }
  11.179 +
  11.180 +    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
  11.181 +    {
  11.182 +        connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
  11.183 +        return;
  11.184      }
  11.185  
  11.186      prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
  11.187 @@ -77,81 +170,60 @@ void blkif_create(blkif_be_create_t *cre
  11.188      if ( error != 0 )
  11.189      {
  11.190          if ( error == -ENOMEM )
  11.191 -            create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
  11.192 +            connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
  11.193          else if ( error == -EFAULT )
  11.194 -            create->status = BLKIF_BE_STATUS_MAPPING_ERROR;
  11.195 +            connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
  11.196          else
  11.197 -            create->status = BLKIF_BE_STATUS_ERROR;
  11.198 -        goto fail2;
  11.199 +            connect->status = BLKIF_BE_STATUS_ERROR;
  11.200 +        vfree(vma->addr);
  11.201 +        return;
  11.202      }
  11.203  
  11.204 -    memset(blkif, 0, sizeof(*blkif));
  11.205 -    blkif->domid         = domid;
  11.206 -    blkif->handle        = handle;
  11.207 +    if ( blkif->status != DISCONNECTED )
  11.208 +    {
  11.209 +        connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
  11.210 +        vfree(vma->addr);
  11.211 +        return;
  11.212 +    }
  11.213 +
  11.214      blkif->evtchn        = evtchn;
  11.215      blkif->irq           = bind_evtchn_to_irq(evtchn);
  11.216      blkif->shmem_frame   = shmem_frame;
  11.217      blkif->blk_ring_base = (blkif_ring_t *)vma->addr;
  11.218 -    spin_lock_init(&blkif->vbd_lock);
  11.219 -    spin_lock_init(&blkif->blk_ring_lock);
  11.220 -
  11.221 -    spin_lock_irqsave(&blkif_hash_lock, flags);
  11.222 -
  11.223 -    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
  11.224 -    while ( *pblkif == NULL )
  11.225 -    {
  11.226 -        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
  11.227 -        {
  11.228 -            spin_unlock_irqrestore(&blkif_hash_lock, flags);
  11.229 -            create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
  11.230 -            goto fail3;
  11.231 -        }
  11.232 -        pblkif = &(*pblkif)->hash_next;
  11.233 -    }
  11.234 -
  11.235 -    atomic_set(&blkif->refcnt, 1);
  11.236 -    blkif->hash_next = *pblkif;
  11.237 -    *pblkif = blkif;
  11.238 -
  11.239 -    spin_unlock_irqrestore(&blkif_hash_lock, flags);
  11.240 +    blkif->status        = CONNECTED;
  11.241 +    blkif_get(blkif);
  11.242  
  11.243      request_irq(blkif->irq, blkif_be_int, 0, "blkif-backend", blkif);
  11.244  
  11.245 -    create->status = BLKIF_BE_STATUS_OKAY;
  11.246 -    return;
  11.247 -
  11.248 - fail3: unbind_evtchn_from_irq(evtchn);
  11.249 - fail2: kmem_cache_free(blkif_cachep, blkif);
  11.250 - fail1: vfree(vma->addr);
  11.251 +    connect->status = BLKIF_BE_STATUS_OKAY;
  11.252  }
  11.253  
  11.254 -void blkif_destroy(blkif_be_destroy_t *destroy)
  11.255 +int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
  11.256  {
  11.257 -    domid_t       domid  = destroy->domid;
  11.258 -    unsigned int  handle = destroy->blkif_handle;
  11.259 -    unsigned long flags;
  11.260 -    blkif_t     **pblkif, *blkif;
  11.261 -
  11.262 -    spin_lock_irqsave(&blkif_hash_lock, flags);
  11.263 +    domid_t       domid  = disconnect->domid;
  11.264 +    unsigned int  handle = disconnect->blkif_handle;
  11.265 +    blkif_t      *blkif;
  11.266  
  11.267 -    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
  11.268 -    while ( (blkif = *pblkif) == NULL )
  11.269 +    blkif = blkif_find_by_handle(domid, handle);
  11.270 +    if ( unlikely(blkif == NULL) )
  11.271      {
  11.272 -        if ( (blkif->domid == domid) && (blkif->handle == handle) )
  11.273 -        {
  11.274 -            *pblkif = blkif->hash_next;
  11.275 -            spin_unlock_irqrestore(&blkif_hash_lock, flags);
  11.276 -            blkif_deschedule(blkif);
  11.277 -            blkif_put(blkif);
  11.278 -            destroy->status = BLKIF_BE_STATUS_OKAY;
  11.279 -            return;
  11.280 -        }
  11.281 -        pblkif = &blkif->hash_next;
  11.282 +        DPRINTK("blkif_disconnect attempted for non-existent blkif"
  11.283 +                " (%llu,%u)\n", disconnect->domid, disconnect->blkif_handle); 
  11.284 +        disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
  11.285 +        return 1; /* Caller will send response error message. */
  11.286      }
  11.287  
  11.288 -    spin_unlock_irqrestore(&blkif_hash_lock, flags);
  11.289 +    if ( blkif->status == CONNECTED )
  11.290 +    {
  11.291 +        blkif->status = DISCONNECTING;
  11.292 +        blkif->disconnect_rspid = rsp_id;
  11.293 +        wmb(); /* Let other CPUs see the status change. */
  11.294 +        free_irq(blkif->irq, NULL);
  11.295 +        blkif_deschedule(blkif);
  11.296 +        blkif_put(blkif);
  11.297 +    }
  11.298  
  11.299 -    destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
  11.300 +    return 0; /* Caller should not send response message. */
  11.301  }
  11.302  
  11.303  void __init blkif_interface_init(void)
  11.304 @@ -159,5 +231,4 @@ void __init blkif_interface_init(void)
  11.305      blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
  11.306                                       0, 0, NULL, NULL);
  11.307      memset(blkif_hash, 0, sizeof(blkif_hash));
  11.308 -    spin_lock_init(&blkif_hash_lock);
  11.309  }
    12.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c	Wed Apr 28 14:08:16 2004 +0000
    12.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c	Fri Apr 30 15:41:03 2004 +0000
    12.3 @@ -33,8 +33,8 @@ static struct vm_struct *mmap_vma;
    12.4      (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
    12.5  #define MMAP_VADDR(_req,_seg)            \
    12.6      ((unsigned long)mmap_vma->addr +     \
    12.7 -     ((_req) * MMAP_PAGES_PER_REQUEST) + \
    12.8 -     ((_seg) * MMAP_PAGES_PER_SEGMENT))
    12.9 +     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
   12.10 +     ((_seg) * MMAP_PAGES_PER_SEGMENT * PAGE_SIZE))
   12.11  
   12.12  /*
   12.13   * Each outstanding request that we've passed to the lower device layers has a 
   12.14 @@ -96,7 +96,7 @@ static void add_to_blkdev_list_tail(blki
   12.15      unsigned long flags;
   12.16      if ( __on_blkdev_list(blkif) ) return;
   12.17      spin_lock_irqsave(&io_schedule_list_lock, flags);
   12.18 -    if ( !__on_blkdev_list(blkif) )
   12.19 +    if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
   12.20      {
   12.21          list_add_tail(&blkif->blkdev_list, &io_schedule_list);
   12.22          blkif_get(blkif);
   12.23 @@ -168,7 +168,8 @@ static void end_block_io_op(struct buffe
   12.24      if ( atomic_dec_and_test(&pending_req->pendcnt) )
   12.25      {
   12.26          int pending_idx = pending_req - pending_reqs;
   12.27 -        vmfree_area_pages(MMAP_VADDR(pending_idx, 0), MMAP_PAGES_PER_REQUEST);
   12.28 +        vmfree_area_pages(MMAP_VADDR(pending_idx, 0), 
   12.29 +                          MMAP_PAGES_PER_REQUEST * PAGE_SIZE);
   12.30          make_response(pending_req->blkif, pending_req->id,
   12.31                        pending_req->operation, pending_req->status);
   12.32          blkif_put(pending_req->blkif);
   12.33 @@ -260,10 +261,11 @@ static void dispatch_probe(blkif_t *blki
   12.34      {
   12.35          if ( (req->buffer_and_sects[i] & ~PAGE_MASK) != (PAGE_SIZE / 512) )
   12.36              goto bad_descriptor;
   12.37 -        if ( direct_remap_area_pages(&init_mm, 
   12.38 +        rc = direct_remap_area_pages(&init_mm, 
   12.39                                       MMAP_VADDR(pending_idx, i),
   12.40                                       req->buffer_and_sects[i] & PAGE_MASK, 
   12.41 -                                     PAGE_SIZE, prot, blkif->domid) != 0 )
   12.42 +                                     PAGE_SIZE, prot, blkif->domid);
   12.43 +        if ( rc != 0 )
   12.44              goto bad_descriptor;
   12.45      }
   12.46  
   12.47 @@ -271,12 +273,13 @@ static void dispatch_probe(blkif_t *blki
   12.48                     (req->nr_segments * PAGE_SIZE) / sizeof(vdisk_t));
   12.49  
   12.50      vmfree_area_pages(MMAP_VADDR(pending_idx, 0), 
   12.51 -                      MMAP_PAGES_PER_REQUEST);
   12.52 +                      MMAP_PAGES_PER_REQUEST * PAGE_SIZE);
   12.53      make_response(blkif, req->id, req->operation, rc);
   12.54      return;
   12.55  
   12.56   bad_descriptor:
   12.57 -    vmfree_area_pages(MMAP_VADDR(pending_idx, 0), MMAP_PAGES_PER_REQUEST);
   12.58 +    vmfree_area_pages(MMAP_VADDR(pending_idx, 0), 
   12.59 +                      MMAP_PAGES_PER_REQUEST * PAGE_SIZE);
   12.60      make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
   12.61  }
   12.62  
   12.63 @@ -284,7 +287,7 @@ static void dispatch_rw_block_io(blkif_t
   12.64  {
   12.65      extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); 
   12.66      struct buffer_head *bh;
   12.67 -    int operation = (req->operation == XEN_BLOCK_WRITE) ? WRITE : READ;
   12.68 +    int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
   12.69      unsigned short nr_sects;
   12.70      unsigned long buffer;
   12.71      int i, tot_sects, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
   12.72 @@ -358,14 +361,15 @@ static void dispatch_rw_block_io(blkif_t
   12.73          unsigned long sz = ((phys_seg[i].buffer & ~PAGE_MASK) + 
   12.74                              (phys_seg[i].nr_sects << 9) + 
   12.75                              (PAGE_SIZE - 1)) & PAGE_MASK;
   12.76 -        if ( direct_remap_area_pages(&init_mm, 
   12.77 -                                     MMAP_VADDR(pending_idx, i),
   12.78 -                                     phys_seg[i].buffer & PAGE_MASK, 
   12.79 -                                     sz, prot, blkif->domid) != 0 )
   12.80 +        int rc = direct_remap_area_pages(&init_mm, 
   12.81 +                                         MMAP_VADDR(pending_idx, i),
   12.82 +                                         phys_seg[i].buffer & PAGE_MASK, 
   12.83 +                                         sz, prot, blkif->domid);
   12.84 +        if ( rc != 0 )
   12.85          {
   12.86              DPRINTK("invalid buffer\n");
   12.87              vmfree_area_pages(MMAP_VADDR(pending_idx, 0), 
   12.88 -                              MMAP_PAGES_PER_REQUEST);
   12.89 +                              MMAP_PAGES_PER_REQUEST * PAGE_SIZE);
   12.90              goto bad_descriptor;
   12.91          }
   12.92      }
   12.93 @@ -374,7 +378,7 @@ static void dispatch_rw_block_io(blkif_t
   12.94      pending_req->blkif     = blkif;
   12.95      pending_req->id        = req->id;
   12.96      pending_req->operation = operation;
   12.97 -    pending_req->status    = BLKIF_RSP_ERROR;
   12.98 +    pending_req->status    = BLKIF_RSP_OKAY;
   12.99      atomic_set(&pending_req->pendcnt, nr_psegs);
  12.100  
  12.101      blkif_get(blkif);
  12.102 @@ -382,29 +386,30 @@ static void dispatch_rw_block_io(blkif_t
  12.103      /* Now we pass each segment down to the real blkdev layer. */
  12.104      for ( i = 0; i < nr_psegs; i++ )
  12.105      {
  12.106 -        bh = kmem_cache_alloc(buffer_head_cachep, GFP_KERNEL);
  12.107 +        bh = kmem_cache_alloc(buffer_head_cachep, GFP_ATOMIC);
  12.108          if ( unlikely(bh == NULL) )
  12.109              panic("bh is null\n");
  12.110          memset(bh, 0, sizeof (struct buffer_head));
  12.111 -    
  12.112 +
  12.113 +        init_waitqueue_head(&bh->b_wait);
  12.114          bh->b_size          = phys_seg[i].nr_sects << 9;
  12.115          bh->b_dev           = phys_seg[i].dev;
  12.116 +        bh->b_rdev          = phys_seg[i].dev;
  12.117          bh->b_rsector       = (unsigned long)phys_seg[i].sector_number;
  12.118 -        bh->b_data          = (char *)MMAP_VADDR(pending_idx, i) + 
  12.119 +        bh->b_data          = (char *)MMAP_VADDR(pending_idx, i) +
  12.120              (phys_seg[i].buffer & ~PAGE_MASK);
  12.121 -        /* SMH: bh_phys() uses the below field as a 'cheap' virt_to_phys */
  12.122 -        bh->b_page          = &mem_map[phys_seg[i].buffer>>PAGE_SHIFT]; 
  12.123          bh->b_end_io        = end_block_io_op;
  12.124          bh->b_private       = pending_req;
  12.125  
  12.126 -        bh->b_state = (1 << BH_Mapped) | (1 << BH_Lock);
  12.127 +        bh->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | 
  12.128 +            (1 << BH_Req) | (1 << BH_Launder);
  12.129          if ( operation == WRITE )
  12.130              bh->b_state |= (1 << BH_JBD) | (1 << BH_Req) | (1 << BH_Uptodate);
  12.131  
  12.132          atomic_set(&bh->b_count, 1);
  12.133  
  12.134          /* Dispatch a single request. We'll flush it to disc later. */
  12.135 -        submit_bh(operation, bh);
  12.136 +        generic_make_request(operation, bh);
  12.137      }
  12.138  
  12.139      pending_cons++;
  12.140 @@ -444,16 +449,7 @@ static void make_response(blkif_t *blkif
  12.141  
  12.142  void blkif_deschedule(blkif_t *blkif)
  12.143  {
  12.144 -    unsigned long flags;
  12.145 -
  12.146 -    spin_lock_irqsave(&io_schedule_list_lock, flags);
  12.147 -    if ( __on_blkdev_list(blkif) )
  12.148 -    {
  12.149 -        list_del(&blkif->blkdev_list);
  12.150 -        blkif->blkdev_list.next = (void *)0xdeadbeef;
  12.151 -        blkif_put(blkif);
  12.152 -    }
  12.153 -    spin_unlock_irqrestore(&io_schedule_list_lock, flags);
  12.154 +    remove_from_blkdev_list(blkif);
  12.155  }
  12.156  
  12.157  static int __init init_module(void)
    13.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/vbd.c	Wed Apr 28 14:08:16 2004 +0000
    13.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/vbd.c	Fri Apr 30 15:41:03 2004 +0000
    13.3 @@ -47,7 +47,7 @@ void vbd_create(blkif_be_vbd_create_t *c
    13.4          }
    13.5      }
    13.6  
    13.7 -    if ( unlikely((vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) )
    13.8 +    if ( unlikely((vbd = kmalloc(sizeof(vbd_t), GFP_ATOMIC)) == NULL) )
    13.9      {
   13.10          DPRINTK("vbd_create: out of memory\n");
   13.11          create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   13.12 @@ -62,11 +62,12 @@ void vbd_create(blkif_be_vbd_create_t *c
   13.13      rb_link_node(&vbd->rb, rb_parent, rb_p);
   13.14      rb_insert_color(&vbd->rb, &blkif->vbd_rb);
   13.15  
   13.16 +    DPRINTK("Successful creation of vdev=%04x (dom=%llu)\n",
   13.17 +            vdevice, create->domid);
   13.18      create->status = BLKIF_BE_STATUS_OKAY;
   13.19  
   13.20   out:
   13.21      spin_unlock(&blkif->vbd_lock);
   13.22 -    blkif_put(blkif);
   13.23  }
   13.24  
   13.25  
   13.26 @@ -110,7 +111,7 @@ void vbd_grow(blkif_be_vbd_grow_t *grow)
   13.27      } 
   13.28  
   13.29      if ( unlikely((x = kmalloc(sizeof(blkif_extent_le_t), 
   13.30 -                               GFP_KERNEL)) == NULL) )
   13.31 +                               GFP_ATOMIC)) == NULL) )
   13.32      {
   13.33          DPRINTK("vbd_grow: out of memory\n");
   13.34          grow->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   13.35 @@ -127,11 +128,12 @@ void vbd_grow(blkif_be_vbd_grow_t *grow)
   13.36  
   13.37      *px = x;
   13.38  
   13.39 +    DPRINTK("Successful grow of vdev=%04x (dom=%llu)\n",
   13.40 +            vdevice, grow->domid);
   13.41      grow->status = BLKIF_BE_STATUS_OKAY;
   13.42  
   13.43   out:
   13.44      spin_unlock(&blkif->vbd_lock);
   13.45 -    blkif_put(blkif);
   13.46  }
   13.47  
   13.48  
   13.49 @@ -190,7 +192,6 @@ void vbd_shrink(blkif_be_vbd_shrink_t *s
   13.50  
   13.51   out:
   13.52      spin_unlock(&blkif->vbd_lock);
   13.53 -    blkif_put(blkif);
   13.54  }
   13.55  
   13.56  
   13.57 @@ -242,7 +243,6 @@ void vbd_destroy(blkif_be_vbd_destroy_t 
   13.58      
   13.59   out:
   13.60      spin_unlock(&blkif->vbd_lock);
   13.61 -    blkif_put(blkif);
   13.62  }
   13.63  
   13.64  
    14.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/main.c	Wed Apr 28 14:08:16 2004 +0000
    14.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/main.c	Fri Apr 30 15:41:03 2004 +0000
    14.3 @@ -18,9 +18,9 @@
    14.4  
    14.5  typedef unsigned char byte; /* from linux/ide.h */
    14.6  
    14.7 -#define BLKIF_STATE_CLOSED    0
    14.8 -#define BLKIF_STATE_DOWN      1
    14.9 -#define BLKIF_STATE_UP        2
   14.10 +#define BLKIF_STATE_CLOSED       0
   14.11 +#define BLKIF_STATE_DISCONNECTED 1
   14.12 +#define BLKIF_STATE_CONNECTED    2
   14.13  static unsigned int blkif_state = BLKIF_STATE_CLOSED;
   14.14  static unsigned int blkif_evtchn, blkif_irq;
   14.15  
   14.16 @@ -35,7 +35,7 @@ static BLK_RING_IDX req_prod;  /* Privat
   14.17  
   14.18  /* We plug the I/O ring if the driver is suspended or if the ring is full. */
   14.19  #define RING_PLUGGED (((req_prod - resp_cons) == BLK_RING_SIZE) || \
   14.20 -                      (blkif_state != BLKIF_STATE_UP))
   14.21 +                      (blkif_state != BLKIF_STATE_CONNECTED))
   14.22  
   14.23  
   14.24  /*
   14.25 @@ -123,8 +123,10 @@ int blkif_release(struct inode *inode, s
   14.26       */
   14.27      if ( --disk->usage == 0 )
   14.28      {
   14.29 +#if 0
   14.30          update_tq.routine = update_vbds_task;
   14.31          schedule_task(&update_tq);
   14.32 +#endif
   14.33      }
   14.34  
   14.35      return 0;
   14.36 @@ -306,7 +308,7 @@ static int blkif_queue_request(unsigned 
   14.37      if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) )
   14.38          BUG();
   14.39  
   14.40 -    if ( unlikely(blkif_state != BLKIF_STATE_UP) )
   14.41 +    if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) )
   14.42          return 1;
   14.43  
   14.44      switch ( operation )
   14.45 @@ -498,7 +500,7 @@ static void blkif_int(int irq, void *dev
   14.46              {
   14.47                  next_bh = bh->b_reqnext;
   14.48                  bh->b_reqnext = NULL;
   14.49 -                bh->b_end_io(bh, !bret->status);
   14.50 +                bh->b_end_io(bh, bret->status == BLKIF_RSP_OKAY);
   14.51              }
   14.52              break;
   14.53          case BLKIF_OP_PROBE:
   14.54 @@ -556,18 +558,18 @@ void blkif_control_send(blkif_request_t 
   14.55  
   14.56  static void blkif_bringup_phase1(void *unused)
   14.57  {
   14.58 -    ctrl_msg_t              cmsg;
   14.59 -    blkif_fe_interface_up_t up;
   14.60 +    ctrl_msg_t                   cmsg;
   14.61 +    blkif_fe_interface_connect_t up;
   14.62  
   14.63 -    /* Move from CLOSED to DOWN state. */
   14.64 +    /* Move from CLOSED to DISCONNECTED state. */
   14.65      blk_ring = (blkif_ring_t *)__get_free_page(GFP_KERNEL);
   14.66      blk_ring->req_prod = blk_ring->resp_prod = resp_cons = req_prod = 0;
   14.67 -    blkif_state  = BLKIF_STATE_DOWN;
   14.68 +    blkif_state  = BLKIF_STATE_DISCONNECTED;
   14.69  
   14.70 -    /* Construct an interface-UP message for the domain controller. */
   14.71 +    /* Construct an interface-CONNECT message for the domain controller. */
   14.72      cmsg.type      = CMSG_BLKIF_FE;
   14.73 -    cmsg.subtype   = CMSG_BLKIF_FE_INTERFACE_UP;
   14.74 -    cmsg.length    = sizeof(blkif_fe_interface_up_t);
   14.75 +    cmsg.subtype   = CMSG_BLKIF_FE_INTERFACE_CONNECT;
   14.76 +    cmsg.length    = sizeof(blkif_fe_interface_connect_t);
   14.77      up.handle      = 0;
   14.78      up.shmem_frame = virt_to_machine(blk_ring) >> PAGE_SHIFT;
   14.79      memcpy(cmsg.msg, &up, sizeof(up));
   14.80 @@ -578,14 +580,14 @@ static void blkif_bringup_phase1(void *u
   14.81  
   14.82  static void blkif_bringup_phase2(void *unused)
   14.83  {
   14.84 -    /* Move from DOWN to UP state. */
   14.85      blkif_irq = bind_evtchn_to_irq(blkif_evtchn);
   14.86      (void)request_irq(blkif_irq, blkif_int, 0, "blkif", NULL);
   14.87 -    blkif_state = BLKIF_STATE_UP;
   14.88  
   14.89      /* Probe for discs that are attached to the interface. */
   14.90      xlvbd_init();
   14.91  
   14.92 +    blkif_state = BLKIF_STATE_CONNECTED;
   14.93 +
   14.94      /* Kick pending requests. */
   14.95      spin_lock_irq(&io_request_lock);
   14.96      kick_pending_request_queues();
   14.97 @@ -608,22 +610,22 @@ static void blkif_status_change(blkif_fe
   14.98                 blkif_state);
   14.99          break;
  14.100  
  14.101 -    case BLKIF_INTERFACE_STATUS_DOWN:
  14.102 +    case BLKIF_INTERFACE_STATUS_DISCONNECTED:
  14.103          if ( blkif_state != BLKIF_STATE_CLOSED )
  14.104          {
  14.105 -            printk(KERN_WARNING "Unexpected blkif-DOWN message in state %d\n",
  14.106 -                   blkif_state);
  14.107 +            printk(KERN_WARNING "Unexpected blkif-DISCONNECTED message"
  14.108 +                   " in state %d\n", blkif_state);
  14.109              break;
  14.110          }
  14.111          blkif_statechange_tq.routine = blkif_bringup_phase1;
  14.112          schedule_task(&blkif_statechange_tq);
  14.113          break;
  14.114  
  14.115 -    case BLKIF_INTERFACE_STATUS_UP:
  14.116 +    case BLKIF_INTERFACE_STATUS_CONNECTED:
  14.117          if ( blkif_state == BLKIF_STATE_CLOSED )
  14.118          {
  14.119 -            printk(KERN_WARNING "Unexpected blkif-UP message in state %d\n",
  14.120 -                   blkif_state);
  14.121 +            printk(KERN_WARNING "Unexpected blkif-CONNECTED message"
  14.122 +                   " in state %d\n", blkif_state);
  14.123              break;
  14.124          }
  14.125          blkif_evtchn = status->evtchn;
  14.126 @@ -683,6 +685,17 @@ int __init xlblk_init(void)
  14.127      memcpy(cmsg.msg, &st, sizeof(st));
  14.128      ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
  14.129  
  14.130 +    /*
  14.131 +     * We should read 'nr_interfaces' from response message and wait
  14.132 +     * for notifications before proceeding. For now we assume that we
  14.133 +     * will be notified of exactly one interface.
  14.134 +     */
  14.135 +    while ( blkif_state != BLKIF_STATE_CONNECTED )
  14.136 +    {
  14.137 +        set_current_state(TASK_INTERRUPTIBLE);
  14.138 +        schedule_timeout(1);
  14.139 +    }
  14.140 +
  14.141      return 0;
  14.142  }
  14.143  
    15.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/vbd.c	Wed Apr 28 14:08:16 2004 +0000
    15.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/vbd.c	Fri Apr 30 15:41:03 2004 +0000
    15.3 @@ -512,7 +512,7 @@ void xlvbd_update_vbds(void)
    15.4   * linux -- this is just for convenience as it means e.g. that the same 
    15.5   * /etc/fstab can be used when booting with or without Xen.
    15.6   */
    15.7 -int __init xlvbd_init(void)
    15.8 +int xlvbd_init(void)
    15.9  {
   15.10      int i;
   15.11      
   15.12 @@ -559,8 +559,3 @@ int __init xlvbd_init(void)
   15.13  
   15.14      return 0;
   15.15  }
   15.16 -
   15.17 -
   15.18 -#ifdef MODULE
   15.19 -module_init(xlvbd_init);
   15.20 -#endif
    16.1 --- a/xenolinux-2.4.26-sparse/include/asm-xen/io.h	Wed Apr 28 14:08:16 2004 +0000
    16.2 +++ b/xenolinux-2.4.26-sparse/include/asm-xen/io.h	Fri Apr 30 15:41:03 2004 +0000
    16.3 @@ -159,13 +159,47 @@ extern void iounmap(void *addr);
    16.4  extern void *bt_ioremap(unsigned long offset, unsigned long size);
    16.5  extern void bt_iounmap(void *addr, unsigned long size);
    16.6  
    16.7 +#ifdef CONFIG_XEN_PHYSDEV_ACCESS
    16.8 +
    16.9 +#ifdef CONFIG_HIGHMEM
   16.10 +#error "Highmem is not yet compatible with physical device access"
   16.11 +#endif
   16.12 +
   16.13  /*
   16.14 - * IO bus memory addresses are also 1:1 with the physical address
   16.15 + * The bus translation macros need special care if we are executing device
   16.16 + * accesses to/from other domains' memory. In these cases the virtual address
   16.17 + * is actually a temporary mapping in the 'vmalloc' space. The physical
   16.18 + * address will therefore be >max_low_pfn, and will not have a valid entry
   16.19 + * in the phys_to_mach mapping table.
   16.20   */
   16.21 +static inline unsigned long phys_to_bus(unsigned long phys)
   16.22 +{
   16.23 +    extern unsigned long max_pfn;
   16.24 +    pgd_t *pgd; pmd_t *pmd; pte_t *pte;
   16.25 +    void *addr;
   16.26 +    unsigned long bus;
   16.27 +    if ( (phys >> PAGE_SHIFT) < max_pfn )
   16.28 +        return phys_to_machine(phys);
   16.29 +    addr = phys_to_virt(phys);
   16.30 +    pgd = pgd_offset_k(   (unsigned long)addr);
   16.31 +    pmd = pmd_offset(pgd, (unsigned long)addr);
   16.32 +    pte = pte_offset(pmd, (unsigned long)addr);
   16.33 +    bus = (pte->pte_low & PAGE_MASK) | (phys & ~PAGE_MASK);
   16.34 +    return bus;
   16.35 +}
   16.36 +
   16.37 +#define virt_to_bus(_x) phys_to_bus(virt_to_phys(_x))
   16.38 +#define bus_to_virt(_x) phys_to_virt(machine_to_phys(_x))
   16.39 +#define page_to_bus(_x) phys_to_bus(page_to_phys(_x))
   16.40 +
   16.41 +#else
   16.42 +
   16.43  #define virt_to_bus(_x) phys_to_machine(virt_to_phys(_x))
   16.44  #define bus_to_virt(_x) phys_to_virt(machine_to_phys(_x))
   16.45  #define page_to_bus(_x) phys_to_machine(page_to_phys(_x))
   16.46  
   16.47 +#endif /* CONFIG_XEN_PHYSDEV_ACCESS */
   16.48 +
   16.49  /*
   16.50   * readX/writeX() are used to access memory mapped devices. On some
   16.51   * architectures the memory mapped IO stuff needs to be accessed