ia64/xen-unstable

changeset 1438:88484dcdafbf

bitkeeper revision 1.934.2.2 (40c59f23b5OBWV0EcUOWaE-IXlUYNQ)

Infrastructure for restartable block device drivers.
author mwilli2@equilibrium.research.intel-research.net
date Tue Jun 08 11:12:35 2004 +0000 (2004-06-08)
parents c061db2d4eb5
children 3ee528275c75
files tools/examples/xc_dom_create.py tools/xend/lib/blkif.py tools/xend/lib/main.py tools/xend/lib/manager.py xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c
line diff
     1.1 --- a/tools/examples/xc_dom_create.py	Tue Jun 08 11:07:31 2004 +0000
     1.2 +++ b/tools/examples/xc_dom_create.py	Tue Jun 08 11:12:35 2004 +0000
     1.3 @@ -273,66 +273,78 @@ def make_domain():
     1.4      # set the expertise level appropriately
     1.5      xenctl.utils.VBD_EXPERT_MODE = vbd_expert
     1.6  
     1.7 -    if new_io_world:
     1.8 -        cmsg = 'new_block_interface(dom='+str(id)+')'
     1.9 -        xend_response = xenctl.utils.xend_control_message(cmsg)
    1.10 -        if not xend_response['success']:
    1.11 -            print "Error creating block interface"
    1.12 -            print "Error type: " + xend_response['error_type']
    1.13 -            if xend_response['error_type'] == 'exception':
    1.14 -                print "Exception type: " + xend_response['exception_type']
    1.15 -                print "Exception val:  " + xend_response['exception_value']
    1.16 -            xc.domain_destroy ( dom=id )
    1.17 -            sys.exit()
    1.18 -    
    1.19 -    for ( uname, virt_name, rw ) in vbd_list:
    1.20 -	virt_dev = xenctl.utils.blkdev_name_to_number( virt_name )
    1.21 -
    1.22 -	segments = xenctl.utils.lookup_disk_uname( uname )
    1.23 -	if not segments:
    1.24 -	    print "Error looking up %s\n" % uname
    1.25 -	    xc.domain_destroy ( dom=id )
    1.26 -	    sys.exit()
    1.27 -
    1.28 +    if not (flags & 4): # It's not a block backend (or it's old IO world)
    1.29          if new_io_world:
    1.30 -            if len(segments) > 1:
    1.31 -                print "New I/O world cannot deal with multi-extent vdisks"
    1.32 -                xc.domain_destroy ( dom=id )
    1.33 -                sys.exit()
    1.34 -            seg = segments[0]
    1.35 -            cmsg = 'new_block_device(dom=' + str(id) + \
    1.36 -                   ',handle=0,vdev=' + str(virt_dev) + \
    1.37 -                   ',pdev=' + str(seg['device']) + \
    1.38 -                   ',start_sect=' + str(seg['start_sector']) + \
    1.39 -                   ',nr_sect=' + str(seg['nr_sectors']) + \
    1.40 -                   ',readonly=' + str(not re.match('w',rw)) + ')'
    1.41 +            cmsg = 'new_block_interface(dom='+str(id)+')'
    1.42              xend_response = xenctl.utils.xend_control_message(cmsg)
    1.43              if not xend_response['success']:
    1.44 -                print "Error creating virtual block device"
    1.45 +                print "Error creating block interface"
    1.46                  print "Error type: " + xend_response['error_type']
    1.47                  if xend_response['error_type'] == 'exception':
    1.48                      print "Exception type: " + xend_response['exception_type']
    1.49                      print "Exception val:  " + xend_response['exception_value']
    1.50                  xc.domain_destroy ( dom=id )
    1.51                  sys.exit()
    1.52 -        else:
    1.53 -            # check that setting up this VBD won't violate the sharing
    1.54 -            # allowed by the current VBD expertise level
    1.55 -            if xenctl.utils.vd_extents_validate(segments,
    1.56 -                                                rw=='w' or rw=='rw') < 0:
    1.57 -                xc.domain_destroy( dom = id )
    1.58 -                sys.exit()
    1.59 -            
    1.60 -            if xc.vbd_create( dom=id, vbd=virt_dev,
    1.61 -                              writeable= rw=='w' or rw=='rw' ):
    1.62 -                print "Error creating VBD %d (writeable=%d)\n" % (virt_dev,rw)
    1.63 +
    1.64 +        for ( uname, virt_name, rw ) in vbd_list:
    1.65 +            virt_dev = xenctl.utils.blkdev_name_to_number( virt_name )
    1.66 +
    1.67 +            segments = xenctl.utils.lookup_disk_uname( uname )
    1.68 +            if not segments:
    1.69 +                print "Error looking up %s\n" % uname
    1.70                  xc.domain_destroy ( dom=id )
    1.71                  sys.exit()
    1.72 +
    1.73 +            if new_io_world:
    1.74 +                if len(segments) > 1:
    1.75 +                    print "New I/O world cannot deal with multi-extent vdisks"
    1.76 +                    xc.domain_destroy ( dom=id )
    1.77 +                    sys.exit()
    1.78 +                seg = segments[0]
    1.79 +                cmsg = 'new_block_device(dom=' + str(id) + \
    1.80 +                       ',handle=0,vdev=' + str(virt_dev) + \
    1.81 +                       ',pdev=' + str(seg['device']) + \
    1.82 +                       ',start_sect=' + str(seg['start_sector']) + \
    1.83 +                       ',nr_sect=' + str(seg['nr_sectors']) + \
    1.84 +                       ',readonly=' + str(not re.match('w',rw)) + ')'
    1.85 +                xend_response = xenctl.utils.xend_control_message(cmsg)
    1.86 +                if not xend_response['success']:
    1.87 +                    print "Error creating virtual block device"
    1.88 +                    print "Error type: " + xend_response['error_type']
    1.89 +                    if xend_response['error_type'] == 'exception':
    1.90 +                        print "Exception type: " + xend_response['exception_type']
    1.91 +                        print "Exception val:  " + xend_response['exception_value']
    1.92 +                    xc.domain_destroy ( dom=id )
    1.93 +                    sys.exit()
    1.94 +            else:
    1.95 +                # check that setting up this VBD won't violate the sharing
    1.96 +                # allowed by the current VBD expertise level
    1.97 +                if xenctl.utils.vd_extents_validate(segments,
    1.98 +                                                    rw=='w' or rw=='rw') < 0:
    1.99 +                    xc.domain_destroy( dom = id )
   1.100 +                    sys.exit()
   1.101 +            
   1.102 +                if xc.vbd_create( dom=id, vbd=virt_dev,
   1.103 +                                  writeable= rw=='w' or rw=='rw' ):
   1.104 +                    print "Error creating VBD %d (writeable=%d)\n" % (virt_dev,rw)
   1.105 +                    xc.domain_destroy ( dom=id )
   1.106 +                    sys.exit()
   1.107  	
   1.108 -            if xc.vbd_setextents( dom=id,
   1.109 -                                  vbd=virt_dev,
   1.110 -                                  extents=segments):
   1.111 -                print "Error populating VBD vbd=%d\n" % virt_dev
   1.112 +                if xc.vbd_setextents( dom=id,
   1.113 +                                      vbd=virt_dev,
   1.114 +                                      extents=segments):
   1.115 +                    print "Error populating VBD vbd=%d\n" % virt_dev
   1.116 +                    xc.domain_destroy ( dom=id )
   1.117 +                    sys.exit()
   1.118 +    else: # It's a block backend - notify Xend.
   1.119 +        cmsg = 'set_block_backend(dom='+str(id)+')'
   1.120 +        xend_response = xenctl.utils.xend_control_message(cmsg)
   1.121 +        if not xend_response['success']:
   1.122 +            print "Error registering network backend"
   1.123 +            print "Error type: " + xend_response['error_type']
   1.124 +            if xend_response['error_type'] == 'exception':
   1.125 +                print "Exception type: " + xend_response['exception_type']
   1.126 +                print "Exception val:  " + xend_response['exception_value']
   1.127                  xc.domain_destroy ( dom=id )
   1.128                  sys.exit()
   1.129  
     2.1 --- a/tools/xend/lib/blkif.py	Tue Jun 08 11:07:31 2004 +0000
     2.2 +++ b/tools/xend/lib/blkif.py	Tue Jun 08 11:12:35 2004 +0000
     2.3 @@ -11,6 +11,7 @@ CMSG_BLKIF_BE = 1
     2.4  CMSG_BLKIF_FE = 2
     2.5  CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
     2.6  CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
     2.7 +CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
     2.8  CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
     2.9  CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
    2.10  CMSG_BLKIF_BE_CREATE      = 0
    2.11 @@ -22,11 +23,19 @@ CMSG_BLKIF_BE_VBD_DESTROY = 5
    2.12  CMSG_BLKIF_BE_VBD_GROW    = 6
    2.13  CMSG_BLKIF_BE_VBD_SHRINK  = 7
    2.14  
    2.15 +BLKIF_DRIVER_STATUS_DOWN  = 0
    2.16 +BLKIF_DRIVER_STATUS_UP    = 1
    2.17 +
    2.18  pendmsg = None
    2.19  pendaddr = None
    2.20  
    2.21 +recovery = False # Is a recovery in progress? (if so we'll need to notify guests)
    2.22 +be_port  = None  # Port object for backend domain
    2.23 +
    2.24  def backend_tx_req(msg):
    2.25 -    port = xend.main.dom0_port
    2.26 +    port = xend.blkif.be_port
    2.27 +    if not port:
    2.28 +        print "BUG: attempt to transmit request to non-existant blkif driver"
    2.29      if port.space_to_write_request():
    2.30          port.write_request(msg)
    2.31          port.notify()
    2.32 @@ -35,6 +44,26 @@ def backend_tx_req(msg):
    2.33  
    2.34  def backend_rx_req(port, msg):
    2.35      port.write_response(msg)
    2.36 +    subtype = (msg.get_header())['subtype']
    2.37 +    print "Received blkif-be request, subtype %d" % subtype
    2.38 +    if subtype == CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
    2.39 +        (status, dummy) = struct.unpack("II", msg.get_payload())
    2.40 +        if status == BLKIF_DRIVER_STATUS_UP:
    2.41 +            if xend.blkif.recovery:
    2.42 +                # Nasty hack: we count the number of VBDs we reattach so that
    2.43 +                # we'll know when to notify the guests.  Must make this better!
    2.44 +                interface.rebuilt_so_far = 0
    2.45 +                interface.nr_to_rebuild  = 0
    2.46 +                print "New blkif backend now UP, rebuilding VBDs:"
    2.47 +                for blkif_key in interface.list.keys():
    2.48 +                    blkif = interface.list[blkif_key]
    2.49 +                    blkif.create()
    2.50 +                    for vdev in blkif.devices.keys():
    2.51 +                        blkif.reattach_device(vdev)
    2.52 +                        interface.nr_to_rebuild += 1
    2.53 +        else:
    2.54 +            print "Unexpected block backend driver status: %d" % status
    2.55 +
    2.56  
    2.57  def backend_rx_rsp(port, msg):
    2.58      subtype = (msg.get_header())['subtype']
    2.59 @@ -58,8 +87,23 @@ def backend_rx_rsp(port, msg):
    2.60                                         pdev,start_sect,nr_sect,0))
    2.61          backend_tx_req(msg)
    2.62      elif subtype == CMSG_BLKIF_BE_VBD_GROW:
    2.63 -        rsp = { 'success': True }
    2.64 -        xend.main.send_management_response(rsp, xend.blkif.pendaddr)
    2.65 +       if not xend.blkif.recovery:
    2.66 +           rsp = { 'success': True }
    2.67 +           xend.main.send_management_response(rsp, xend.blkif.pendaddr)
    2.68 +       else:
    2.69 +           interface.rebuilt_so_far += 1
    2.70 +           if interface.rebuilt_so_far == interface.nr_to_rebuild:
    2.71 +               print "Rebuilt VBDs, notifying guests:"
    2.72 +               for blkif_key in interface.list.keys():
    2.73 +                   blkif = interface.list[blkif_key]
    2.74 +                   print "  Notifying %d" % blkif.dom
    2.75 +                   msg = xend.utils.message(CMSG_BLKIF_FE,                   \
    2.76 +                                            CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, 0)
    2.77 +                   msg.append_payload(struct.pack("III", 0,1,0))
    2.78 +                   blkif.ctrlif_tx_req(xend.main.port_from_dom(blkif.dom),msg)
    2.79 +               xend.blkif.recovery = False
    2.80 +               print "Done notifying guests"
    2.81 +
    2.82  
    2.83  def backend_do_work(port):
    2.84      global pendmsg
    2.85 @@ -75,7 +119,6 @@ class interface:
    2.86      # Dictionary of all block-device interfaces.
    2.87      list = {}
    2.88  
    2.89 -
    2.90      # NB. 'key' is an opaque value that has no meaning in this class.
    2.91      def __init__(self, dom, key):
    2.92          self.dom     = dom
    2.93 @@ -83,8 +126,11 @@ class interface:
    2.94          self.devices = {}
    2.95          self.pendmsg = None
    2.96          interface.list[key] = self
    2.97 +        self.create()
    2.98 +
    2.99 +    def create(self):
   2.100          msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE, 0)
   2.101 -        msg.append_payload(struct.pack("III",dom,0,0))
   2.102 +        msg.append_payload(struct.pack("III",self.dom,0,0))
   2.103          xend.blkif.pendaddr = xend.main.mgmt_req_addr
   2.104          backend_tx_req(msg)
   2.105  
   2.106 @@ -99,6 +145,12 @@ class interface:
   2.107          backend_tx_req(msg)
   2.108          return True
   2.109  
   2.110 +    def reattach_device(self, vdev):
   2.111 +        (pdev, start_sect, nr_sect, readonly) = self.devices[vdev]
   2.112 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE, 0)
   2.113 +        msg.append_payload(struct.pack("IIHII",self.dom,0,vdev,readonly,0))
   2.114 +        xend.blkif.pendaddr = xend.main.mgmt_req_addr
   2.115 +        backend_tx_req(msg)
   2.116  
   2.117      # Completely destroy this interface.
   2.118      def destroy(self):
   2.119 @@ -128,14 +180,18 @@ class interface:
   2.120          port.write_response(msg)
   2.121          subtype = (msg.get_header())['subtype']
   2.122          if subtype == CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
   2.123 +            print "BLKIF: Domain %d says hello" % port.remote_dom
   2.124              msg = xend.utils.message(CMSG_BLKIF_FE, \
   2.125                                       CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, 0)
   2.126              msg.append_payload(struct.pack("III",0,1,0))
   2.127              self.ctrlif_tx_req(port, msg)
   2.128          elif subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT:
   2.129 +            print "BLKIF: Domain %d wants to connect" % port.remote_dom
   2.130              (hnd,frame) = struct.unpack("IL", msg.get_payload())
   2.131              xc = Xc.new()
   2.132 -            self.evtchn = xc.evtchn_bind_interdomain(dom1=0,dom2=self.dom)
   2.133 +            self.evtchn = xc.evtchn_bind_interdomain( \
   2.134 +                dom1=xend.blkif.be_port.remote_dom,   \
   2.135 +                dom2=self.dom)
   2.136              msg = xend.utils.message(CMSG_BLKIF_BE, \
   2.137                                       CMSG_BLKIF_BE_CONNECT, 0)
   2.138              msg.append_payload(struct.pack("IIILI",self.dom,0, \
     3.1 --- a/tools/xend/lib/main.py	Tue Jun 08 11:07:31 2004 +0000
     3.2 +++ b/tools/xend/lib/main.py	Tue Jun 08 11:12:35 2004 +0000
     3.3 @@ -72,6 +72,8 @@ def daemon_loop():
     3.4      # Note that console messages don't come our way (actually, only driver
     3.5      # back-ends should use the DOM0 control interface).
     3.6      dom0_port = xend.utils.port(0)
     3.7 +    xend.netif.be_port = dom0_port
     3.8 +    xend.blkif_be_port = dom0_port
     3.9      notifier.bind(dom0_port.local_port)
    3.10      port_list[dom0_port.local_port] = dom0_port
    3.11  
    3.12 @@ -195,7 +197,7 @@ def daemon_loop():
    3.13                      con_if.ctrlif_rx_req(port, msg)
    3.14                  elif type == CMSG_BLKIF_FE and blk_if:
    3.15                      blk_if.ctrlif_rx_req(port, msg)
    3.16 -                elif type == CMSG_BLKIF_BE and port == dom0_port:
    3.17 +                elif type == CMSG_BLKIF_BE and port == xend.blkif.be_port:
    3.18                      xend.blkif.backend_rx_req(port, msg)
    3.19                  elif type == CMSG_NETIF_FE and net_if:
    3.20                      net_if.ctrlif_rx_req(port, msg)
    3.21 @@ -209,7 +211,7 @@ def daemon_loop():
    3.22                  msg = port.read_response()
    3.23                  work_done = True
    3.24                  type = (msg.get_header())['type']
    3.25 -                if type == CMSG_BLKIF_BE and port == dom0_port:
    3.26 +                if type == CMSG_BLKIF_BE and port == xend.blkif.be_port:
    3.27                      xend.blkif.backend_rx_rsp(port, msg)
    3.28                  elif type == CMSG_NETIF_BE and port == xend.netif.be_port:
    3.29                      xend.netif.backend_rx_rsp(port, msg)
     4.1 --- a/tools/xend/lib/manager.py	Tue Jun 08 11:07:31 2004 +0000
     4.2 +++ b/tools/xend/lib/manager.py	Tue Jun 08 11:12:35 2004 +0000
     4.3 @@ -161,3 +161,13 @@ def set_network_backend(dom):
     4.4      if xend.netif.be_port: xend.netif.recovery = True
     4.5      xend.netif.be_port = xend.main.port_from_dom(dom)
     4.6      return { 'success' : True }
     4.7 +
     4.8 +##
     4.9 +## set_block_backend
    4.10 +##  Authorise a domain to act as the block backend (assumes we only have one
    4.11 +##  backend driver for now).  After this call, back end "up" notifications
    4.12 +##  for the network will only be accepted from this domain.
    4.13 +def set_block_backend(dom):
    4.14 +    if xend.blkif.be_port: xend.blkif.recovery = True
    4.15 +    xend.blkif.be_port = xend.main.port_from_dom(dom)
    4.16 +    return { 'success' : True }
     5.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c	Tue Jun 08 11:07:31 2004 +0000
     5.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c	Tue Jun 08 11:12:35 2004 +0000
     5.3 @@ -487,7 +487,8 @@ static int __init init_module(void)
     5.4  {
     5.5      int i;
     5.6  
     5.7 -    if ( !(start_info.flags & SIF_INITDOMAIN) )
     5.8 +    if ( !(start_info.flags & SIF_INITDOMAIN)
     5.9 +	 && !(start_info.flags & SIF_BLK_BE_DOMAIN) )
    5.10          return 0;
    5.11  
    5.12      blkif_interface_init();