ia64/xen-unstable
changeset 1330:c31e790d45bd
bitkeeper revision 1.879.1.6 (409274b9hAoH4PwGPSnXlglUfoAL7w)
Manual merge.
Manual merge.
line diff
1.1 --- a/.rootkeys Thu Apr 29 15:36:38 2004 +0000 1.2 +++ b/.rootkeys Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 2.2 +++ b/tools/examples/xc_dom_create.py Fri Apr 30 15:46:01 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 @@ -263,6 +272,18 @@ def make_domain(): 2.50 2.51 # set the expertise level appropriately 2.52 xenctl.utils.VBD_EXPERT_MODE = vbd_expert 2.53 + 2.54 + if new_io_world: 2.55 + cmsg = 'new_block_interface(dom='+str(id)+')' 2.56 + xend_response = xenctl.utils.xend_control_message(cmsg) 2.57 + if not xend_response['success']: 2.58 + print "Error creating block interface" 2.59 + print "Error type: " + xend_response['error_type'] 2.60 + if xend_response['error_type'] == 'exception': 2.61 + print "Exception type: " + xend_response['exception_type'] 2.62 + print "Exception val: " + xend_response['exception_value'] 2.63 + xc.domain_destroy ( dom=id ) 2.64 + sys.exit() 2.65 2.66 for ( uname, virt_name, rw ) in vbd_list: 2.67 virt_dev = xenctl.utils.blkdev_name_to_number( virt_name ) 2.68 @@ -273,42 +294,70 @@ def make_domain(): 2.69 xc.domain_destroy ( dom=id ) 2.70 sys.exit() 2.71 2.72 - # check that setting up this VBD won't violate the sharing 2.73 - # allowed by the current VBD expertise level 2.74 - if xenctl.utils.vd_extents_validate(segments, rw=='w' or rw=='rw') < 0: 2.75 - xc.domain_destroy( dom = id ) 2.76 - sys.exit() 2.77 + if new_io_world: 2.78 + if len(segments) > 1: 2.79 + print "New I/O world cannot deal with multi-extent vdisks" 2.80 + xc.domain_destroy ( dom=id ) 2.81 + sys.exit() 2.82 + seg = segments[0] 2.83 + cmsg = 'new_block_device(dom=' + str(id) + \ 2.84 + ',handle=0,vdev=' + str(virt_dev) + \ 2.85 + ',pdev=' + str(seg['device']) + \ 2.86 + ',start_sect=' + str(seg['start_sector']) + \ 2.87 + ',nr_sect=' + str(seg['nr_sectors']) + \ 2.88 + ',readonly=' + str(not re.match('w',rw)) + ')' 2.89 + xend_response = xenctl.utils.xend_control_message(cmsg) 2.90 + if not xend_response['success']: 2.91 + print "Error creating virtual block device" 2.92 + print "Error type: " + xend_response['error_type'] 2.93 + if xend_response['error_type'] == 'exception': 2.94 + print "Exception type: " + xend_response['exception_type'] 2.95 + print "Exception val: " + xend_response['exception_value'] 2.96 + xc.domain_destroy ( dom=id ) 2.97 + sys.exit() 2.98 + else: 2.99 + # check that setting up this VBD won't violate the sharing 2.100 + # allowed by the current VBD expertise level 2.101 + if xenctl.utils.vd_extents_validate(segments, 2.102 + rw=='w' or rw=='rw') < 0: 2.103 + xc.domain_destroy( dom = id ) 2.104 + sys.exit() 2.105 2.106 - if xc.vbd_create( dom=id, vbd=virt_dev, writeable= rw=='w' or rw=='rw' ): 2.107 - print "Error creating VBD vbd=%d writeable=%d\n" % (virt_dev,rw) 2.108 - xc.domain_destroy ( dom=id ) 2.109 - sys.exit() 2.110 + if xc.vbd_create( dom=id, vbd=virt_dev, 2.111 + writeable= rw=='w' or rw=='rw' ): 2.112 + print "Error creating VBD %d (writeable=%d)\n" % (virt_dev,rw) 2.113 + xc.domain_destroy ( dom=id ) 2.114 + sys.exit() 2.115 2.116 - if xc.vbd_setextents( dom=id, 2.117 - vbd=virt_dev, 2.118 - extents=segments): 2.119 - print "Error populating VBD vbd=%d\n" % virt_dev 2.120 - xc.domain_destroy ( dom=id ) 2.121 - sys.exit() 2.122 + if xc.vbd_setextents( dom=id, 2.123 + vbd=virt_dev, 2.124 + extents=segments): 2.125 + print "Error populating VBD vbd=%d\n" % virt_dev 2.126 + xc.domain_destroy ( dom=id ) 2.127 + sys.exit() 2.128 2.129 - # setup virtual firewall rules for all aliases 2.130 - for ip in vfr_ipaddr: 2.131 - xenctl.utils.setup_vfr_rules_for_vif( id, 0, ip ) 2.132 + if not new_io_world: 2.133 + # setup virtual firewall rules for all aliases 2.134 + for ip in vfr_ipaddr: 2.135 + xenctl.utils.setup_vfr_rules_for_vif( id, 0, ip ) 2.136 2.137 - # check for physical device access 2.138 - for (pci_bus, pci_dev, pci_func) in pci_device_list: 2.139 - if xc.physdev_pci_access_modify( 2.140 - dom=id, bus=pci_bus, dev=pci_dev, func=pci_func, enable=1 ) < 0: 2.141 - print "Non-fatal error enabling PCI device access." 2.142 - else: 2.143 - print "Enabled PCI access (%d:%d:%d)." % (pci_bus,pci_dev,pci_func) 2.144 + if new_io_world: 2.145 + # check for physical device access 2.146 + for (pci_bus, pci_dev, pci_func) in pci_device_list: 2.147 + if xc.physdev_pci_access_modify( 2.148 + dom=id, bus=pci_bus, dev=pci_dev, 2.149 + 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)." % \ 2.153 + (pci_bus,pci_dev,pci_func) 2.154 2.155 if xc.domain_start( dom=id ) < 0: 2.156 print "Error starting domain" 2.157 xc.domain_destroy ( dom=id ) 2.158 sys.exit() 2.159 2.160 - return (id, xend_response['console_port']) 2.161 + return (id, cons_response['console_port']) 2.162 # end of make_domain() 2.163 2.164 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:46:01 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 Thu Apr 29 15:36:38 2004 +0000 4.2 +++ b/tools/xend/lib/console.py Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 5.2 +++ b/tools/xend/lib/domain_controller.h Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 6.2 +++ b/tools/xend/lib/main.py Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 7.2 +++ b/tools/xend/lib/manager.py Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 8.2 +++ b/xen/common/event_channel.c Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 9.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/common.h Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 10.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/control.c Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 11.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/interface.c Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 12.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 13.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/vbd.c Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 14.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/main.c Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 15.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/frontend/vbd.c Fri Apr 30 15:46:01 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 Thu Apr 29 15:36:38 2004 +0000 16.2 +++ b/xenolinux-2.4.26-sparse/include/asm-xen/io.h Fri Apr 30 15:46:01 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