direct-io.hg

changeset 1439:3ee528275c75

bitkeeper revision 1.940 (40c5a0a5VY_RJcApOo3Gmxz36JQSrQ)

Manual merge.
author mwilli2@equilibrium.research.intel-research.net
date Tue Jun 08 11:19:01 2004 +0000 (2004-06-08)
parents 64c28f73f702 88484dcdafbf
children 2a1ade2f1f48
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 xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/main.c
line diff
     1.1 --- a/tools/examples/xc_dom_create.py	Tue Jun 08 10:00:47 2004 +0000
     1.2 +++ b/tools/examples/xc_dom_create.py	Tue Jun 08 11:19:01 2004 +0000
     1.3 @@ -274,66 +274,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 10:00:47 2004 +0000
     2.2 +++ b/tools/xend/lib/blkif.py	Tue Jun 08 11:19:01 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 @@ -68,8 +97,23 @@ def backend_rx_rsp(port, msg):
    2.60                                     'extent.device' : pdev })
    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 @@ -85,7 +129,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 @@ -93,8 +136,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 -                                 { 'domid' : dom, 'blkif_handle' : 0 })
   2.102 +                                 { 'domid' : self.dom, 'blkif_handle' : 0 })
   2.103          xend.blkif.pendaddr = xend.main.mgmt_req_addr
   2.104          backend_tx_req(msg)
   2.105  
   2.106 @@ -110,6 +156,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 @@ -148,7 +200,9 @@ class interface:
   2.120              pl = msg.get_payload()
   2.121              (hnd, frame) = (pl['handle'], pl['shmem_frame'])
   2.122              xc = Xc.new()
   2.123 -            self.evtchn = xc.evtchn_bind_interdomain(dom1=0,dom2=self.dom)
   2.124 +            self.evtchn = xc.evtchn_bind_interdomain( \
   2.125 +                dom1=xend.blkif.be_port.remote_dom,   \
   2.126 +                dom2=self.dom)
   2.127              msg = xend.utils.message(CMSG_BLKIF_BE,
   2.128                                       CMSG_BLKIF_BE_CONNECT, 0,
   2.129                                       { 'domid' : self.dom, 'blkif_handle' : 0,
     3.1 --- a/tools/xend/lib/main.py	Tue Jun 08 10:00:47 2004 +0000
     3.2 +++ b/tools/xend/lib/main.py	Tue Jun 08 11:19:01 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 @@ -197,7 +199,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 @@ -211,7 +213,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 10:00:47 2004 +0000
     4.2 +++ b/tools/xend/lib/manager.py	Tue Jun 08 11:19:01 2004 +0000
     4.3 @@ -162,3 +162,13 @@ def set_network_backend(dom):
     4.4          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 10:00:47 2004 +0000
     5.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c	Tue Jun 08 11:19:01 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();
     6.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/main.c	Tue Jun 08 10:00:47 2004 +0000
     6.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/main.c	Tue Jun 08 11:19:01 2004 +0000
     6.3 @@ -16,6 +16,8 @@
     6.4  #include <scsi/scsi.h>
     6.5  #include <asm/ctrl_if.h>
     6.6  
     6.7 +
     6.8 +
     6.9  typedef unsigned char byte; /* from linux/ide.h */
    6.10  
    6.11  #define BLKIF_STATE_CLOSED       0
    6.12 @@ -31,6 +33,15 @@ static blkif_ring_t *blk_ring;
    6.13  static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */
    6.14  static BLK_RING_IDX req_prod;  /* Private request producer.         */
    6.15  
    6.16 +
    6.17 +static blkif_ring_t *blk_ring_rec; /* Private copy of requests, used for
    6.18 +                                    * recovery.  Responses not stored here. */
    6.19 +static BLK_RING_IDX resp_cons_rec; /* Copy of response consumer, used for
    6.20 +                                    * recovery */
    6.21 +static int recovery = 0;           /* "Recovery in progress" flag.  Protected
    6.22 +                                    * by the io_request_lock */
    6.23 +
    6.24 +
    6.25  /* We plug the I/O ring if the driver is suspended or if the ring is full. */
    6.26  #define RING_PLUGGED (((req_prod - resp_cons) == BLK_RING_SIZE) || \
    6.27                        (blkif_state != BLKIF_STATE_CONNECTED))
    6.28 @@ -352,6 +363,11 @@ static int blkif_queue_request(unsigned 
    6.29                  sg_next_sect += nr_sectors;
    6.30              else
    6.31                  DISABLE_SCATTERGATHER();
    6.32 +
    6.33 +            /* Update the copy of the request in the recovery ring. */
    6.34 +            blk_ring_rec->ring[MASK_BLK_IDX(blk_ring_rec->req_prod - 1)].req
    6.35 +                = *req;
    6.36 +
    6.37              return 0;
    6.38          }
    6.39          else if ( RING_PLUGGED )
    6.40 @@ -380,6 +396,10 @@ static int blkif_queue_request(unsigned 
    6.41      req->frame_and_sects[0] = buffer_ma | (fsect<<3) | lsect;
    6.42      req_prod++;
    6.43  
    6.44 +    /* Keep a private copy so we can reissue requests when recovering. */
    6.45 +    blk_ring_rec->ring[MASK_BLK_IDX(blk_ring_rec->req_prod)].req = *req;
    6.46 +    blk_ring_rec->req_prod++;
    6.47 +
    6.48      return 0;
    6.49  }
    6.50  
    6.51 @@ -485,10 +505,17 @@ static void blkif_int(int irq, void *dev
    6.52      unsigned long flags; 
    6.53      struct buffer_head *bh, *next_bh;
    6.54      
    6.55 -    if ( unlikely(blkif_state == BLKIF_STATE_CLOSED) )
    6.56 +//    printk(KERN_ALERT "blkif_int\n");
    6.57 +
    6.58 +    spin_lock_irqsave(&io_request_lock, flags);     
    6.59 +
    6.60 +    if ( unlikely(blkif_state == BLKIF_STATE_CLOSED || recovery) )
    6.61 +    {
    6.62 +        printk("Bailed out\n");
    6.63 +        
    6.64 +        spin_unlock_irqrestore(&io_request_lock, flags);
    6.65          return;
    6.66 -    
    6.67 -    spin_lock_irqsave(&io_request_lock, flags);     
    6.68 +    }
    6.69  
    6.70      for ( i = resp_cons; i != blk_ring->resp_prod; i++ )
    6.71      {
    6.72 @@ -519,6 +546,7 @@ static void blkif_int(int irq, void *dev
    6.73      }
    6.74      
    6.75      resp_cons = i;
    6.76 +    resp_cons_rec = i;
    6.77  
    6.78      kick_pending_request_queues();
    6.79  
    6.80 @@ -546,6 +574,8 @@ void blkif_control_send(blkif_request_t 
    6.81  
    6.82      DISABLE_SCATTERGATHER();
    6.83      memcpy(&blk_ring->ring[MASK_BLK_IDX(req_prod)].req, req, sizeof(*req));
    6.84 +    memcpy(&blk_ring_rec->ring[MASK_BLK_IDX(blk_ring_rec->req_prod++)].req,
    6.85 +           req, sizeof(*req));
    6.86      req_prod++;
    6.87      flush_requests();
    6.88  
    6.89 @@ -586,7 +616,19 @@ static void blkif_status_change(blkif_fe
    6.90          {
    6.91              printk(KERN_WARNING "Unexpected blkif-DISCONNECTED message"
    6.92                     " in state %d\n", blkif_state);
    6.93 -            break;
    6.94 +
    6.95 +            printk(KERN_INFO "VBD driver recovery in progress\n");
    6.96 +            
    6.97 +            /* Prevent new requests being issued until we've fixed things up. */
    6.98 +            spin_lock_irq(&io_request_lock);
    6.99 +            recovery = 1;
   6.100 +            blkif_state = BLKIF_STATE_DISCONNECTED;
   6.101 +            spin_unlock_irq(&io_request_lock);
   6.102 +
   6.103 +            /* Free resources associated with old device channel. */
   6.104 +            free_page((unsigned long)blk_ring);
   6.105 +            free_irq(blkif_irq, NULL);
   6.106 +            unbind_evtchn_from_irq(blkif_evtchn);
   6.107          }
   6.108  
   6.109          /* Move from CLOSED to DISCONNECTED state. */
   6.110 @@ -617,16 +659,55 @@ static void blkif_status_change(blkif_fe
   6.111          blkif_evtchn = status->evtchn;
   6.112          blkif_irq = bind_evtchn_to_irq(blkif_evtchn);
   6.113          (void)request_irq(blkif_irq, blkif_int, 0, "blkif", NULL);
   6.114 -        
   6.115 -        /* Probe for discs that are attached to the interface. */
   6.116 -        xlvbd_init();
   6.117 -        
   6.118 +
   6.119 +        if ( recovery )
   6.120 +        {
   6.121 +            int i;
   6.122 +
   6.123 +	    /* Shouldn't need the io_request_lock here - the device is
   6.124 +	     * plugged and the recovery flag prevents the interrupt handler
   6.125 +	     * changing anything. */
   6.126 +
   6.127 +            /* Reissue requests from the private block ring. */
   6.128 +            for ( i = 0;
   6.129 +		  resp_cons_rec < blk_ring_rec->req_prod;
   6.130 +                  resp_cons_rec++, i++ )
   6.131 +            {
   6.132 +                blk_ring->ring[i].req
   6.133 +                    = blk_ring_rec->ring[MASK_BLK_IDX(resp_cons_rec)].req;
   6.134 +            }
   6.135 +
   6.136 +            /* Reset the private block ring to match the new ring. */
   6.137 +            memcpy(blk_ring_rec, blk_ring, sizeof(*blk_ring));
   6.138 +            resp_cons_rec = 0;
   6.139 +
   6.140 +            /* blk_ring->req_prod will be set when we flush_requests().*/
   6.141 +            blk_ring_rec->req_prod = req_prod = i;
   6.142 +
   6.143 +            wmb();
   6.144 +
   6.145 +            /* Switch off recovery mode, using a memory barrier to ensure that
   6.146 +             * it's seen before we flush requests - we don't want to miss any
   6.147 +             * interrupts. */
   6.148 +            recovery = 0;
   6.149 +            wmb();
   6.150 +
   6.151 +            /* Kicks things back into life. */
   6.152 +            flush_requests();
   6.153 +        }
   6.154 +        else
   6.155 +        {
   6.156 +            /* Probe for discs that are attached to the interface. */
   6.157 +            xlvbd_init();
   6.158 +        }
   6.159 +
   6.160          blkif_state = BLKIF_STATE_CONNECTED;
   6.161          
   6.162          /* Kick pending requests. */
   6.163          spin_lock_irq(&io_request_lock);
   6.164          kick_pending_request_queues();
   6.165          spin_unlock_irq(&io_request_lock);
   6.166 +
   6.167          break;
   6.168  
   6.169      default:
   6.170 @@ -671,9 +752,15 @@ int __init xlblk_init(void)
   6.171      ctrl_msg_t                       cmsg;
   6.172      blkif_fe_driver_status_changed_t st;
   6.173  
   6.174 -    if ( start_info.flags & SIF_INITDOMAIN )
   6.175 +    if ( (start_info.flags & SIF_INITDOMAIN) 
   6.176 +        || (start_info.flags & SIF_BLK_BE_DOMAIN) )
   6.177          return 0;
   6.178  
   6.179 +    printk(KERN_INFO "Initialising Xen virtual block device\n");
   6.180 +
   6.181 +    blk_ring_rec = (blkif_ring_t *)__get_free_page(GFP_KERNEL);
   6.182 +    memset(blk_ring_rec, 0, sizeof(*blk_ring_rec));
   6.183 +
   6.184      (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
   6.185                                      CALLBACK_IN_BLOCKING_CONTEXT);
   6.186