direct-io.hg

changeset 1035:8b679d77790f

bitkeeper revision 1.674 (4006e662w0P_G2ebTRx5hqQilMAXTw)

rbtree.h, rbtree.c:
new file
Many files:
Cleanups to new VBD mechanisms.
author kaf24@scramble.cl.cam.ac.uk
date Thu Jan 15 19:13:38 2004 +0000 (2004-01-15)
parents 0ab2028bc982
children 7c6c07befbdc
files .rootkeys xen/common/domain.c xen/common/rbtree.c xen/drivers/block/xen_block.c xen/drivers/block/xen_vbd.c xen/drivers/ide/ide-xeno.c xen/drivers/scsi/sd.c xen/include/xeno/multiboot.h xen/include/xeno/rbtree.h xen/include/xeno/sched.h xen/include/xeno/vbd.h xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_block.c xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_block.h xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_vbd.c xenolinux-2.4.24-sparse/include/asm-xeno/hypervisor.h
line diff
     1.1 --- a/.rootkeys	Wed Jan 14 18:05:25 2004 +0000
     1.2 +++ b/.rootkeys	Thu Jan 15 19:13:38 2004 +0000
     1.3 @@ -134,6 +134,7 @@ 3ddb79bdS39UXxUtZnaScie83-7VTQ xen/commo
     1.4  3ddb79bdN51qpRC-6bOH-v5hl_AK6A xen/common/network.c
     1.5  3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c
     1.6  3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
     1.7 +4006e659i9j-doVxY7DKOGU4XVin1Q xen/common/rbtree.c
     1.8  3ddb79bdHqdQpATqC0rmUZNbsb6L6A xen/common/resource.c
     1.9  3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
    1.10  3ddb79bdB9RNMnkQnUyZ5C9hhMSQQw xen/common/slab.c
    1.11 @@ -461,6 +462,7 @@ 3ddb79c0MOVXq8qZDQRGb6z64_xAwg xen/inclu
    1.12  3e54c38dlSCVdyVM4PKcrSfzLLxWUQ xen/include/xeno/perfc.h
    1.13  3e54c38de9SUSYSAwxDf_DwkpAnQFA xen/include/xeno/perfc_defn.h
    1.14  3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xeno/prefetch.h
    1.15 +4006e65fWMwLqcocgik6wbF0Eeh0Og xen/include/xeno/rbtree.h
    1.16  3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h
    1.17  3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h
    1.18  3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h
     2.1 --- a/xen/common/domain.c	Wed Jan 14 18:05:25 2004 +0000
     2.2 +++ b/xen/common/domain.c	Thu Jan 15 19:13:38 2004 +0000
     2.3 @@ -542,6 +542,11 @@ int setup_guestos(struct task_struct *p,
     2.4      l1_pgentry_t *l1tab = NULL, *l1start = NULL;
     2.5      struct pfn_info *page = NULL;
     2.6  
     2.7 +    extern void ide_probe_devices(xen_disk_info_t *);
     2.8 +    extern void scsi_probe_devices(xen_disk_info_t *);
     2.9 +    xen_disk_info_t xdi;
    2.10 +    xen_disk_t *xd;
    2.11 +
    2.12      /* Sanity! */
    2.13      if ( p->domain != 0 ) BUG();
    2.14      if ( (p->flags & PF_CONSTRUCTED) ) BUG();
    2.15 @@ -771,6 +776,27 @@ int setup_guestos(struct task_struct *p,
    2.16      write_cr3_counted(pagetable_val(current->mm.pagetable));
    2.17      __sti();
    2.18  
    2.19 +    /* DOM0 gets access to all real block devices. */
    2.20 +#define MAX_REAL_DISKS 256
    2.21 +    xd = kmalloc(MAX_REAL_DISKS * sizeof(xen_disk_t), GFP_KERNEL);
    2.22 +    xdi.max   = MAX_REAL_DISKS;
    2.23 +    xdi.count = 0;
    2.24 +    xdi.disks = xd;
    2.25 +    ide_probe_devices(&xdi);
    2.26 +    scsi_probe_devices(&xdi);
    2.27 +    for ( i = 0; i < xdi.count; i++ )
    2.28 +    {
    2.29 +        xen_extent_t e;
    2.30 +        e.device       = xd[i].device;
    2.31 +        e.start_sector = 0;
    2.32 +        e.nr_sectors   = xd[i].capacity;
    2.33 +        if ( (__vbd_create(p, xd[i].device, VBD_MODE_R|VBD_MODE_W, 
    2.34 +                           xd[i].info) != 0) ||
    2.35 +             (__vbd_grow(p, xd[i].device, &e) != 0) )
    2.36 +            BUG();
    2.37 +    }
    2.38 +    kfree(xd);
    2.39 +
    2.40      p->flags |= PF_CONSTRUCTED;
    2.41  
    2.42      new_thread(p, 
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/common/rbtree.c	Thu Jan 15 19:13:38 2004 +0000
     3.3 @@ -0,0 +1,295 @@
     3.4 +/*
     3.5 +  Red Black Trees
     3.6 +  (C) 1999  Andrea Arcangeli <andrea@suse.de>
     3.7 +  
     3.8 +  This program is free software; you can redistribute it and/or modify
     3.9 +  it under the terms of the GNU General Public License as published by
    3.10 +  the Free Software Foundation; either version 2 of the License, or
    3.11 +  (at your option) any later version.
    3.12 +
    3.13 +  This program is distributed in the hope that it will be useful,
    3.14 +  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.16 +  GNU General Public License for more details.
    3.17 +
    3.18 +  You should have received a copy of the GNU General Public License
    3.19 +  along with this program; if not, write to the Free Software
    3.20 +  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.21 +
    3.22 +  linux/lib/rbtree.c
    3.23 +*/
    3.24 +
    3.25 +#include <xeno/rbtree.h>
    3.26 +
    3.27 +static void __rb_rotate_left(rb_node_t * node, rb_root_t * root)
    3.28 +{
    3.29 +	rb_node_t * right = node->rb_right;
    3.30 +
    3.31 +	if ((node->rb_right = right->rb_left))
    3.32 +		right->rb_left->rb_parent = node;
    3.33 +	right->rb_left = node;
    3.34 +
    3.35 +	if ((right->rb_parent = node->rb_parent))
    3.36 +	{
    3.37 +		if (node == node->rb_parent->rb_left)
    3.38 +			node->rb_parent->rb_left = right;
    3.39 +		else
    3.40 +			node->rb_parent->rb_right = right;
    3.41 +	}
    3.42 +	else
    3.43 +		root->rb_node = right;
    3.44 +	node->rb_parent = right;
    3.45 +}
    3.46 +
    3.47 +static void __rb_rotate_right(rb_node_t * node, rb_root_t * root)
    3.48 +{
    3.49 +	rb_node_t * left = node->rb_left;
    3.50 +
    3.51 +	if ((node->rb_left = left->rb_right))
    3.52 +		left->rb_right->rb_parent = node;
    3.53 +	left->rb_right = node;
    3.54 +
    3.55 +	if ((left->rb_parent = node->rb_parent))
    3.56 +	{
    3.57 +		if (node == node->rb_parent->rb_right)
    3.58 +			node->rb_parent->rb_right = left;
    3.59 +		else
    3.60 +			node->rb_parent->rb_left = left;
    3.61 +	}
    3.62 +	else
    3.63 +		root->rb_node = left;
    3.64 +	node->rb_parent = left;
    3.65 +}
    3.66 +
    3.67 +void rb_insert_color(rb_node_t * node, rb_root_t * root)
    3.68 +{
    3.69 +	rb_node_t * parent, * gparent;
    3.70 +
    3.71 +	while ((parent = node->rb_parent) && parent->rb_color == RB_RED)
    3.72 +	{
    3.73 +		gparent = parent->rb_parent;
    3.74 +
    3.75 +		if (parent == gparent->rb_left)
    3.76 +		{
    3.77 +			{
    3.78 +				register rb_node_t * uncle = gparent->rb_right;
    3.79 +				if (uncle && uncle->rb_color == RB_RED)
    3.80 +				{
    3.81 +					uncle->rb_color = RB_BLACK;
    3.82 +					parent->rb_color = RB_BLACK;
    3.83 +					gparent->rb_color = RB_RED;
    3.84 +					node = gparent;
    3.85 +					continue;
    3.86 +				}
    3.87 +			}
    3.88 +
    3.89 +			if (parent->rb_right == node)
    3.90 +			{
    3.91 +				register rb_node_t * tmp;
    3.92 +				__rb_rotate_left(parent, root);
    3.93 +				tmp = parent;
    3.94 +				parent = node;
    3.95 +				node = tmp;
    3.96 +			}
    3.97 +
    3.98 +			parent->rb_color = RB_BLACK;
    3.99 +			gparent->rb_color = RB_RED;
   3.100 +			__rb_rotate_right(gparent, root);
   3.101 +		} else {
   3.102 +			{
   3.103 +				register rb_node_t * uncle = gparent->rb_left;
   3.104 +				if (uncle && uncle->rb_color == RB_RED)
   3.105 +				{
   3.106 +					uncle->rb_color = RB_BLACK;
   3.107 +					parent->rb_color = RB_BLACK;
   3.108 +					gparent->rb_color = RB_RED;
   3.109 +					node = gparent;
   3.110 +					continue;
   3.111 +				}
   3.112 +			}
   3.113 +
   3.114 +			if (parent->rb_left == node)
   3.115 +			{
   3.116 +				register rb_node_t * tmp;
   3.117 +				__rb_rotate_right(parent, root);
   3.118 +				tmp = parent;
   3.119 +				parent = node;
   3.120 +				node = tmp;
   3.121 +			}
   3.122 +
   3.123 +			parent->rb_color = RB_BLACK;
   3.124 +			gparent->rb_color = RB_RED;
   3.125 +			__rb_rotate_left(gparent, root);
   3.126 +		}
   3.127 +	}
   3.128 +
   3.129 +	root->rb_node->rb_color = RB_BLACK;
   3.130 +}
   3.131 +EXPORT_SYMBOL(rb_insert_color);
   3.132 +
   3.133 +static void __rb_erase_color(rb_node_t * node, rb_node_t * parent,
   3.134 +			     rb_root_t * root)
   3.135 +{
   3.136 +	rb_node_t * other;
   3.137 +
   3.138 +	while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node)
   3.139 +	{
   3.140 +		if (parent->rb_left == node)
   3.141 +		{
   3.142 +			other = parent->rb_right;
   3.143 +			if (other->rb_color == RB_RED)
   3.144 +			{
   3.145 +				other->rb_color = RB_BLACK;
   3.146 +				parent->rb_color = RB_RED;
   3.147 +				__rb_rotate_left(parent, root);
   3.148 +				other = parent->rb_right;
   3.149 +			}
   3.150 +			if ((!other->rb_left ||
   3.151 +			     other->rb_left->rb_color == RB_BLACK)
   3.152 +			    && (!other->rb_right ||
   3.153 +				other->rb_right->rb_color == RB_BLACK))
   3.154 +			{
   3.155 +				other->rb_color = RB_RED;
   3.156 +				node = parent;
   3.157 +				parent = node->rb_parent;
   3.158 +			}
   3.159 +			else
   3.160 +			{
   3.161 +				if (!other->rb_right ||
   3.162 +				    other->rb_right->rb_color == RB_BLACK)
   3.163 +				{
   3.164 +					register rb_node_t * o_left;
   3.165 +					if ((o_left = other->rb_left))
   3.166 +						o_left->rb_color = RB_BLACK;
   3.167 +					other->rb_color = RB_RED;
   3.168 +					__rb_rotate_right(other, root);
   3.169 +					other = parent->rb_right;
   3.170 +				}
   3.171 +				other->rb_color = parent->rb_color;
   3.172 +				parent->rb_color = RB_BLACK;
   3.173 +				if (other->rb_right)
   3.174 +					other->rb_right->rb_color = RB_BLACK;
   3.175 +				__rb_rotate_left(parent, root);
   3.176 +				node = root->rb_node;
   3.177 +				break;
   3.178 +			}
   3.179 +		}
   3.180 +		else
   3.181 +		{
   3.182 +			other = parent->rb_left;
   3.183 +			if (other->rb_color == RB_RED)
   3.184 +			{
   3.185 +				other->rb_color = RB_BLACK;
   3.186 +				parent->rb_color = RB_RED;
   3.187 +				__rb_rotate_right(parent, root);
   3.188 +				other = parent->rb_left;
   3.189 +			}
   3.190 +			if ((!other->rb_left ||
   3.191 +			     other->rb_left->rb_color == RB_BLACK)
   3.192 +			    && (!other->rb_right ||
   3.193 +				other->rb_right->rb_color == RB_BLACK))
   3.194 +			{
   3.195 +				other->rb_color = RB_RED;
   3.196 +				node = parent;
   3.197 +				parent = node->rb_parent;
   3.198 +			}
   3.199 +			else
   3.200 +			{
   3.201 +				if (!other->rb_left ||
   3.202 +				    other->rb_left->rb_color == RB_BLACK)
   3.203 +				{
   3.204 +					register rb_node_t * o_right;
   3.205 +					if ((o_right = other->rb_right))
   3.206 +						o_right->rb_color = RB_BLACK;
   3.207 +					other->rb_color = RB_RED;
   3.208 +					__rb_rotate_left(other, root);
   3.209 +					other = parent->rb_left;
   3.210 +				}
   3.211 +				other->rb_color = parent->rb_color;
   3.212 +				parent->rb_color = RB_BLACK;
   3.213 +				if (other->rb_left)
   3.214 +					other->rb_left->rb_color = RB_BLACK;
   3.215 +				__rb_rotate_right(parent, root);
   3.216 +				node = root->rb_node;
   3.217 +				break;
   3.218 +			}
   3.219 +		}
   3.220 +	}
   3.221 +	if (node)
   3.222 +		node->rb_color = RB_BLACK;
   3.223 +}
   3.224 +
   3.225 +void rb_erase(rb_node_t * node, rb_root_t * root)
   3.226 +{
   3.227 +	rb_node_t * child, * parent;
   3.228 +	int color;
   3.229 +
   3.230 +	if (!node->rb_left)
   3.231 +		child = node->rb_right;
   3.232 +	else if (!node->rb_right)
   3.233 +		child = node->rb_left;
   3.234 +	else
   3.235 +	{
   3.236 +		rb_node_t * old = node, * left;
   3.237 +
   3.238 +		node = node->rb_right;
   3.239 +		while ((left = node->rb_left))
   3.240 +			node = left;
   3.241 +		child = node->rb_right;
   3.242 +		parent = node->rb_parent;
   3.243 +		color = node->rb_color;
   3.244 +
   3.245 +		if (child)
   3.246 +			child->rb_parent = parent;
   3.247 +		if (parent)
   3.248 +		{
   3.249 +			if (parent->rb_left == node)
   3.250 +				parent->rb_left = child;
   3.251 +			else
   3.252 +				parent->rb_right = child;
   3.253 +		}
   3.254 +		else
   3.255 +			root->rb_node = child;
   3.256 +
   3.257 +		if (node->rb_parent == old)
   3.258 +			parent = node;
   3.259 +		node->rb_parent = old->rb_parent;
   3.260 +		node->rb_color = old->rb_color;
   3.261 +		node->rb_right = old->rb_right;
   3.262 +		node->rb_left = old->rb_left;
   3.263 +
   3.264 +		if (old->rb_parent)
   3.265 +		{
   3.266 +			if (old->rb_parent->rb_left == old)
   3.267 +				old->rb_parent->rb_left = node;
   3.268 +			else
   3.269 +				old->rb_parent->rb_right = node;
   3.270 +		} else
   3.271 +			root->rb_node = node;
   3.272 +
   3.273 +		old->rb_left->rb_parent = node;
   3.274 +		if (old->rb_right)
   3.275 +			old->rb_right->rb_parent = node;
   3.276 +		goto color;
   3.277 +	}
   3.278 +
   3.279 +	parent = node->rb_parent;
   3.280 +	color = node->rb_color;
   3.281 +
   3.282 +	if (child)
   3.283 +		child->rb_parent = parent;
   3.284 +	if (parent)
   3.285 +	{
   3.286 +		if (parent->rb_left == node)
   3.287 +			parent->rb_left = child;
   3.288 +		else
   3.289 +			parent->rb_right = child;
   3.290 +	}
   3.291 +	else
   3.292 +		root->rb_node = child;
   3.293 +
   3.294 + color:
   3.295 +	if (color == RB_BLACK)
   3.296 +		__rb_erase_color(child, parent, root);
   3.297 +}
   3.298 +EXPORT_SYMBOL(rb_erase);
     4.1 --- a/xen/drivers/block/xen_block.c	Wed Jan 14 18:05:25 2004 +0000
     4.2 +++ b/xen/drivers/block/xen_block.c	Thu Jan 15 19:13:38 2004 +0000
     4.3 @@ -287,7 +287,7 @@ long do_block_io_op(block_io_op_t *u_blo
     4.4  	/* query VBD information for self or others (or all) */
     4.5  	if ( (ret = vbd_probe(&op.u.probe_params)) == 0 )
     4.6  	    copy_to_user(u_block_io_op, &op, sizeof(op)); 
     4.7 -	break; 
     4.8 +	break;
     4.9  
    4.10      case BLOCK_IO_OP_VBD_INFO: 
    4.11  	/* query information about a particular VBD */
    4.12 @@ -449,21 +449,15 @@ static void dispatch_rw_block_io(struct 
    4.13  	phys_seg[nr_psegs].nr_sects      = nr_sects;
    4.14  
    4.15          /* Translate the request into the relevant 'physical device' */
    4.16 -	new_segs = vbd_translate(&phys_seg[nr_psegs], p, operation); 
    4.17 -
    4.18 -	/* If it fails we bail (unless the caller is privileged). */
    4.19 +	new_segs = vbd_translate(&phys_seg[nr_psegs], p, operation);
    4.20  	if ( new_segs < 0 )
    4.21          { 
    4.22 -            if ( unlikely(new_segs != -ENODEV) || unlikely(!IS_PRIV(p)) )
    4.23 -            {
    4.24 -                DPRINTK("access denied: %s of [%ld,%ld] on dev=%04x\n", 
    4.25 -                        operation == READ ? "read" : "write", 
    4.26 -                        req->sector_number + tot_sects, 
    4.27 -                        req->sector_number + tot_sects + nr_sects, 
    4.28 -                        req->device); 
    4.29 -                goto bad_descriptor;
    4.30 -            }
    4.31 -            new_segs = 1;
    4.32 +            DPRINTK("access denied: %s of [%ld,%ld] on dev=%04x\n", 
    4.33 +                    operation == READ ? "read" : "write", 
    4.34 +                    req->sector_number + tot_sects, 
    4.35 +                    req->sector_number + tot_sects + nr_sects, 
    4.36 +                    req->device); 
    4.37 +            goto bad_descriptor;
    4.38          }
    4.39  	 
    4.40          nr_psegs += new_segs;
     5.1 --- a/xen/drivers/block/xen_vbd.c	Wed Jan 14 18:05:25 2004 +0000
     5.2 +++ b/xen/drivers/block/xen_vbd.c	Thu Jan 15 19:13:38 2004 +0000
     5.3 @@ -1,5 +1,9 @@
     5.4 -/*
     5.5 - * xen_vbd.c : routines for managing virtual block devices 
     5.6 +/******************************************************************************
     5.7 + * xen_vbd.c
     5.8 + * 
     5.9 + * Routines for managing virtual block devices.
    5.10 + * 
    5.11 + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
    5.12   */
    5.13  
    5.14  #include <xeno/config.h>
    5.15 @@ -17,29 +21,67 @@
    5.16  #include <hypervisor-ifs/hypervisor-if.h>
    5.17  #include <xeno/event.h>
    5.18  
    5.19 -/* 
    5.20 -** XXX SMH: the below probe functions /append/ their info to the 
    5.21 -** xdi array; i.e.  they assume that all earlier slots are correctly 
    5.22 -** filled, and that xdi->count points to the first  free entry in 
    5.23 -** the array. All kinda gross but it'll do for now.  
    5.24 -*/
    5.25 -extern int ide_probe_devices(xen_disk_info_t *xdi);
    5.26 -extern int scsi_probe_devices(xen_disk_info_t *xdi);
    5.27 +long __vbd_create(struct task_struct *p,
    5.28 +                  unsigned short vdevice,
    5.29 +                  unsigned char mode,
    5.30 +                  unsigned char type)
    5.31 +{
    5.32 +    vbd_t *vbd; 
    5.33 +    rb_node_t **rb_p, *rb_parent = NULL;
    5.34 +    long ret = 0;
    5.35 +    unsigned long cpu_mask;
    5.36 +
    5.37 +    spin_lock(&p->vbd_lock);
    5.38  
    5.39 -/* XXX SMH: crappy 'hash function' .. fix when care. */
    5.40 -#define HSH(_x) ((_x) & (VBD_HTAB_SZ - 1))
    5.41 +    rb_p = &p->vbd_rb.rb_node;
    5.42 +    while ( *rb_p != NULL )
    5.43 +    {
    5.44 +        rb_parent = *rb_p;
    5.45 +        vbd = rb_entry(rb_parent, vbd_t, rb);
    5.46 +        if ( vdevice < vbd->vdevice )
    5.47 +        {
    5.48 +            rb_p = &rb_parent->rb_left;
    5.49 +        }
    5.50 +        else if ( vdevice > vbd->vdevice )
    5.51 +        {
    5.52 +            rb_p = &rb_parent->rb_right;
    5.53 +        }
    5.54 +        else
    5.55 +        {
    5.56 +            DPRINTK("vbd_create attempted for already existing vbd\n");
    5.57 +            ret = -EINVAL;
    5.58 +            goto out;
    5.59 +        }
    5.60 +    }
    5.61 +
    5.62 +    if ( unlikely((vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) )
    5.63 +    {
    5.64 +        DPRINTK("vbd_create: out of memory\n");
    5.65 +        ret = -ENOMEM;
    5.66 +        goto out;
    5.67 +    }
    5.68 +
    5.69 +    vbd->vdevice = vdevice; 
    5.70 +    vbd->mode    = mode; 
    5.71 +    vbd->type    = type;
    5.72 +    vbd->extents = NULL; 
    5.73 +
    5.74 +    rb_link_node(&vbd->rb, rb_parent, rb_p);
    5.75 +    rb_insert_color(&vbd->rb, &p->vbd_rb);
    5.76 +
    5.77 +    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
    5.78 +    guest_event_notify(cpu_mask);
    5.79 +
    5.80 + out:
    5.81 +    spin_unlock(&p->vbd_lock);
    5.82 +    return ret; 
    5.83 +}
    5.84  
    5.85  
    5.86 -/* 
    5.87 -** Create a new VBD; all this involves is adding an entry to the domain's
    5.88 -** vbd hash table; caller must be privileged. 
    5.89 -*/
    5.90  long vbd_create(vbd_create_t *create) 
    5.91  {
    5.92 -    struct task_struct *p; 
    5.93 -    vbd_t *new_vbd, **pv; 
    5.94 -    long ret = 0;
    5.95 -    unsigned long cpu_mask;
    5.96 +    struct task_struct *p;
    5.97 +    long rc;
    5.98  
    5.99      if ( unlikely(!IS_PRIV(current)) )
   5.100          return -EPERM;
   5.101 @@ -47,58 +89,81 @@ long vbd_create(vbd_create_t *create)
   5.102      if ( unlikely((p = find_domain_by_id(create->domain)) == NULL) )
   5.103      {
   5.104          DPRINTK("vbd_create attempted for non-existent domain %d\n", 
   5.105 -                create->domain); 
   5.106 +                domain); 
   5.107          return -EINVAL; 
   5.108      }
   5.109  
   5.110 +    rc = __vbd_create(p, create->vdevice, create->mode,
   5.111 +                      XD_TYPE_DISK | XD_FLAG_VIRT);
   5.112 +
   5.113 +    put_task_struct(p);
   5.114 +
   5.115 +    return rc;
   5.116 +}
   5.117 +
   5.118 +
   5.119 +long __vbd_grow(struct task_struct *p,
   5.120 +                unsigned short vdevice,
   5.121 +                xen_extent_t *extent)
   5.122 +{
   5.123 +    xen_extent_le_t **px, *x; 
   5.124 +    vbd_t *vbd = NULL;
   5.125 +    rb_node_t *rb;
   5.126 +    long ret = 0;
   5.127 +    unsigned long cpu_mask;
   5.128 +
   5.129      spin_lock(&p->vbd_lock);
   5.130  
   5.131 -    for ( pv = &p->vbdtab[HSH(create->vdevice)]; 
   5.132 -          *pv != NULL; 
   5.133 -          pv = &(*pv)->next ) 
   5.134 +    rb = p->vbd_rb.rb_node;
   5.135 +    while ( rb != NULL )
   5.136      {
   5.137 -        if ( unlikely((*pv)->vdevice == create->vdevice) )
   5.138 -        {
   5.139 -            DPRINTK("vbd_create attempted for already existing vbd\n");
   5.140 -            ret = -EINVAL;
   5.141 -            goto out;
   5.142 -        }
   5.143 -        if ( (*pv)->vdevice > create->vdevice )
   5.144 +        vbd = rb_entry(rb, vbd_t, rb);
   5.145 +        if ( vdevice < vbd->vdevice )
   5.146 +            rb = rb->rb_left;
   5.147 +        else if ( vdevice > vbd->vdevice )
   5.148 +            rb = rb->rb_right;
   5.149 +        else
   5.150              break;
   5.151      }
   5.152  
   5.153 -    if ( unlikely((new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) )
   5.154 +    if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != vdevice) )
   5.155      {
   5.156 -        DPRINTK("vbd_create: out of memory\n");
   5.157 +        DPRINTK("vbd_grow: attempted to append extent to non-existent VBD.\n");
   5.158 +        ret = -EINVAL;
   5.159 +        goto out;
   5.160 +    } 
   5.161 +
   5.162 +    if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL)) == NULL) )
   5.163 +    {
   5.164 +        DPRINTK("vbd_grow: out of memory\n");
   5.165          ret = -ENOMEM;
   5.166          goto out;
   5.167      }
   5.168 + 
   5.169 +    x->extent.device       = extent->device; 
   5.170 +    x->extent.start_sector = extent->start_sector; 
   5.171 +    x->extent.nr_sectors   = extent->nr_sectors; 
   5.172 +    x->next                = (xen_extent_le_t *)NULL; 
   5.173  
   5.174 -    new_vbd->vdevice = create->vdevice; 
   5.175 -    new_vbd->mode    = create->mode; 
   5.176 -    new_vbd->extents = NULL; 
   5.177 -    new_vbd->next    = *pv; 
   5.178 +    for ( px = &vbd->extents; *px != NULL; px = &(*px)->next ) 
   5.179 +        continue;
   5.180  
   5.181 -    *pv = new_vbd;
   5.182 +    *px = x;
   5.183  
   5.184      cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   5.185      guest_event_notify(cpu_mask);
   5.186  
   5.187   out:
   5.188      spin_unlock(&p->vbd_lock);
   5.189 -    put_task_struct(p);
   5.190 -    return ret; 
   5.191 +    return ret;
   5.192  }
   5.193  
   5.194  
   5.195  /* Grow a VBD by appending a new extent. Fails if the VBD doesn't exist. */
   5.196  long vbd_grow(vbd_grow_t *grow) 
   5.197  {
   5.198 -    struct task_struct *p; 
   5.199 -    xen_extent_le_t **px, *x; 
   5.200 -    vbd_t *v; 
   5.201 -    long ret = 0;
   5.202 -    unsigned long cpu_mask;
   5.203 +    struct task_struct *p;
   5.204 +    long rc;
   5.205  
   5.206      if ( unlikely(!IS_PRIV(current)) )
   5.207          return -EPERM; 
   5.208 @@ -110,43 +175,11 @@ long vbd_grow(vbd_grow_t *grow)
   5.209          return -EINVAL; 
   5.210      }
   5.211  
   5.212 -    spin_lock(&p->vbd_lock);
   5.213 -
   5.214 -    for ( v = p->vbdtab[HSH(grow->vdevice)]; v != NULL; v = v->next ) 
   5.215 -        if ( v->vdevice == grow->vdevice )
   5.216 -            break; 
   5.217 -
   5.218 -    if ( unlikely(v == NULL) )
   5.219 -    {
   5.220 -        DPRINTK("vbd_grow: attempted to append extent to non-existent VBD.\n");
   5.221 -        ret = -EINVAL;
   5.222 -        goto out; 
   5.223 -    }
   5.224 +    rc = __vbd_grow(p, grow->vdevice, &grow->extent);
   5.225  
   5.226 -    if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL)) == NULL) )
   5.227 -    {
   5.228 -        DPRINTK("vbd_grow: out of memory\n");
   5.229 -        ret = -ENOMEM;
   5.230 -        goto out;
   5.231 -    }
   5.232 - 
   5.233 -    x->extent.device       = grow->extent.device; 
   5.234 -    x->extent.start_sector = grow->extent.start_sector; 
   5.235 -    x->extent.nr_sectors   = grow->extent.nr_sectors; 
   5.236 -    x->next                = (xen_extent_le_t *)NULL; 
   5.237 +    put_task_struct(p);
   5.238  
   5.239 -    for ( px = &v->extents; *px != NULL; px = &(*px)->next ) 
   5.240 -        continue;
   5.241 -
   5.242 -    *px = x;
   5.243 -
   5.244 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   5.245 -    guest_event_notify(cpu_mask);
   5.246 -
   5.247 - out:
   5.248 -    spin_unlock(&p->vbd_lock);
   5.249 -    put_task_struct(p);
   5.250 -    return ret;
   5.251 +    return rc;
   5.252  }
   5.253  
   5.254  
   5.255 @@ -154,7 +187,8 @@ long vbd_shrink(vbd_shrink_t *shrink)
   5.256  {
   5.257      struct task_struct *p; 
   5.258      xen_extent_le_t **px, *x; 
   5.259 -    vbd_t *v; 
   5.260 +    vbd_t *vbd = NULL;
   5.261 +    rb_node_t *rb;
   5.262      long ret = 0;
   5.263      unsigned long cpu_mask;
   5.264  
   5.265 @@ -170,11 +204,21 @@ long vbd_shrink(vbd_shrink_t *shrink)
   5.266  
   5.267      spin_lock(&p->vbd_lock);
   5.268  
   5.269 -    for ( v = p->vbdtab[HSH(shrink->vdevice)]; v != NULL; v = v->next ) 
   5.270 -        if ( v->vdevice == shrink->vdevice )
   5.271 -            break; 
   5.272 +    rb = p->vbd_rb.rb_node;
   5.273 +    while ( rb != NULL )
   5.274 +    {
   5.275 +        vbd = rb_entry(rb, vbd_t, rb);
   5.276 +        if ( shrink->vdevice < vbd->vdevice )
   5.277 +            rb = rb->rb_left;
   5.278 +        else if ( shrink->vdevice > vbd->vdevice )
   5.279 +            rb = rb->rb_right;
   5.280 +        else
   5.281 +            break;
   5.282 +    }
   5.283  
   5.284 -    if ( unlikely(v == NULL) || unlikely(v->extents == NULL) )
   5.285 +    if ( unlikely(vbd == NULL) || 
   5.286 +         unlikely(vbd->vdevice != shrink->vdevice) ||
   5.287 +         unlikely(vbd->extents == NULL) )
   5.288      {
   5.289          DPRINTK("vbd_shrink: attempt to remove non-existent extent.\n"); 
   5.290          ret = -EINVAL;
   5.291 @@ -182,7 +226,7 @@ long vbd_shrink(vbd_shrink_t *shrink)
   5.292      }
   5.293  
   5.294      /* Find the last extent. We now know that there is at least one. */
   5.295 -    for ( px = &v->extents; (*px)->next != NULL; px = &(*px)->next )
   5.296 +    for ( px = &vbd->extents; (*px)->next != NULL; px = &(*px)->next )
   5.297          continue;
   5.298  
   5.299      x   = *px;
   5.300 @@ -204,7 +248,8 @@ long vbd_setextents(vbd_setextents_t *se
   5.301      struct task_struct *p; 
   5.302      xen_extent_t e;
   5.303      xen_extent_le_t *new_extents, *x, *t; 
   5.304 -    vbd_t *v; 
   5.305 +    vbd_t *vbd = NULL;
   5.306 +    rb_node_t *rb;
   5.307      int i;
   5.308      long ret = 0;
   5.309      unsigned long cpu_mask;
   5.310 @@ -221,11 +266,20 @@ long vbd_setextents(vbd_setextents_t *se
   5.311  
   5.312      spin_lock(&p->vbd_lock);
   5.313  
   5.314 -    for ( v = p->vbdtab[HSH(setextents->vdevice)]; v != NULL; v = v->next ) 
   5.315 -        if ( v->vdevice == setextents->vdevice )
   5.316 -            break; 
   5.317 +    rb = p->vbd_rb.rb_node;
   5.318 +    while ( rb != NULL )
   5.319 +    {
   5.320 +        vbd = rb_entry(rb, vbd_t, rb);
   5.321 +        if ( setextents->vdevice < vbd->vdevice )
   5.322 +            rb = rb->rb_left;
   5.323 +        else if ( setextents->vdevice > vbd->vdevice )
   5.324 +            rb = rb->rb_right;
   5.325 +        else
   5.326 +            break;
   5.327 +    }
   5.328  
   5.329 -    if ( unlikely(v == NULL) )
   5.330 +    if ( unlikely(vbd == NULL) || 
   5.331 +         unlikely(vbd->vdevice != setextents->vdevice) )
   5.332      {
   5.333          DPRINTK("vbd_setextents: attempt to modify non-existent VBD.\n"); 
   5.334          ret = -EINVAL;
   5.335 @@ -260,14 +314,14 @@ long vbd_setextents(vbd_setextents_t *se
   5.336      }
   5.337  
   5.338      /* Delete the old extent list _after_ successfully creating the new. */
   5.339 -    for ( x = v->extents; x != NULL; x = t )
   5.340 +    for ( x = vbd->extents; x != NULL; x = t )
   5.341      {
   5.342          t = x->next;
   5.343          kfree(x);
   5.344      }
   5.345  
   5.346      /* Make the new list visible. */
   5.347 -    v->extents = new_extents;
   5.348 +    vbd->extents = new_extents;
   5.349  
   5.350      cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   5.351      guest_event_notify(cpu_mask);
   5.352 @@ -291,7 +345,8 @@ long vbd_setextents(vbd_setextents_t *se
   5.353  long vbd_delete(vbd_delete_t *delete) 
   5.354  {
   5.355      struct task_struct *p; 
   5.356 -    vbd_t *v, **pv; 
   5.357 +    vbd_t *vbd;
   5.358 +    rb_node_t *rb;
   5.359      xen_extent_le_t *x, *t;
   5.360      unsigned long cpu_mask;
   5.361  
   5.362 @@ -307,14 +362,18 @@ long vbd_delete(vbd_delete_t *delete)
   5.363  
   5.364      spin_lock(&p->vbd_lock);
   5.365  
   5.366 -    for ( pv = &p->vbdtab[HSH(delete->vdevice)]; 
   5.367 -          *pv != NULL; 
   5.368 -          pv = &(*pv)->next ) 
   5.369 +    rb = p->vbd_rb.rb_node;
   5.370 +    while ( rb != NULL )
   5.371      {
   5.372 -        if ( (*pv)->vdevice == delete->vdevice )
   5.373 +        vbd = rb_entry(rb, vbd_t, rb);
   5.374 +        if ( delete->vdevice < vbd->vdevice )
   5.375 +            rb = rb->rb_left;
   5.376 +        else if ( delete->vdevice > vbd->vdevice )
   5.377 +            rb = rb->rb_right;
   5.378 +        else
   5.379              goto found;
   5.380      }
   5.381 -    
   5.382 +
   5.383      DPRINTK("vbd_delete attempted for non-existing VBD.\n");
   5.384  
   5.385      spin_unlock(&p->vbd_lock);
   5.386 @@ -322,10 +381,9 @@ long vbd_delete(vbd_delete_t *delete)
   5.387      return -EINVAL;
   5.388  
   5.389   found:
   5.390 -    v = *pv;
   5.391 -    *pv = v->next;
   5.392 -    x = v->extents;
   5.393 -    kfree(v);
   5.394 +    rb_erase(rb, &p->vbd_rb);
   5.395 +    x = vbd->extents;
   5.396 +    kfree(vbd);
   5.397  
   5.398      while ( x != NULL )
   5.399      {
   5.400 @@ -345,28 +403,27 @@ long vbd_delete(vbd_delete_t *delete)
   5.401  
   5.402  void destroy_all_vbds(struct task_struct *p)
   5.403  {
   5.404 -    int i;
   5.405 -    vbd_t *v; 
   5.406 +    vbd_t *vbd;
   5.407 +    rb_node_t *rb;
   5.408      xen_extent_le_t *x, *t;
   5.409      unsigned long cpu_mask;
   5.410  
   5.411      spin_lock(&p->vbd_lock);
   5.412 -    for ( i = 0; i < VBD_HTAB_SZ; i++ )
   5.413 +
   5.414 +    while ( (rb = p->vbd_rb.rb_node) != NULL )
   5.415      {
   5.416 -        while ( (v = p->vbdtab[i]) != NULL )
   5.417 +        vbd = rb_entry(rb, vbd_t, rb);
   5.418 +
   5.419 +        rb_erase(rb, &p->vbd_rb);
   5.420 +        x = vbd->extents;
   5.421 +        kfree(vbd);
   5.422 +        
   5.423 +        while ( x != NULL )
   5.424          {
   5.425 -            p->vbdtab[i] = v->next;
   5.426 -      
   5.427 -            x = v->extents;
   5.428 -            kfree(v);
   5.429 -            
   5.430 -            while ( x != NULL )
   5.431 -            {
   5.432 -                t = x->next;
   5.433 -                kfree(x);
   5.434 -                x = t;
   5.435 -            }          
   5.436 -        }
   5.437 +            t = x->next;
   5.438 +            kfree(x);
   5.439 +            x = t;
   5.440 +        }          
   5.441      }
   5.442  
   5.443      cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   5.444 @@ -376,68 +433,100 @@ void destroy_all_vbds(struct task_struct
   5.445  }
   5.446  
   5.447  
   5.448 -/*
   5.449 - * vbd_probe_devices: 
   5.450 - *
   5.451 - * add the virtual block devices for this domain to a xen_disk_info_t; 
   5.452 - * we assume xdi->count points to the first unused place in the array. 
   5.453 - */
   5.454 -static int vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p)
   5.455 +static int vbd_probe_single(xen_disk_info_t *xdi, 
   5.456 +                            vbd_t *vbd, 
   5.457 +                            struct task_struct *p)
   5.458  {
   5.459      xen_extent_le_t *x; 
   5.460      xen_disk_t cur_disk; 
   5.461 -    vbd_t *v; 
   5.462 -    int i; 
   5.463 +
   5.464 +    if ( xdi->count == xdi->max )
   5.465 +    {
   5.466 +        DPRINTK("vbd_probe_devices: out of space for probe.\n"); 
   5.467 +        return -ENOMEM; 
   5.468 +    }
   5.469 +
   5.470 +    cur_disk.device = vbd->vdevice; 
   5.471 +    cur_disk.info   = vbd->type;
   5.472 +    if ( !VBD_CAN_WRITE(vbd) )
   5.473 +        cur_disk.info |= XD_FLAG_RO; 
   5.474 +    cur_disk.capacity = 0 ; 
   5.475 +    for ( x = vbd->extents; x != NULL; x = x->next )
   5.476 +        cur_disk.capacity += x->extent.nr_sectors; 
   5.477 +    cur_disk.domain = p->domain; 
   5.478 +        
   5.479 +    /* Now copy into relevant part of user-space buffer */
   5.480 +    if( copy_to_user(&xdi->disks[xdi->count], 
   5.481 +                     &cur_disk, 
   5.482 +                     sizeof(xen_disk_t)) )
   5.483 +    { 
   5.484 +        DPRINTK("vbd_probe_devices: copy_to_user failed\n");
   5.485 +        return -EFAULT;
   5.486 +    } 
   5.487 +        
   5.488 +    xdi->count++; 
   5.489 +
   5.490 +    return 0;
   5.491 +}
   5.492 +
   5.493 +
   5.494 +static int vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p)
   5.495 +{
   5.496 +    int rc = 0;
   5.497 +    rb_node_t *rb;
   5.498  
   5.499      spin_lock(&p->vbd_lock);
   5.500  
   5.501 -    for ( i = 0; i < VBD_HTAB_SZ; i++ )
   5.502 -    { 
   5.503 -        for ( v = p->vbdtab[i]; v != NULL; v = v->next )
   5.504 -        { 
   5.505 -            if ( xdi->count == xdi->max )
   5.506 -            {
   5.507 -                DPRINTK("vbd_probe_devices: out of space for probe.\n"); 
   5.508 -                spin_unlock(&p->vbd_lock);
   5.509 -                return -ENOMEM; 
   5.510 -            }
   5.511 +    if ( (rb = p->vbd_rb.rb_node) == NULL )
   5.512 +        goto out;
   5.513 +
   5.514 + new_subtree:
   5.515 +    /* STEP 1. Find least node (it'll be left-most). */
   5.516 +    while ( rb->rb_left != NULL )
   5.517 +        rb = rb->rb_left;
   5.518 +
   5.519 +    for ( ; ; )
   5.520 +    {
   5.521 +        /* STEP 2. Dealt with left subtree. Now process current node. */
   5.522 +        if ( (rc = vbd_probe_single(xdi, rb_entry(rb, vbd_t, rb), p)) != 0 )
   5.523 +            goto out;
   5.524  
   5.525 -            cur_disk.device = v->vdevice; 
   5.526 -            cur_disk.info   = XD_FLAG_VIRT | XD_TYPE_DISK; 
   5.527 -            if ( !VBD_CAN_WRITE(v) )
   5.528 -                cur_disk.info |= XD_FLAG_RO; 
   5.529 -            cur_disk.capacity = 0 ; 
   5.530 -            for ( x = v->extents; x != NULL; x = x->next )
   5.531 -                cur_disk.capacity += x->extent.nr_sectors; 
   5.532 -            cur_disk.domain = p->domain; 
   5.533 +        /* STEP 3. Process right subtree, if any. */
   5.534 +        if ( rb->rb_right != NULL )
   5.535 +        {
   5.536 +            rb = rb->rb_right;
   5.537 +            goto new_subtree;
   5.538 +        }
   5.539  
   5.540 -            /* Now copy into relevant part of user-space buffer */
   5.541 -            if( copy_to_user(&xdi->disks[xdi->count], 
   5.542 -                             &cur_disk, 
   5.543 -                             sizeof(xen_disk_t)) )
   5.544 -            { 
   5.545 -                DPRINTK("vbd_probe_devices: copy_to_user failed\n");
   5.546 -                spin_unlock(&p->vbd_lock);
   5.547 -                return -EFAULT;
   5.548 -            } 
   5.549 -        
   5.550 -            xdi->count++; 
   5.551 +        /* STEP 4. Done both subtrees. Head back through ancesstors. */
   5.552 +        for ( ; ; ) 
   5.553 +        {
   5.554 +            /* We're done when we get back to the root node. */
   5.555 +            if ( rb->rb_parent == NULL )
   5.556 +                goto out;
   5.557 +            /* If we are left of parent, then parent is next to process. */
   5.558 +            if ( rb->rb_parent->rb_left == rb )
   5.559 +                break;
   5.560 +            /* If we are right of parent, then we climb to grandparent. */
   5.561 +            rb = rb->rb_parent;
   5.562          }
   5.563 -    } 
   5.564 +
   5.565 +        rb = rb->rb_parent;
   5.566 +    }
   5.567  
   5.568 + out:
   5.569      spin_unlock(&p->vbd_lock);
   5.570 -    return 0;  
   5.571 +    return rc;  
   5.572  }
   5.573  
   5.574  
   5.575  /*
   5.576 -** Return information about the VBDs available for a given domain, 
   5.577 -** or for all domains; in the general case the 'domain' argument 
   5.578 -** will be 0 which means "information about the caller"; otherwise
   5.579 -** the 'domain' argument will specify either a given domain, or 
   5.580 -** all domains ("VBD_PROBE_ALL") -- both of these cases require the
   5.581 -** caller to be privileged. 
   5.582 -*/
   5.583 + * Return information about the VBDs available for a given domain, or for all 
   5.584 + * domains; in the general case the 'domain' argument will be 0 which means 
   5.585 + * "information about the caller"; otherwise the 'domain' argument will 
   5.586 + * specify either a given domain, or all domains ("VBD_PROBE_ALL") -- both of 
   5.587 + * these cases require the caller to be privileged.
   5.588 + */
   5.589  long vbd_probe(vbd_probe_t *probe) 
   5.590  {
   5.591      struct task_struct *p = NULL; 
   5.592 @@ -446,7 +535,7 @@ long vbd_probe(vbd_probe_t *probe)
   5.593  
   5.594      if ( probe->domain != 0 )
   5.595      { 
   5.596 -        /* We can only probe for ourselves unless we're privileged. */
   5.597 +        /* We can only probe for ourselves (unless we're privileged). */
   5.598          if( (probe->domain != current->domain) && !IS_PRIV(current) )
   5.599              return -EPERM; 
   5.600  
   5.601 @@ -465,14 +554,6 @@ long vbd_probe(vbd_probe_t *probe)
   5.602          get_task_struct(p); /* to mirror final put_task_struct */
   5.603      }
   5.604  
   5.605 -    if ( (probe->domain == VBD_PROBE_ALL) || IS_PRIV(p) )
   5.606 -    { 
   5.607 -        /* Privileged domains always get access to the 'real' devices. */
   5.608 -        if ( ((ret = ide_probe_devices(&probe->xdi)) != 0) ||
   5.609 -             ((ret = scsi_probe_devices(&probe->xdi)) != 0) )
   5.610 -            goto out; 
   5.611 -    } 
   5.612 -
   5.613      if ( probe->domain == VBD_PROBE_ALL )
   5.614      { 
   5.615          read_lock_irqsave(&tasklist_lock, flags);
   5.616 @@ -507,7 +588,8 @@ long vbd_info(vbd_info_t *info)
   5.617      struct task_struct *p; 
   5.618      xen_extent_le_t *x; 
   5.619      xen_extent_t *extents; 
   5.620 -    vbd_t *v; 
   5.621 +    vbd_t *vbd = NULL;
   5.622 +    rb_node_t *rb;
   5.623      long ret = 0;  
   5.624     
   5.625      if ( (info->domain != current->domain) && !IS_PRIV(current) )
   5.626 @@ -522,22 +604,30 @@ long vbd_info(vbd_info_t *info)
   5.627  
   5.628      spin_lock(&p->vbd_lock);
   5.629  
   5.630 -    for ( v = p->vbdtab[HSH(info->vdevice)]; v != NULL; v = v->next ) 
   5.631 -        if ( v->vdevice == info->vdevice )
   5.632 -            break; 
   5.633 +    rb = p->vbd_rb.rb_node;
   5.634 +    while ( rb != NULL )
   5.635 +    {
   5.636 +        vbd = rb_entry(rb, vbd_t, rb);
   5.637 +        if ( info->vdevice < vbd->vdevice )
   5.638 +            rb = rb->rb_left;
   5.639 +        else if ( info->vdevice > vbd->vdevice )
   5.640 +            rb = rb->rb_right;
   5.641 +        else
   5.642 +            break;
   5.643 +    }
   5.644  
   5.645 -    if ( v == NULL )
   5.646 +    if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != info->vdevice) )
   5.647      {
   5.648          DPRINTK("vbd_info attempted on non-existent VBD.\n"); 
   5.649          ret = -EINVAL; 
   5.650          goto out; 
   5.651      }
   5.652  
   5.653 -    info->mode     = v->mode; 
   5.654 +    info->mode     = vbd->mode;
   5.655      info->nextents = 0; 
   5.656  
   5.657      extents = info->extents;
   5.658 -    for ( x = v->extents; x != NULL; x = x->next )
   5.659 +    for ( x = vbd->extents; x != NULL; x = x->next )
   5.660      {
   5.661          if ( info->nextents == info->maxextents )
   5.662              break;
   5.663 @@ -561,26 +651,34 @@ long vbd_info(vbd_info_t *info)
   5.664  int vbd_translate(phys_seg_t *pseg, struct task_struct *p, int operation)
   5.665  {
   5.666      xen_extent_le_t *x; 
   5.667 -    vbd_t *v; 
   5.668 +    vbd_t *vbd;
   5.669 +    rb_node_t *rb;
   5.670      unsigned long sec_off, nr_secs;
   5.671  
   5.672      spin_lock(&p->vbd_lock);
   5.673  
   5.674 -    for ( v = p->vbdtab[HSH(pseg->dev)]; v != NULL; v = v->next ) 
   5.675 -        if ( v->vdevice == pseg->dev )
   5.676 -            goto found; 
   5.677 +    rb = p->vbd_rb.rb_node;
   5.678 +    while ( rb != NULL )
   5.679 +    {
   5.680 +        vbd = rb_entry(rb, vbd_t, rb);
   5.681 +        if ( pseg->dev < vbd->vdevice )
   5.682 +            rb = rb->rb_left;
   5.683 +        else if ( pseg->dev > vbd->vdevice )
   5.684 +            rb = rb->rb_right;
   5.685 +        else
   5.686 +            goto found;
   5.687 +    }
   5.688  
   5.689 -    if ( unlikely(!IS_PRIV(p)) ) 
   5.690 -        DPRINTK("vbd_translate; domain %d attempted to access "
   5.691 -                "non-existent VBD.\n", p->domain); 
   5.692 +    DPRINTK("vbd_translate; domain %d attempted to access "
   5.693 +            "non-existent VBD.\n", p->domain); 
   5.694  
   5.695      spin_unlock(&p->vbd_lock);
   5.696      return -ENODEV; 
   5.697  
   5.698   found:
   5.699  
   5.700 -    if ( ((operation == READ) && !VBD_CAN_READ(v)) ||
   5.701 -         ((operation == WRITE) && !VBD_CAN_WRITE(v)) )
   5.702 +    if ( ((operation == READ) && !VBD_CAN_READ(vbd)) ||
   5.703 +         ((operation == WRITE) && !VBD_CAN_WRITE(vbd)) )
   5.704      {
   5.705          spin_unlock(&p->vbd_lock);
   5.706          return -EACCES; 
   5.707 @@ -592,7 +690,7 @@ int vbd_translate(phys_seg_t *pseg, stru
   5.708       */
   5.709      sec_off = pseg->sector_number; 
   5.710      nr_secs = pseg->nr_sects;
   5.711 -    for ( x = v->extents; x != NULL; x = x->next )
   5.712 +    for ( x = vbd->extents; x != NULL; x = x->next )
   5.713      { 
   5.714          if ( sec_off < x->extent.nr_sectors )
   5.715          {
     6.1 --- a/xen/drivers/ide/ide-xeno.c	Wed Jan 14 18:05:25 2004 +0000
     6.2 +++ b/xen/drivers/ide/ide-xeno.c	Thu Jan 15 19:13:38 2004 +0000
     6.3 @@ -6,9 +6,7 @@
     6.4  #include <asm/domain_page.h>
     6.5  #include <asm/io.h>
     6.6  
     6.7 -#define NR_IDE_DEVS  20
     6.8 -
     6.9 -static kdev_t ide_devs[NR_IDE_DEVS] = { 
    6.10 +static kdev_t ide_devs[] = { 
    6.11      MKDEV(IDE0_MAJOR, 0), MKDEV(IDE0_MAJOR, 64),                /* hda, hdb */
    6.12      MKDEV(IDE1_MAJOR, 0), MKDEV(IDE1_MAJOR, 64),                /* hdc, hdd */
    6.13      MKDEV(IDE2_MAJOR, 0), MKDEV(IDE2_MAJOR, 64),                /* hde, hdf */
    6.14 @@ -21,63 +19,43 @@ static kdev_t ide_devs[NR_IDE_DEVS] = {
    6.15      MKDEV(IDE9_MAJOR, 0), MKDEV(IDE9_MAJOR, 64)                 /* hds, hdt */
    6.16  };
    6.17  
    6.18 -
    6.19 -
    6.20 -
    6.21 -int ide_probe_devices(xen_disk_info_t* xdi)
    6.22 +void ide_probe_devices(xen_disk_info_t* xdi)
    6.23  {
    6.24 -    int loop, ret = 0;
    6.25 -    unsigned int unit;
    6.26 -    unsigned short type; 
    6.27 +    int i, unit;
    6.28      ide_drive_t *drive;
    6.29 -    xen_disk_t cur_disk; 
    6.30 +    xen_disk_t *xd = &xdi->disks[xdi->count];
    6.31  
    6.32 -    for ( loop = 0; loop < MAX_HWIFS; loop++ )
    6.33 +    for ( i = 0; i < MAX_HWIFS; i++ )
    6.34      {
    6.35 -	ide_hwif_t *hwif = &ide_hwifs[loop];
    6.36 +	ide_hwif_t *hwif = &ide_hwifs[i];
    6.37  	if ( !hwif->present ) continue;
    6.38  
    6.39          for ( unit = 0; unit < MAX_DRIVES; unit++ )
    6.40          {
    6.41              drive = &hwif->drives[unit];
    6.42  
    6.43 -            if ( !drive->present ) continue;
    6.44 -
    6.45 +            if ( !drive->present )
    6.46 +                continue;
    6.47  
    6.48 -	    /* SMH: don't ever expect this to happen, hence verbose printk */
    6.49 -	    if ( xdi->count == xdi->max ) { 
    6.50 -		printk("ide_probe_devices: out of space for probe.\n"); 
    6.51 -		return -ENOMEM;  
    6.52 -	    }
    6.53 +	    if ( xdi->count == xdi->max )
    6.54 +                BUG();
    6.55  
    6.56 -            
    6.57 -	    
    6.58 -	    /* SMH: we export 'raw' linux device numbers to domain 0 */
    6.59 -	    cur_disk.device = ide_devs[(loop * MAX_DRIVES) + unit]; 
    6.60 +	    /* We export 'raw' linux device numbers to domain 0. */
    6.61 +	    xd->device = ide_devs[(i * MAX_DRIVES) + unit]; 
    6.62  
    6.63 -	    /* 
    6.64 -	    ** NB: we use the ide 'media' field (ide_disk, ide_cdrom, etc) 
    6.65 -	    ** as our 'type' field (XD_TYPE_DISK, XD_TYPE_CDROM, etc). 
    6.66 -	    ** Hence must ensure these are kept in sync. 
    6.67 -	    */
    6.68 -	    cur_disk.info   = (type = drive->media); 
    6.69 -	    if(type == XD_TYPE_CDROM) 
    6.70 -		cur_disk.info |= XD_FLAG_RO; 
    6.71 +	    /*
    6.72 +	     * NB: we use the ide 'media' field (ide_disk, ide_cdrom, etc) as 
    6.73 +	     * our 'type' field (XD_TYPE_DISK, XD_TYPE_CDROM, etc). Hence must 
    6.74 +	     * ensure these are kept in sync.
    6.75 +	     */
    6.76 +	    if ( (xd->info = drive->media) == XD_TYPE_CDROM ) 
    6.77 +		xd->info |= XD_FLAG_RO; 
    6.78  
    6.79 -	    cur_disk.capacity = current_capacity(drive);
    6.80 -	    cur_disk.domain   = 0; /* 'physical' disks belong to domain 0 */
    6.81 -
    6.82 -	    /* Now copy into relevant part of user-space buffer */
    6.83 -	    if((ret = copy_to_user(xdi->disks + xdi->count, &cur_disk, 
    6.84 -				   sizeof(xen_disk_t))) < 0) { 
    6.85 -		printk("ide_probe_devices: copy_to_user failed [rc=%d]\n", 
    6.86 -		       ret); 
    6.87 -		return ret; 
    6.88 -	    } 
    6.89 +	    xd->capacity = current_capacity(drive);
    6.90 +	    xd->domain   = 0;
    6.91  		
    6.92              xdi->count++;
    6.93 +            xd++;
    6.94          }
    6.95      }
    6.96 -    
    6.97 -    return ret; 
    6.98  }
     7.1 --- a/xen/drivers/scsi/sd.c	Wed Jan 14 18:05:25 2004 +0000
     7.2 +++ b/xen/drivers/scsi/sd.c	Thu Jan 15 19:13:38 2004 +0000
     7.3 @@ -32,19 +32,10 @@
     7.4  
     7.5  #include <xeno/config.h>
     7.6  #include <xeno/module.h>
     7.7 -
     7.8 -/*  #include <xeno/fs.h> */
     7.9 -/*  #include <xeno/kernel.h> */
    7.10  #include <xeno/sched.h>
    7.11 -/*  #include <xeno/mm.h> */
    7.12 -/*  #include <xeno/string.h> */
    7.13  #include <xeno/hdreg.h>
    7.14 -/*  #include <xeno/errno.h> */
    7.15 -/*  #include <xeno/interrupt.h> */
    7.16  #include <xeno/init.h>
    7.17  
    7.18 -/*  #include <xeno/smp.h> */
    7.19 -
    7.20  #include <asm/uaccess.h>
    7.21  #include <asm/system.h>
    7.22  #include <asm/io.h>
    7.23 @@ -1322,9 +1313,7 @@ static void sd_finish()
    7.24  **
    7.25  */
    7.26  
    7.27 -#define NR_SCSI_DEVS 16
    7.28 -
    7.29 -static kdev_t scsi_devs[NR_SCSI_DEVS] = { 
    7.30 +static kdev_t scsi_devs[] = { 
    7.31      MKDEV(SCSI_DISK0_MAJOR,   0), MKDEV(SCSI_DISK0_MAJOR,  16), /* sda, sdb */
    7.32      MKDEV(SCSI_DISK0_MAJOR,  32), MKDEV(SCSI_DISK0_MAJOR,  48), /* sdc, sdd */
    7.33      MKDEV(SCSI_DISK0_MAJOR,  64), MKDEV(SCSI_DISK0_MAJOR,  80), /* sde, sdf */
    7.34 @@ -1336,39 +1325,29 @@ static kdev_t scsi_devs[NR_SCSI_DEVS] = 
    7.35  };
    7.36  
    7.37  
    7.38 -int scsi_probe_devices(xen_disk_info_t *xdi)
    7.39 +void scsi_probe_devices(xen_disk_info_t *xdi)
    7.40  {
    7.41 +    int i;
    7.42      Scsi_Disk *sd; 
    7.43 -    xen_disk_t cur_disk; 
    7.44 -    int i, ret;
    7.45 +    xen_disk_t *xd = &xdi->disks[xdi->count];
    7.46  
    7.47      for ( sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++ )
    7.48      {
    7.49 -        if ( sd->device == NULL ) continue;
    7.50 +        if ( sd->device == NULL )
    7.51 +            continue;
    7.52  
    7.53 -	/* SMH: don't ever expect this to happen, hence verbose printk */
    7.54 -	if ( xdi->count == xdi->max ) { 
    7.55 -	    printk("scsi_probe_devices: out of space for probe.\n"); 
    7.56 -	    return -ENOMEM; 
    7.57 -	}
    7.58 +	if ( xdi->count == xdi->max )
    7.59 +            BUG();
    7.60  
    7.61 -	/* SMH: we export 'raw' linux device numbers to domain 0 */
    7.62 -	cur_disk.device   = scsi_devs[i]; 
    7.63 -	cur_disk.info     = XD_TYPE_DISK; // XXX SMH: should determine properly
    7.64 -        cur_disk.capacity = sd->capacity;
    7.65 -	cur_disk.domain   = 0;            // 'physical' disks belong to dom0 
    7.66 +	/* We export 'raw' linux device numbers to domain 0. */
    7.67 +	xd->device   = scsi_devs[i]; 
    7.68 +	xd->info     = XD_TYPE_DISK; /* XXX should determine properly */
    7.69 +        xd->capacity = sd->capacity;
    7.70 +	xd->domain   = 0;
    7.71  
    7.72 -	/* Now copy into relevant part of user-space buffer */
    7.73 -	if((ret = copy_to_user(xdi->disks + xdi->count, &cur_disk, 
    7.74 -			       sizeof(xen_disk_t))) < 0) {  
    7.75 -	    printk("scsi_probe_devices: copy_to_user failed [rc=%d]\n", ret); 
    7.76 -	    return ret; 
    7.77 -	} 
    7.78 -	
    7.79  	xdi->count++;
    7.80 +        xd++;
    7.81      }
    7.82 -
    7.83 -    return 0;
    7.84  }	
    7.85  
    7.86  
     8.1 --- a/xen/include/xeno/multiboot.h	Wed Jan 14 18:05:25 2004 +0000
     8.2 +++ b/xen/include/xeno/multiboot.h	Thu Jan 15 19:13:38 2004 +0000
     8.3 @@ -26,7 +26,7 @@
     8.4  #define MULTIBOOT_BOOTLOADER_MAGIC	0x2BADB002
     8.5  
     8.6  /* The symbol table for a.out.  */
     8.7 -typedef struct aout_symbol_table
     8.8 +typedef struct
     8.9  {
    8.10    unsigned long tabsize;
    8.11    unsigned long strsize;
    8.12 @@ -35,7 +35,7 @@ typedef struct aout_symbol_table
    8.13  } aout_symbol_table_t;
    8.14  
    8.15  /* The section header table for ELF.  */
    8.16 -typedef struct elf_section_header_table
    8.17 +typedef struct
    8.18  {
    8.19    unsigned long num;
    8.20    unsigned long size;
    8.21 @@ -44,7 +44,7 @@ typedef struct elf_section_header_table
    8.22  } elf_section_header_table_t;
    8.23  
    8.24  /* The Multiboot information.  */
    8.25 -typedef struct multiboot_info
    8.26 +typedef struct
    8.27  {
    8.28    unsigned long flags;
    8.29    unsigned long mem_lower;
    8.30 @@ -63,7 +63,7 @@ typedef struct multiboot_info
    8.31  } multiboot_info_t;
    8.32  
    8.33  /* The module structure.  */
    8.34 -typedef struct module
    8.35 +typedef struct
    8.36  {
    8.37    unsigned long mod_start;
    8.38    unsigned long mod_end;
    8.39 @@ -73,7 +73,7 @@ typedef struct module
    8.40  
    8.41  /* The memory map. Be careful that the offset 0 is base_addr_low
    8.42     but no size.  */
    8.43 -typedef struct memory_map
    8.44 +typedef struct
    8.45  {
    8.46    unsigned long size;
    8.47    unsigned long base_addr_low;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/include/xeno/rbtree.h	Thu Jan 15 19:13:38 2004 +0000
     9.3 @@ -0,0 +1,134 @@
     9.4 +/*
     9.5 +  Red Black Trees
     9.6 +  (C) 1999  Andrea Arcangeli <andrea@suse.de>
     9.7 +  
     9.8 +  This program is free software; you can redistribute it and/or modify
     9.9 +  it under the terms of the GNU General Public License as published by
    9.10 +  the Free Software Foundation; either version 2 of the License, or
    9.11 +  (at your option) any later version.
    9.12 +
    9.13 +  This program is distributed in the hope that it will be useful,
    9.14 +  but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.15 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.16 +  GNU General Public License for more details.
    9.17 +
    9.18 +  You should have received a copy of the GNU General Public License
    9.19 +  along with this program; if not, write to the Free Software
    9.20 +  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.21 +
    9.22 +  linux/include/linux/rbtree.h
    9.23 +
    9.24 +  To use rbtrees you'll have to implement your own insert and search cores.
    9.25 +  This will avoid us to use callbacks and to drop drammatically performances.
    9.26 +  I know it's not the cleaner way,  but in C (not in C++) to get
    9.27 +  performances and genericity...
    9.28 +
    9.29 +  Some example of insert and search follows here. The search is a plain
    9.30 +  normal search over an ordered tree. The insert instead must be implemented
    9.31 +  int two steps: as first thing the code must insert the element in
    9.32 +  order as a red leaf in the tree, then the support library function
    9.33 +  rb_insert_color() must be called. Such function will do the
    9.34 +  not trivial work to rebalance the rbtree if necessary.
    9.35 +
    9.36 +-----------------------------------------------------------------------
    9.37 +static inline struct page * rb_search_page_cache(struct inode * inode,
    9.38 +						 unsigned long offset)
    9.39 +{
    9.40 +	rb_node_t * n = inode->i_rb_page_cache.rb_node;
    9.41 +	struct page * page;
    9.42 +
    9.43 +	while (n)
    9.44 +	{
    9.45 +		page = rb_entry(n, struct page, rb_page_cache);
    9.46 +
    9.47 +		if (offset < page->offset)
    9.48 +			n = n->rb_left;
    9.49 +		else if (offset > page->offset)
    9.50 +			n = n->rb_right;
    9.51 +		else
    9.52 +			return page;
    9.53 +	}
    9.54 +	return NULL;
    9.55 +}
    9.56 +
    9.57 +static inline struct page * __rb_insert_page_cache(struct inode * inode,
    9.58 +						   unsigned long offset,
    9.59 +						   rb_node_t * node)
    9.60 +{
    9.61 +	rb_node_t ** p = &inode->i_rb_page_cache.rb_node;
    9.62 +	rb_node_t * parent = NULL;
    9.63 +	struct page * page;
    9.64 +
    9.65 +	while (*p)
    9.66 +	{
    9.67 +		parent = *p;
    9.68 +		page = rb_entry(parent, struct page, rb_page_cache);
    9.69 +
    9.70 +		if (offset < page->offset)
    9.71 +			p = &(*p)->rb_left;
    9.72 +		else if (offset > page->offset)
    9.73 +			p = &(*p)->rb_right;
    9.74 +		else
    9.75 +			return page;
    9.76 +	}
    9.77 +
    9.78 +	rb_link_node(node, parent, p);
    9.79 +
    9.80 +	return NULL;
    9.81 +}
    9.82 +
    9.83 +static inline struct page * rb_insert_page_cache(struct inode * inode,
    9.84 +						 unsigned long offset,
    9.85 +						 rb_node_t * node)
    9.86 +{
    9.87 +	struct page * ret;
    9.88 +	if ((ret = __rb_insert_page_cache(inode, offset, node)))
    9.89 +		goto out;
    9.90 +	rb_insert_color(node, &inode->i_rb_page_cache);
    9.91 + out:
    9.92 +	return ret;
    9.93 +}
    9.94 +-----------------------------------------------------------------------
    9.95 +*/
    9.96 +
    9.97 +#ifndef	_LINUX_RBTREE_H
    9.98 +#define	_LINUX_RBTREE_H
    9.99 +
   9.100 +#include <xeno/config.h>
   9.101 +#include <xeno/lib.h>
   9.102 +#include <xeno/module.h>
   9.103 +
   9.104 +typedef struct rb_node_s
   9.105 +{
   9.106 +	struct rb_node_s * rb_parent;
   9.107 +	int rb_color;
   9.108 +#define	RB_RED		0
   9.109 +#define	RB_BLACK	1
   9.110 +	struct rb_node_s * rb_right;
   9.111 +	struct rb_node_s * rb_left;
   9.112 +}
   9.113 +rb_node_t;
   9.114 +
   9.115 +typedef struct rb_root_s
   9.116 +{
   9.117 +	struct rb_node_s * rb_node;
   9.118 +}
   9.119 +rb_root_t;
   9.120 +
   9.121 +#define RB_ROOT	(rb_root_t) { NULL, }
   9.122 +#define	rb_entry(ptr, type, member)					\
   9.123 +	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
   9.124 +
   9.125 +extern void rb_insert_color(rb_node_t *, rb_root_t *);
   9.126 +extern void rb_erase(rb_node_t *, rb_root_t *);
   9.127 +
   9.128 +static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link)
   9.129 +{
   9.130 +	node->rb_parent = parent;
   9.131 +	node->rb_color = RB_RED;
   9.132 +	node->rb_left = node->rb_right = NULL;
   9.133 +
   9.134 +	*rb_link = node;
   9.135 +}
   9.136 +
   9.137 +#endif	/* _LINUX_RBTREE_H */
    10.1 --- a/xen/include/xeno/sched.h	Wed Jan 14 18:05:25 2004 +0000
    10.2 +++ b/xen/include/xeno/sched.h	Thu Jan 15 19:13:38 2004 +0000
    10.3 @@ -15,6 +15,7 @@
    10.4  #include <xeno/time.h>
    10.5  #include <xeno/ac_timer.h>
    10.6  #include <xeno/delay.h>
    10.7 +#include <xeno/rbtree.h>
    10.8  
    10.9  #define MAX_DOMAIN_NAME 16
   10.10  
   10.11 @@ -126,8 +127,8 @@ struct task_struct
   10.12      BLK_RING_IDX blk_resp_prod; /* (private version of) response producer */
   10.13      struct list_head blkdev_list;
   10.14      spinlock_t blk_ring_lock;
   10.15 -    vbd_t *vbdtab[VBD_HTAB_SZ];   /* mapping from 16-bit vdevices to vbds */
   10.16 -    spinlock_t vbd_lock;
   10.17 +    rb_root_t  vbd_rb;          /* mapping from 16-bit vdevices to vbds */
   10.18 +    spinlock_t vbd_lock;        /* protects VBD mapping */
   10.19  
   10.20      /* VM */
   10.21      struct mm_struct mm;
    11.1 --- a/xen/include/xeno/vbd.h	Wed Jan 14 18:05:25 2004 +0000
    11.2 +++ b/xen/include/xeno/vbd.h	Thu Jan 15 19:13:38 2004 +0000
    11.3 @@ -9,27 +9,40 @@
    11.4  #include <hypervisor-ifs/block.h>
    11.5  #include <hypervisor-ifs/vbd.h>
    11.6  
    11.7 -/* an entry in a list of xen_extent's */
    11.8 +#include <xeno/rbtree.h>
    11.9 +
   11.10 +/* An entry in a list of xen_extents. */
   11.11  typedef struct _xen_extent_le { 
   11.12 -    xen_extent_t           extent;     /* an individual extent */
   11.13 +    xen_extent_t extent;               /* an individual extent */
   11.14      struct _xen_extent_le *next;       /* and a pointer to the next */ 
   11.15  } xen_extent_le_t; 
   11.16  
   11.17 -
   11.18  /*
   11.19 -** This is what a vbd looks like from the pov of xen: essentially a list 
   11.20 -** of xen_extents which a given domain refers to by a particular 16bit id. 
   11.21 -** Each domain has a hash table to map from these to the relevant VBD. 
   11.22 -*/
   11.23 + * This is what a vbd looks like from the p.o.v. of xen: essentially a list of
   11.24 + * xen_extents which a given domain refers to by a particular 16bit id. Each
   11.25 + * domain has a lookup structure to map from these to the relevant VBD.
   11.26 + */
   11.27  typedef struct _vbd { 
   11.28      unsigned short    vdevice;   /* what the domain refers to this vbd as */
   11.29 -    unsigned short    mode;      /* VBD_MODE_{READONLY,READWRITE} */
   11.30 +    unsigned char     mode;      /* VBD_MODE_{R,W} */
   11.31 +    unsigned char     type;      /* XD_TYPE_xxx */
   11.32      xen_extent_le_t  *extents;   /* list of xen_extents making up this vbd */
   11.33 -    struct _vbd      *next;      /* for chaining in the hash table */
   11.34 +    rb_node_t         rb;        /* for linking into R-B tree lookup struct */
   11.35  } vbd_t; 
   11.36  
   11.37 -#define VBD_HTAB_SZ  16       /* # entries in the vbd hash table. */
   11.38 +/*
   11.39 + * Internal forms of 'vbd_create' and 'vbd_grow. Used when setting up real 
   11.40 + * physical device access for domain 0.
   11.41 + */
   11.42 +long __vbd_create(struct task_struct *p,
   11.43 +                  unsigned short vdevice,
   11.44 +                  unsigned char mode,
   11.45 +                  unsigned char type);
   11.46 +long __vbd_grow(struct task_struct *p,
   11.47 +                unsigned short vdevice,
   11.48 +                xen_extent_t *extent);
   11.49  
   11.50 +/* This is the main API, accessible from guest OSes. */
   11.51  long vbd_create(vbd_create_t *create_params); 
   11.52  long vbd_grow(vbd_grow_t *grow_params); 
   11.53  long vbd_shrink(vbd_shrink_t *shrink_params);
    12.1 --- a/xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_block.c	Wed Jan 14 18:05:25 2004 +0000
    12.2 +++ b/xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_block.c	Thu Jan 15 19:13:38 2004 +0000
    12.3 @@ -3,11 +3,10 @@
    12.4   * 
    12.5   * Xenolinux virtual block-device driver.
    12.6   * 
    12.7 + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
    12.8 + * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
    12.9   */
   12.10  
   12.11 -/* Some modifications to the original by Mark A. Williamson and (C) Intel
   12.12 - * Research Cambridge */
   12.13 -
   12.14  #include "xl_block.h"
   12.15  #include <linux/blk.h>
   12.16  #include <linux/cdrom.h>
   12.17 @@ -31,9 +30,6 @@ static blk_ring_t *blk_ring;
   12.18  static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */
   12.19  static BLK_RING_IDX req_prod;  /* Private request producer.         */
   12.20  
   12.21 -#define XDI_MAX 64 
   12.22 -xen_disk_info_t xlblk_disk_info; /* information about our disks/VBDs */
   12.23 -
   12.24  /* We plug the I/O ring if the driver is suspended or if the ring is full. */
   12.25  #define RING_PLUGGED (((req_prod - resp_cons) == BLK_RING_SIZE) || \
   12.26                        (state != STATE_ACTIVE))
   12.27 @@ -66,6 +62,25 @@ static inline void signal_requests_to_xe
   12.28  }
   12.29  
   12.30  
   12.31 +/*
   12.32 + * xlblk_update_int/update-vbds_task - handle VBD update events from Xen
   12.33 + * 
   12.34 + * Schedule a task for keventd to run, which will update the VBDs and perform 
   12.35 + * the corresponding updates to our view of VBD state, so the XenoLinux will 
   12.36 + * respond to changes / additions / deletions to the set of VBDs automatically.
   12.37 + */
   12.38 +static struct tq_struct update_tq;
   12.39 +static void update_vbds_task(void *unused)
   12.40 +{ 
   12.41 +    xlvbd_update_vbds();
   12.42 +}
   12.43 +static void xlblk_update_int(int irq, void *dev_id, struct pt_regs *ptregs)
   12.44 +{
   12.45 +    update_tq.routine = update_vbds_task;
   12.46 +    schedule_task(&update_tq);
   12.47 +}
   12.48 +
   12.49 +
   12.50  int xenolinux_block_open(struct inode *inode, struct file *filep)
   12.51  {
   12.52      short xldev = inode->i_rdev; 
   12.53 @@ -100,9 +115,9 @@ int xenolinux_block_open(struct inode *i
   12.54          }
   12.55      }
   12.56      
   12.57 -    /* RACE: need locking SMP / pre-emptive kernels */
   12.58 +    /* Update of usage count is protected by per-device semaphore. */
   12.59      disk->usage++;
   12.60 -    DPRINTK("xenolinux_block_open\n");
   12.61 +
   12.62      return 0;
   12.63  }
   12.64  
   12.65 @@ -110,17 +125,16 @@ int xenolinux_block_open(struct inode *i
   12.66  int xenolinux_block_release(struct inode *inode, struct file *filep)
   12.67  {
   12.68      xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
   12.69 -    disk->usage--; /* RACE: need locking for SMP / pre-emptive kernels */
   12.70 -    DPRINTK("xenolinux_block_release\n");
   12.71  
   12.72 - /* A reference to a disk has been dropped: may enable more changes to VBDs to
   12.73 -  * go through (currently don't do any updates while references are held), so
   12.74 -  * we run the update magic again.  Could equally well schedule this update for
   12.75 -  * keventd to run, or use a flag so we only update at this point if we think
   12.76 -  * something (relevant) may have changed.
   12.77 -  * Keventd has the advantage that it'll serialise executions of this function
   12.78 -  * - there's a race here for SMP / pre-emptive kernels */
   12.79 -    xlvbd_update_vbds();
   12.80 +    /*
   12.81 +     * When usage drops to zero it may allow more VBD updates to occur.
   12.82 +     * Update of usage count is protected by a per-device semaphore.
   12.83 +     */
   12.84 +    if ( --disk->usage == 0 )
   12.85 +    {
   12.86 +        update_tq.routine = update_vbds_task;
   12.87 +        schedule_task(&update_tq);
   12.88 +    }
   12.89  
   12.90      return 0;
   12.91  }
   12.92 @@ -212,34 +226,36 @@ int xenolinux_block_check(kdev_t dev)
   12.93      return 0;
   12.94  }
   12.95  
   12.96 -/* MAW - leaving this as it is for now.  As long as we're responding to the VBD
   12.97 - * update events from the hypervisor, I figure this will still do what it's
   12.98 - * meant to do :-) */
   12.99  int xenolinux_block_revalidate(kdev_t dev)
  12.100  {
  12.101 -    struct gendisk *gd = get_gendisk(dev);
  12.102 -    xl_disk_t *disk = xldev_to_xldisk(dev);
  12.103 -    unsigned long flags, capacity = gd->part[MINOR(dev)].nr_sects;
  12.104 -    int i, disk_nr = MINOR(dev) >> gd->minor_shift;
  12.105 +    struct block_device *bd;
  12.106 +    struct gendisk *gd;
  12.107 +    xl_disk_t *disk;
  12.108 +    unsigned long flags, capacity;
  12.109 +    int i, rc = 0, disk_nr = MINOR(dev) >> gd->minor_shift;
  12.110      
  12.111 -    DPRINTK("xenolinux_block_revalidate: %d\n", dev);
  12.112 +    if ( (bd = bdget(dev)) == NULL )
  12.113 +        return -EINVAL;
  12.114  
  12.115      /*
  12.116 -     * We didn't construct this VBD by reading a partition table. This
  12.117 -     * function can only do bad things to us.
  12.118 +     * Update of partition info, and check of usage count, is protected
  12.119 +     * by the per-block-device semaphore.
  12.120       */
  12.121 -    if ( capacity == 0 )
  12.122 -        return -EINVAL;
  12.123 +    down(&bd->bd_sem);
  12.124  
  12.125 -    spin_lock_irqsave(&io_request_lock, flags);
  12.126 +    if ( ((gd = get_gendisk(dev)) == NULL) ||
  12.127 +         ((disk = xldev_to_xldisk(dev)) == NULL) ||
  12.128 +         ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) )
  12.129 +    {
  12.130 +        rc = -EINVAL;
  12.131 +        goto out;
  12.132 +    }
  12.133 +
  12.134      if ( disk->usage > 1 )
  12.135      {
  12.136 -        spin_unlock_irqrestore(&io_request_lock, flags);
  12.137 -        return -EBUSY;
  12.138 +        rc = -EBUSY;
  12.139 +        goto out;
  12.140      }
  12.141 -    spin_unlock_irqrestore(&io_request_lock, flags);
  12.142 -
  12.143 -    /* RACE? is it OK that we give up the lock */
  12.144  
  12.145      for ( i = gd->max_p - 1; i >= 0; i-- )
  12.146      {
  12.147 @@ -249,12 +265,12 @@ int xenolinux_block_revalidate(kdev_t de
  12.148          gd->sizes[MINOR(dev+i)]           = 0;
  12.149      }
  12.150  
  12.151 -    /* shouldn't need to revalidate VBDs here as it's done automatically when
  12.152 -     * we get the VBD update event from Xen */
  12.153 -
  12.154      grok_partitions(gd, disk_nr, gd->max_p, capacity);
  12.155  
  12.156 -    return 0;
  12.157 + out:
  12.158 +    up(&bd->bd_sem);
  12.159 +    bdput(bd);
  12.160 +    return rc;
  12.161  }
  12.162  
  12.163  
  12.164 @@ -449,43 +465,6 @@ static void kick_pending_request_queues(
  12.165  }
  12.166  
  12.167  
  12.168 -/**
  12.169 - * do_update_vbds - called in process context by keventd to update VBDs
  12.170 - * @arg:            dummy argument to fit schedule_task API
  12.171 - *
  12.172 - * When this function is run, it simply calls through to xlvbd_update_vbds in
  12.173 - * update the VBD state information.  The argument is ignored - it's only there
  12.174 - * because the API for scheduling with keventd requires it.
  12.175 - */
  12.176 -void do_update_vbds(void * arg)
  12.177 -{
  12.178 -    DPRINTK("xl_block.c::do_update_vbds() - called\n");
  12.179 -    xlvbd_update_vbds();
  12.180 -}
  12.181 -
  12.182 -/* this data is needed to register do_update_vbds() as a task for keventd */
  12.183 -static struct tq_struct update = {
  12.184 -    .sync = 0,
  12.185 -    .routine = do_update_vbds,
  12.186 -    .data = 0
  12.187 -};
  12.188 -
  12.189 -/**
  12.190 - * xlblk_update_int - handle VBD update events from Xen
  12.191 - *
  12.192 - * This function schedules a task for keventd to run, which will update the
  12.193 - * VBDs and perform the corresponding updates to our view of VBD state, so the
  12.194 - * XenoLinux will respond to changes / additions / deletions to the set of VBDs
  12.195 - * automatically.
  12.196 - */
  12.197 -static void xlblk_update_int(int irq, void *dev_id, struct pt_regs *ptregs)
  12.198 -{
  12.199 -    DPRINTK("xl_block.c::xlblk_update_int() - called\n");
  12.200 -    
  12.201 -    schedule_task(&update);
  12.202 -}
  12.203 -
  12.204 -
  12.205  static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
  12.206  {
  12.207      BLK_RING_IDX i; 
  12.208 @@ -530,7 +509,6 @@ static void xlblk_response_int(int irq, 
  12.209  }
  12.210  
  12.211  
  12.212 -
  12.213  static void reset_xlblk_interface(void)
  12.214  {
  12.215      block_io_op_t op; 
  12.216 @@ -556,7 +534,6 @@ static void reset_xlblk_interface(void)
  12.217  int __init xlblk_init(void)
  12.218  {
  12.219      int error; 
  12.220 -    block_io_op_t op; 
  12.221  
  12.222      reset_xlblk_interface();
  12.223  
  12.224 @@ -577,31 +554,7 @@ int __init xlblk_init(void)
  12.225          goto fail;
  12.226      }
  12.227  
  12.228 -    /* Setup our [empty] disk information structure */
  12.229 -    xlblk_disk_info.max   = XDI_MAX; 
  12.230 -    xlblk_disk_info.disks = kmalloc(XDI_MAX * sizeof(xen_disk_t), GFP_KERNEL);
  12.231 -    xlblk_disk_info.count = 0; 
  12.232 -
  12.233 -    /* Probe for disk information. */
  12.234 -    memset(&op, 0, sizeof(op)); 
  12.235 -    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
  12.236 -    op.u.probe_params.domain = 0; 
  12.237 -    memcpy(&op.u.probe_params.xdi, &xlblk_disk_info, sizeof(xlblk_disk_info)); 
  12.238 -
  12.239 -    error = HYPERVISOR_block_io_op(&op); 
  12.240 -
  12.241 -    if ( error )
  12.242 -    {
  12.243 -        printk(KERN_ALERT "Could not probe disks (%d)\n", error);
  12.244 -        free_irq(XLBLK_RESPONSE_IRQ, NULL);
  12.245 -        goto fail;
  12.246 -    }
  12.247 -
  12.248 -    /* copy back the [updated] count parameter */
  12.249 -    xlblk_disk_info.count = op.u.probe_params.xdi.count; 
  12.250 -
  12.251 -    /* Pass the information to our virtual block device susbystem. */
  12.252 -    xlvbd_init(&xlblk_disk_info);
  12.253 +    (void)xlvbd_init();
  12.254  
  12.255      return 0;
  12.256  
  12.257 @@ -609,6 +562,7 @@ int __init xlblk_init(void)
  12.258      return error;
  12.259  }
  12.260  
  12.261 +
  12.262  static void __exit xlblk_cleanup(void)
  12.263  {
  12.264      xlvbd_cleanup();
    13.1 --- a/xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_block.h	Wed Jan 14 18:05:25 2004 +0000
    13.2 +++ b/xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_block.h	Thu Jan 15 19:13:38 2004 +0000
    13.3 @@ -52,7 +52,6 @@ typedef struct xl_disk {
    13.4      int usage;
    13.5  } xl_disk_t;
    13.6  
    13.7 -/* Generic layer. */
    13.8  extern int xenolinux_control_msg(int operration, char *buffer, int size);
    13.9  extern int xenolinux_block_open(struct inode *inode, struct file *filep);
   13.10  extern int xenolinux_block_release(struct inode *inode, struct file *filep);
   13.11 @@ -62,22 +61,22 @@ extern int xenolinux_block_check(kdev_t 
   13.12  extern int xenolinux_block_revalidate(kdev_t dev);
   13.13  extern void do_xlblk_request (request_queue_t *rq); 
   13.14  
   13.15 -extern xen_disk_info_t xlblk_disk_info; /* this is really in xl_block.c */
   13.16 -extern void xlvbd_update_vbds(void);    /* this is really in xl_vbd.c */
   13.17 +extern void xlvbd_update_vbds(void);
   13.18  
   13.19  static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev)
   13.20  {
   13.21      struct gendisk *gd = get_gendisk(xldev);
   13.22 -
   13.23 -    if(!gd) return NULL;
   13.24 -
   13.25 +    
   13.26 +    if ( gd == NULL ) 
   13.27 +        return NULL;
   13.28 +    
   13.29      return (xl_disk_t *)gd->real_devices + 
   13.30          (MINOR(xldev) >> gd->minor_shift);
   13.31  }
   13.32  
   13.33  
   13.34  /* Virtual block-device subsystem. */
   13.35 -extern int  xlvbd_init(xen_disk_info_t *xdi);
   13.36 +extern int  xlvbd_init(void);
   13.37  extern void xlvbd_cleanup(void); 
   13.38  
   13.39  #endif /* __XL_BLOCK_H__ */
    14.1 --- a/xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_vbd.c	Wed Jan 14 18:05:25 2004 +0000
    14.2 +++ b/xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_vbd.c	Thu Jan 15 19:13:38 2004 +0000
    14.3 @@ -3,11 +3,10 @@
    14.4   * 
    14.5   * Xenolinux virtual block-device driver (xvd).
    14.6   * 
    14.7 + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
    14.8 + * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
    14.9   */
   14.10  
   14.11 -/* Some modifications to the original by Mark A. Williamson and (C) Intel
   14.12 - * Research Cambridge */
   14.13 -
   14.14  #include "xl_block.h"
   14.15  #include <linux/blk.h>
   14.16  
   14.17 @@ -30,13 +29,9 @@
   14.18  #define XLSCSI_PARTN_SHIFT 4    /* amount to shift minor to get 'real' minor */
   14.19  #define XLSCSI_MAX_PART   (1 << XLSCSI_PARTN_SHIFT)   /* minors per scsi vbd */
   14.20  
   14.21 -#define XLVBD_PARTN_SHIFT  6    /* amount to shift minor to get 'real' minor */
   14.22 +#define XLVBD_PARTN_SHIFT  4    /* amount to shift minor to get 'real' minor */
   14.23  #define XLVBD_MAX_PART    (1 << XLVBD_PARTN_SHIFT) /* minors per 'other' vbd */
   14.24  
   14.25 -/* Used to record data in vbd_state[] and detect changes in configuration */
   14.26 -#define VBD_NODEV 1
   14.27 -#define VBD_KNOWN 2
   14.28 -
   14.29  /* The below are for the generic drivers/block/ll_rw_block.c code. */
   14.30  static int xlide_blksize_size[256];
   14.31  static int xlide_hardsect_size[256];
   14.32 @@ -48,6 +43,11 @@ static int xlvbd_blksize_size[256];
   14.33  static int xlvbd_hardsect_size[256];
   14.34  static int xlvbd_max_sectors[256];
   14.35  
   14.36 +/* Information from Xen about our VBDs. */
   14.37 +#define MAX_VBDS 64
   14.38 +static int nr_vbds;
   14.39 +static xen_disk_t *vbd_info;
   14.40 +
   14.41  static struct block_device_operations xlvbd_block_fops = 
   14.42  {
   14.43      open:               xenolinux_block_open,
   14.44 @@ -57,10 +57,29 @@ static struct block_device_operations xl
   14.45      revalidate:         xenolinux_block_revalidate,
   14.46  };
   14.47  
   14.48 - /* hold state about for all possible VBDs for use in handling updates */
   14.49 -static char vbd_state[65536];
   14.50 +static int xlvbd_get_vbd_info(xen_disk_t *disk_info)
   14.51 +{
   14.52 +    int error;
   14.53 +    block_io_op_t op; 
   14.54  
   14.55 -/**
   14.56 +    /* Probe for disk information. */
   14.57 +    memset(&op, 0, sizeof(op)); 
   14.58 +    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
   14.59 +    op.u.probe_params.domain    = 0; 
   14.60 +    op.u.probe_params.xdi.max   = MAX_VBDS;
   14.61 +    op.u.probe_params.xdi.disks = disk_info;
   14.62 +    op.u.probe_params.xdi.count = 0;
   14.63 +
   14.64 +    if ( (error = HYPERVISOR_block_io_op(&op)) != 0 )
   14.65 +    {
   14.66 +        printk(KERN_ALERT "Could not probe disks (%d)\n", error);
   14.67 +        return -1;
   14.68 +    }
   14.69 +
   14.70 +    return op.u.probe_params.xdi.count;
   14.71 +}
   14.72 +
   14.73 +/*
   14.74   * xlvbd_init_device - initialise a VBD device
   14.75   * @disk:              a xen_disk_t describing the VBD
   14.76   *
   14.77 @@ -71,23 +90,37 @@ static char vbd_state[65536];
   14.78   * corruption does not occur.  Also, devices that are in use should not have
   14.79   * their details updated.  This is the caller's responsibility.
   14.80   */
   14.81 -int xlvbd_init_device(xen_disk_t *disk)
   14.82 +static int xlvbd_init_device(xen_disk_t *xd)
   14.83  {
   14.84 -    int device = disk->device;
   14.85 +    int device = xd->device;
   14.86      int major  = MAJOR(device); 
   14.87      int minor  = MINOR(device);
   14.88      int is_ide = IDE_DISK_MAJOR(major);  /* is this an ide device? */
   14.89      int is_scsi= SCSI_BLK_MAJOR(major);  /* is this a scsi device? */
   14.90 -    int partno;
   14.91 -    char * major_name;
   14.92 -    int max_part;
   14.93 -    
   14.94 +    char *major_name;
   14.95      struct gendisk *gd;
   14.96 -    int result;
   14.97 -    int j;
   14.98 +    struct block_device *bd;
   14.99 +    xl_disk_t *disk;
  14.100 +    int i, rc = 0, max_part, partno;
  14.101  
  14.102      unsigned char buf[64];
  14.103  
  14.104 +    if ( (bd = bdget(device)) == NULL )
  14.105 +        return -1;
  14.106 +
  14.107 +    /*
  14.108 +     * Update of partition info, and check of usage count, is protected
  14.109 +     * by the per-block-device semaphore.
  14.110 +     */
  14.111 +    down(&bd->bd_sem);
  14.112 +
  14.113 +    if ( ((disk = xldev_to_xldisk(device)) != NULL) && (disk->usage != 0) )
  14.114 +    {
  14.115 +        printk(KERN_ALERT "VBD update failed - in use [dev=%x]\n", device);
  14.116 +        rc = -1;
  14.117 +        goto out;
  14.118 +    }
  14.119 +
  14.120      if ( is_ide )
  14.121      { 
  14.122  	major_name = XLIDE_MAJOR_NAME; 
  14.123 @@ -108,11 +141,11 @@ int xlvbd_init_device(xen_disk_t *disk)
  14.124      
  14.125      if ( (gd = get_gendisk(device)) == NULL )
  14.126      {
  14.127 -        result = register_blkdev(major, major_name, &xlvbd_block_fops);
  14.128 -        if ( result < 0 )
  14.129 +        rc = register_blkdev(major, major_name, &xlvbd_block_fops);
  14.130 +        if ( rc < 0 )
  14.131          {
  14.132              printk(KERN_ALERT "XL VBD: can't get major %d\n", major);
  14.133 -            return -1; /* XXX make this sane one day */
  14.134 +            goto out;
  14.135          }
  14.136  
  14.137          if ( is_ide )
  14.138 @@ -199,7 +232,7 @@ int xlvbd_init_device(xen_disk_t *disk)
  14.139          blk_size[major] = gd->sizes;
  14.140      }
  14.141  
  14.142 -    if ( XD_READONLY(disk->info) )
  14.143 +    if ( XD_READONLY(xd->info) )
  14.144          set_device_ro(device, 1); 
  14.145  
  14.146      gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XENO;
  14.147 @@ -214,14 +247,12 @@ int xlvbd_init_device(xen_disk_t *disk)
  14.148          if ( gd->sizes[minor & ~(max_part-1)] != 0 )
  14.149          {
  14.150              kdev_t dev = device & ~(max_part-1);
  14.151 -            for ( j = max_part - 1; j >= 0; j-- )
  14.152 +            for ( i = max_part - 1; i >= 0; i-- )
  14.153              {
  14.154 -                invalidate_device(dev+j, 1);
  14.155 -                gd->part[MINOR(dev+j)].start_sect = 0;
  14.156 -                gd->part[MINOR(dev+j)].nr_sects   = 0;
  14.157 -                gd->sizes[MINOR(dev+j)]           = 0;
  14.158 -
  14.159 -                vbd_state[dev+j] &= ~VBD_KNOWN;
  14.160 +                invalidate_device(dev+i, 1);
  14.161 +                gd->part[MINOR(dev+i)].start_sect = 0;
  14.162 +                gd->part[MINOR(dev+i)].nr_sects   = 0;
  14.163 +                gd->sizes[MINOR(dev+i)]           = 0;
  14.164              }
  14.165              printk(KERN_ALERT
  14.166                     "Virtual partitions found for /dev/%s - ignoring any "
  14.167 @@ -231,31 +262,27 @@ int xlvbd_init_device(xen_disk_t *disk)
  14.168  
  14.169          /* Need to skankily setup 'partition' information */
  14.170          gd->part[minor].start_sect = 0; 
  14.171 -        gd->part[minor].nr_sects   = disk->capacity; 
  14.172 -        gd->sizes[minor]           = disk->capacity; 
  14.173 +        gd->part[minor].nr_sects   = xd->capacity; 
  14.174 +        gd->sizes[minor]           = xd->capacity; 
  14.175  
  14.176          gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS;
  14.177 -
  14.178 -        vbd_state[device] |= VBD_KNOWN;
  14.179      }
  14.180      else
  14.181      {
  14.182          /* Some final fix-ups depending on the device type */
  14.183 -        switch ( XD_TYPE(disk->info) )
  14.184 +        switch ( XD_TYPE(xd->info) )
  14.185          { 
  14.186          case XD_TYPE_CDROM:
  14.187          case XD_TYPE_FLOPPY: 
  14.188          case XD_TYPE_TAPE:
  14.189 -            gd->part[minor].nr_sects = disk->capacity;
  14.190 -            gd->sizes[minor] = disk->capacity>>(BLOCK_SIZE_BITS-9);
  14.191 +            gd->part[minor].nr_sects = xd->capacity;
  14.192 +            gd->sizes[minor] = xd->capacity>>(BLOCK_SIZE_BITS-9);
  14.193              gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; 
  14.194              printk(KERN_ALERT 
  14.195                     "Skipping partition check on %s /dev/%s\n", 
  14.196 -                   XD_TYPE(disk->info)==XD_TYPE_CDROM ? "cdrom" : 
  14.197 -                   (XD_TYPE(disk->info)==XD_TYPE_TAPE ? "tape" : 
  14.198 +                   XD_TYPE(xd->info)==XD_TYPE_CDROM ? "cdrom" : 
  14.199 +                   (XD_TYPE(xd->info)==XD_TYPE_TAPE ? "tape" : 
  14.200                      "floppy"), disk_name(gd, MINOR(device), buf)); 
  14.201 -
  14.202 -            vbd_state[device] |= VBD_KNOWN; /* remember the VBD is there now */
  14.203              break; 
  14.204  
  14.205          case XD_TYPE_DISK:
  14.206 @@ -268,135 +295,173 @@ int xlvbd_init_device(xen_disk_t *disk)
  14.207                  break;
  14.208              }
  14.209              register_disk(gd, device, gd->max_p, &xlvbd_block_fops, 
  14.210 -                          disk->capacity);
  14.211 -
  14.212 -            vbd_state[device] |= VBD_KNOWN; /* remember the VBD is there now */
  14.213 -            
  14.214 +                          xd->capacity);            
  14.215              break; 
  14.216  
  14.217          default:
  14.218              printk(KERN_ALERT "XenoLinux: unknown device type %d\n", 
  14.219 -                   XD_TYPE(disk->info)); 
  14.220 +                   XD_TYPE(xd->info)); 
  14.221              break; 
  14.222          }
  14.223      }
  14.224  
  14.225 -    printk(KERN_ALERT "XenoLinux Virtual Block Device Driver "
  14.226 -           "installed [device: %04x]\n", device);
  14.227 -
  14.228 -    return 0;
  14.229 + out:
  14.230 +    up(&bd->bd_sem);
  14.231 +    bdput(bd);    
  14.232 +    return rc;
  14.233  }
  14.234  
  14.235  
  14.236 -/**
  14.237 - * xlvbd_remove - see if a VBD should be removed and do so if appropriate
  14.238 +/*
  14.239 + * xlvbd_remove_device - remove a device node if possible
  14.240   * @device:       numeric device ID
  14.241   *
  14.242   * Updates the gendisk structure and invalidates devices.
  14.243   *
  14.244   * This is OK for now but in future, should perhaps consider where this should
  14.245 - * deallocate gendisks / unregister devices?
  14.246 + * deallocate gendisks / unregister devices.
  14.247   */
  14.248 -int xlvbd_remove(int device)
  14.249 +static int xlvbd_remove_device(int device)
  14.250  {
  14.251 -    int major  = MAJOR(device); 
  14.252 -    int minor  = MINOR(device);
  14.253 -    int is_ide = IDE_DISK_MAJOR(major);  /* is this an ide device? */
  14.254 -    int is_scsi= SCSI_BLK_MAJOR(major);  /* is this a scsi device? */
  14.255 -    int i;                               /* loop counter */
  14.256 -    int partno;
  14.257 -    int max_part;
  14.258 -    char * major_name;
  14.259 -    
  14.260 +    int i, rc = 0, max_part, minor = MINOR(device);
  14.261      struct gendisk *gd;
  14.262 +    struct block_device *bd;
  14.263 +    xl_disk_t *disk;
  14.264 +
  14.265 +    if ( (bd = bdget(device)) == NULL )
  14.266 +        return -1;
  14.267  
  14.268 -    DPRINTK("xl_vbd.c::xlvbd_remove() - Removing a VBD\n");
  14.269 -  
  14.270 -    /* if device is in use then we shouldn't change its settings */
  14.271 -    if(xldev_to_xldisk(device)->usage)
  14.272 +    /*
  14.273 +     * Update of partition info, and check of usage count, is protected
  14.274 +     * by the per-block-device semaphore.
  14.275 +     */
  14.276 +    down(&bd->bd_sem);
  14.277 +
  14.278 +    if ( ((gd = get_gendisk(device)) == NULL) ||
  14.279 +         ((disk = xldev_to_xldisk(device)) == NULL) )
  14.280 +        BUG();
  14.281 +
  14.282 +    if ( disk->usage != 0 )
  14.283      {
  14.284 -        DPRINTK("xl_vbd.c::xlvbd_remove() - VBD in use, could not remove\n");
  14.285 -        printk(KERN_ALERT "Removing XenoLinux VBD failed - "
  14.286 -               "in use [device: %x]\n", device);
  14.287 -        return -1;
  14.288 -    }
  14.289 -
  14.290 -    if((gd = get_gendisk(device)) == NULL)
  14.291 -    {
  14.292 -        printk(KERN_ALERT
  14.293 -               "xl_vbd.c::xlvbd_remove() - ERROR could not get gendisk\n");
  14.294 -        
  14.295 -        return -1;
  14.296 +        printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device);
  14.297 +        rc = -1;
  14.298 +        goto out;
  14.299      }
  14.300  
  14.301 -    if ( is_ide )
  14.302 -    { 
  14.303 -        major_name = XLIDE_MAJOR_NAME; 
  14.304 -        max_part   = XLIDE_MAX_PART;
  14.305 -    }
  14.306 -    else if ( is_scsi )
  14.307 -    { 
  14.308 -        major_name = XLSCSI_MAJOR_NAME;
  14.309 -        max_part   = XLSCSI_MAX_PART;
  14.310 +    if ( IDE_DISK_MAJOR(MAJOR(device)) )
  14.311 +        max_part = XLIDE_MAX_PART;
  14.312 +    else if ( SCSI_BLK_MAJOR(MAJOR(device)) )
  14.313 +        max_part = XLSCSI_MAX_PART;
  14.314 +    else
  14.315 +        max_part = XLVBD_MAX_PART;
  14.316 + 
  14.317 +    if ( (minor & (max_part-1)) != 0 )
  14.318 +    {
  14.319 +        /* 1: The VBD is mapped to a partition rather than a whole unit. */
  14.320 +        invalidate_device(device, 1);
  14.321 +	gd->part[minor].start_sect = 0;
  14.322 +        gd->part[minor].nr_sects   = 0;
  14.323 +        gd->sizes[minor]           = 0;
  14.324 +
  14.325 +        /* Clear the consists-of-virtual-partitions flag if possible. */
  14.326 +        gd->flags[minor >> gd->minor_shift] &= ~GENHD_FL_VIRT_PARTNS;
  14.327 +        for ( i = 0; i < max_part; i++ )
  14.328 +            if ( gd->sizes[(minor & ~(max_part-1)) + i] != 0 )
  14.329 +                gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS;
  14.330      }
  14.331      else
  14.332 -    { 
  14.333 -        major_name = XLVBD_MAJOR_NAME;
  14.334 -        max_part   = XLVBD_MAX_PART;
  14.335 -    }
  14.336 -
  14.337 -    partno = minor & (max_part - 1); 
  14.338 -
  14.339 -    DPRINTK("Got partno = 0x%x\n", partno);
  14.340 -
  14.341 -    if(partno) /* if the VBD is mapped to a "partition" device node in Linux */
  14.342      {
  14.343 -        int should_clear_virtpart = 1; /* if this is set true we should clear
  14.344 -                                        * the GENHD_FL_VIRT_PARTNS flag in the
  14.345 -                                        * gendisk */
  14.346 -        
  14.347 -        gd->sizes[minor] = 0;
  14.348 -
  14.349 -        for(i = 0; i < max_part; i++)
  14.350 -            if(gd->sizes[minor - partno + i]) should_clear_virtpart = 0;
  14.351 -        
  14.352 -        /* if there aren't any virtual partitions here then clear the flag for
  14.353 -         * this unit */
  14.354 -        if(should_clear_virtpart)
  14.355 -        {
  14.356 -            gd->flags[minor >> gd->minor_shift] &= ~GENHD_FL_VIRT_PARTNS;
  14.357 -
  14.358 -            DPRINTK("xl_vbd.c::xlvbd_remove() - "
  14.359 -                    "cleared virtual partition flag\n");
  14.360 -        }
  14.361 -        
  14.362 -	gd->part[MINOR(device)].start_sect = 0;
  14.363 -        gd->part[MINOR(device)].nr_sects   = 0;
  14.364 -        gd->sizes[MINOR(device)]           = 0;
  14.365 -        
  14.366 -        invalidate_device(device, 1);
  14.367 -
  14.368 -        vbd_state[device] &= ~VBD_KNOWN; /* forget VBD was ever there */
  14.369 -    }
  14.370 -    else /* the VBD is mapped to a "whole disk drive" device node in Linux */
  14.371 -    {
  14.372 +        /* 2: The VBD is mapped to an entire 'unit'. Clear all partitions. */
  14.373          for ( i = max_part - 1; i >= 0; i-- )
  14.374          {
  14.375              invalidate_device(device+i, 1);
  14.376 -            gd->part[MINOR(device+i)].start_sect = 0;
  14.377 -            gd->part[MINOR(device+i)].nr_sects   = 0;
  14.378 -            gd->sizes[MINOR(device+i)]           = 0;
  14.379 -            
  14.380 -            vbd_state[device+i] &= ~VBD_KNOWN; /* forget VBD was ever there */
  14.381 +            gd->part[minor+i].start_sect = 0;
  14.382 +            gd->part[minor+i].nr_sects   = 0;
  14.383 +            gd->sizes[minor+i]           = 0;
  14.384          }
  14.385      }
  14.386  
  14.387 -    printk(KERN_ALERT "XenoLinux Virtual Block Device removed "
  14.388 -           " [device: %04x]\n", device);
  14.389 -    return 0;
  14.390 + out:
  14.391 +    up(&bd->bd_sem);
  14.392 +    bdput(bd);
  14.393 +    return rc;
  14.394  }
  14.395  
  14.396  /*
  14.397 + * xlvbd_update_vbds - reprobes the VBD status and performs updates driver
  14.398 + * state. The VBDs need to be updated in this way when the domain is
  14.399 + * initialised and also each time we receive an XLBLK_UPDATE event.
  14.400 + */
  14.401 +void xlvbd_update_vbds(void)
  14.402 +{
  14.403 +    int i, j, k, old_nr, new_nr;
  14.404 +    xen_disk_t *old_info, *new_info, *merged_info;
  14.405 +
  14.406 +    old_info = vbd_info;
  14.407 +    old_nr   = nr_vbds;
  14.408 +
  14.409 +    new_info = kmalloc(MAX_VBDS * sizeof(xen_disk_t), GFP_KERNEL);
  14.410 +    if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
  14.411 +    {
  14.412 +        kfree(new_info);
  14.413 +        return;
  14.414 +    }
  14.415 +
  14.416 +    /*
  14.417 +     * Final list maximum size is old list + new list. This occurs only when
  14.418 +     * old list and new list do not overlap at all, and we cannot yet destroy
  14.419 +     * VBDs in the old list because the usage counts are busy.
  14.420 +     */
  14.421 +    merged_info = kmalloc((old_nr + new_nr) * sizeof(xen_disk_t), GFP_KERNEL);
  14.422 +
  14.423 +    /* @i tracks old list; @j tracks new list; @k tracks merged list. */
  14.424 +    i = j = k = 0;
  14.425 +
  14.426 +    while ( (i < old_nr) && (j < new_nr) )
  14.427 +    {
  14.428 +        if ( old_info[i].device < new_info[j].device )
  14.429 +        {
  14.430 +            if ( xlvbd_remove_device(old_info[i].device) != 0 )
  14.431 +                memcpy(&merged_info[k++], &old_info[i], sizeof(xen_disk_t));
  14.432 +            i++;
  14.433 +        }
  14.434 +        else if ( old_info[i].device > new_info[j].device )
  14.435 +        {
  14.436 +            if ( xlvbd_init_device(&new_info[j]) == 0 )
  14.437 +                memcpy(&merged_info[k++], &new_info[j], sizeof(xen_disk_t));
  14.438 +            j++;
  14.439 +        }
  14.440 +        else
  14.441 +        {
  14.442 +            if ( xlvbd_init_device(&new_info[j]) == 0 )
  14.443 +                memcpy(&merged_info[k++], &new_info[j], sizeof(xen_disk_t));
  14.444 +            else
  14.445 +                memcpy(&merged_info[k++], &old_info[i], sizeof(xen_disk_t));
  14.446 +            i++; j++;
  14.447 +        }
  14.448 +    }
  14.449 +
  14.450 +    for ( ; i < old_nr; i++ )
  14.451 +    {
  14.452 +        if ( xlvbd_remove_device(old_info[i].device) != 0 )
  14.453 +            memcpy(&merged_info[k++], &old_info[i], sizeof(xen_disk_t));
  14.454 +    }
  14.455 +
  14.456 +    for ( ; j < new_nr; j++ )
  14.457 +    {
  14.458 +        if ( xlvbd_init_device(&new_info[j]) == 0 )
  14.459 +            memcpy(&merged_info[k++], &new_info[j], sizeof(xen_disk_t));
  14.460 +    }
  14.461 +
  14.462 +    vbd_info = merged_info;
  14.463 +    nr_vbds  = k;
  14.464 +
  14.465 +    kfree(old_info);
  14.466 +    kfree(new_info);
  14.467 +}
  14.468 +
  14.469 +
  14.470 +/*
  14.471   * Set up all the linux device goop for the virtual block devices (vbd's) that 
  14.472   * xen tells us about. Note that although from xen's pov VBDs are addressed 
  14.473   * simply an opaque 16-bit device number, the domain creation tools 
  14.474 @@ -404,17 +469,18 @@ int xlvbd_remove(int device)
  14.475   * linux -- this is just for convenience as it means e.g. that the same 
  14.476   * /etc/fstab can be used when booting with or without xen.
  14.477   */
  14.478 -int __init xlvbd_init(xen_disk_info_t *xdi)
  14.479 +int __init xlvbd_init(void)
  14.480  {
  14.481 -    int i; /* loop counter */
  14.482 +    int i;
  14.483      
  14.484 +    /*
  14.485 +     * If compiled as a module, we don't support unloading yet. We therefore 
  14.486 +     * permanently increment the reference count to disallow it.
  14.487 +     */
  14.488      SET_MODULE_OWNER(&xlvbd_block_fops);
  14.489 +    MOD_INC_USE_COUNT;
  14.490  
  14.491      /* Initialize the global arrays. */
  14.492 -
  14.493 -    for( i = 0; i < 65536; i++)
  14.494 -        vbd_state[i] = VBD_NODEV;
  14.495 -
  14.496      for ( i = 0; i < 256; i++ ) 
  14.497      {
  14.498          /* from the generic ide code (drivers/ide/ide-probe.c, etc) */
  14.499 @@ -433,186 +499,25 @@ int __init xlvbd_init(xen_disk_info_t *x
  14.500          xlvbd_max_sectors[i]   = 128;
  14.501      }
  14.502  
  14.503 -    /*
  14.504 -     * We need to loop through each major device we've been told about and: 
  14.505 -     * a) register the appropriate blkdev 
  14.506 -     * b) setup the indexed-by-major global arrays (blk_size[], 
  14.507 -     *    blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) 
  14.508 -     * c) setup the block queue + make it sensible
  14.509 -     * d) create an appropriate gendisk structure, and 
  14.510 -     * e) register the gendisk 
  14.511 -     */
  14.512 -    for ( i = 0; i < xdi->count; i++ )
  14.513 +    vbd_info = kmalloc(MAX_VBDS * sizeof(xen_disk_t), GFP_KERNEL);
  14.514 +    nr_vbds  = xlvbd_get_vbd_info(vbd_info);
  14.515 +
  14.516 +    if ( nr_vbds < 0 )
  14.517      {
  14.518 -        xlvbd_init_device(&xdi->disks[i]);
  14.519 +        kfree(vbd_info);
  14.520 +        vbd_info = NULL;
  14.521 +        nr_vbds  = 0;
  14.522 +    }
  14.523 +    else
  14.524 +    {
  14.525 +        for ( i = 0; i < nr_vbds; i++ )
  14.526 +            xlvbd_init_device(&vbd_info[i]);
  14.527      }
  14.528  
  14.529      return 0;
  14.530  }
  14.531  
  14.532 -/**
  14.533 - * xlvbd_update_vbds - reprobes the VBD status and performs updates driver state
  14.534 - *
  14.535 - * The VBDs need to be updated in this way when the domain is initialised and
  14.536 - * also each time we receive an XLBLK_UPDATE event.
  14.537 - *
  14.538 - * The vbd_state array is consistent on entry to and exit from this function but
  14.539 - * not whilst the function runs, so this should not be called re-entrantly.
  14.540 - */
  14.541 -void xlvbd_update_vbds(void)
  14.542 -{
  14.543 -    int i;            /* loop counter       */
  14.544 -    int ret;          /* return values      */
  14.545 -    block_io_op_t op; /* for talking to Xen */
  14.546 -
  14.547 -    xen_disk_info_t *xdi = &xlblk_disk_info; /* pointer to structures in
  14.548 -                                              * xl_block.c */
  14.549 -
  14.550 -    /* Probe for disk information. */
  14.551 -    memset(&op, 0, sizeof(op)); 
  14.552 -    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
  14.553 -    op.u.probe_params.domain = 0;
  14.554 -    
  14.555 -    xdi->count = 0; /* need to keep resetting this to zero because the probe
  14.556 -                     * will append results after "used" space in the array */
  14.557 -
  14.558 -    memcpy(&op.u.probe_params.xdi, &xlblk_disk_info, sizeof(xlblk_disk_info)); 
  14.559 -
  14.560 -    ret = HYPERVISOR_block_io_op(&op);
  14.561 -    
  14.562 -    if ( ret )
  14.563 -    {
  14.564 -        printk(KERN_ALERT "Could not probe disks (%d)\n", ret);
  14.565 -    }
  14.566 -
  14.567 -    /* copy back the [updated] count parameter */
  14.568 -    xlblk_disk_info.count = op.u.probe_params.xdi.count;
  14.569 -
  14.570 -    DPRINTK("Retrieved %d disks\n",op.u.probe_params.xdi.count);
  14.571 -    
  14.572 -    
  14.573 -    for( i = 0; i < 65536; i++ )
  14.574 -        vbd_state[i] |= VBD_NODEV;
  14.575 -    
  14.576 -    for( i = 0; i < xdi->count; i++ )
  14.577 -    {
  14.578 -        int device = xdi->disks[i].device;
  14.579 -        xl_disk_t *d;
  14.580 -
  14.581 -        vbd_state[device] &= ~VBD_NODEV;
  14.582 -
  14.583 -        DPRINTK("Inspecting xen_disk_t: device = %hx, info = %hx, "
  14.584 -                "capacity = %lx, domain = %d\n",
  14.585 -                xdi->disks[i].device, xdi->disks[i].info, xdi->disks[i].capacity,
  14.586 -                xdi->disks[i].domain); 
  14.587 -
  14.588 -        if(xdi->disks[i].info & XD_FLAG_VIRT)
  14.589 -        {
  14.590 -            /* RACE: need to fix this for SMP / pre-emptive kernels */
  14.591 -
  14.592 -            d = xldev_to_xldisk(device);
  14.593 -
  14.594 -            /* only go on to monkey with this stuff if we successfully got the
  14.595 -            * xldisk and it says no-one else is using the disk OR if we didn't
  14.596 -            * successfully retrieve the xldisk (so it doesn't exist and nobody
  14.597 -            * can be using it), otherwise skip on to the next device */
  14.598 -            if(d != NULL && d->usage > 0)
  14.599 -            {
  14.600 -                printk(KERN_ALERT "XenoLinux VBD Driver: "
  14.601 -                    "skipping update in a disk currently in use");
  14.602 -                DPRINTK("Usage = %d\n", d->usage);
  14.603 -                continue; /* skip to next device */
  14.604 -            }
  14.605 -            
  14.606 -            printk(KERN_ALERT "XenoLinux VBD Driver: updating a VBD "
  14.607 -                   "[device: %x]\n", device);
  14.608 -            /* also takes care of any overrides (i.e. due to VBDs mapped to
  14.609 -             * partitions overriding VBDs mapped to disks) and of registering
  14.610 -             * disks */
  14.611 -            xlvbd_init_device(xdi->disks + i);
  14.612 -        }
  14.613 -        
  14.614 -    }
  14.615 -
  14.616 -    for( i = 0; i < 65536; i++ )
  14.617 -    {
  14.618 -        switch(vbd_state[i])
  14.619 -        {
  14.620 -        case VBD_NODEV | VBD_KNOWN: /* a VBD we knew about before has gone */
  14.621 -           
  14.622 -            DPRINTK("About to remove VBD 0x%x\n",i);
  14.623 -               
  14.624 -            ret = xlvbd_remove(i);
  14.625 -
  14.626 -            if(ret) DPRINTK("Failed to remove VBD\n");
  14.627 -
  14.628 -            break;
  14.629 -
  14.630 -        case VBD_NODEV: /* there's nothing here and there wasn't anything
  14.631 -                         * before */
  14.632 -            break;
  14.633 -            
  14.634 -        case VBD_KNOWN: /* the device is present and it's set up */
  14.635 -            break;
  14.636 -
  14.637 -        case 0:         /* there's a device present we haven't set up - either
  14.638 -                         * one of the "non virtual" VBDs or we weren't able to
  14.639 -                         * update it because it was mounted */
  14.640 -            break;
  14.641 -
  14.642 -        default:        /* if there's any other weird combination, something
  14.643 -                         * unexpected is happening */
  14.644 -            printk(KERN_ALERT "xl_vbd.c::xlvbd_update_vbds: BUG - Unknown state "
  14.645 -                   "when updating VBDs: 0x%x\n", vbd_state[i]);
  14.646 -        }
  14.647 -    }
  14.648 -
  14.649 -}
  14.650 -
  14.651 -void xlvbd_cleanup(void)
  14.652 -{
  14.653 -    int is_ide, is_scsi, i; 
  14.654 -    struct gendisk *gd; 
  14.655 -    char *major_name; 
  14.656 -    int major; 
  14.657 -
  14.658 -    for ( major = 0; major < MAX_BLKDEV; major++ )
  14.659 -    {
  14.660 -        if ( (gd = get_gendisk(MKDEV(major, 0))) == NULL )
  14.661 -            continue; 
  14.662 -
  14.663 -        /*
  14.664 -         * If this is a 'Xeno' blkdev then at least one unit will have the Xeno
  14.665 -         * flag set.
  14.666 -         */
  14.667 -        for ( i = 0; i < gd->nr_real; i++ )
  14.668 -            if ( gd->flags[i] & GENHD_FL_XENO )
  14.669 -                break;
  14.670 -        if ( i == gd->nr_real )
  14.671 -            continue;
  14.672 -        
  14.673 -        is_ide  = IDE_DISK_MAJOR(major);  /* is this an ide device? */
  14.674 -        is_scsi = SCSI_BLK_MAJOR(major);  /* is this a scsi device? */
  14.675 -
  14.676 -        blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); 
  14.677 -
  14.678 -        if ( is_ide ) 
  14.679 -            major_name = XLIDE_MAJOR_NAME; 
  14.680 -        else if ( is_scsi )
  14.681 -            major_name = XLSCSI_MAJOR_NAME;
  14.682 -        else 
  14.683 -            major_name = XLVBD_MAJOR_NAME;
  14.684 -
  14.685 -        if ( unregister_blkdev(major, major_name) != 0 ) 
  14.686 -            printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:"
  14.687 -                   "major device %04x uninstalled w/ errors\n", major);
  14.688 -
  14.689 -        /* XXX shouldn't we remove the gendisk from the kernel linked list and
  14.690 -         * deallocate the memory here? */
  14.691 -    }
  14.692 -}
  14.693  
  14.694  #ifdef MODULE
  14.695  module_init(xlvbd_init);
  14.696 -module_exit(xlvbd_cleanup);
  14.697  #endif
    15.1 --- a/xenolinux-2.4.24-sparse/include/asm-xeno/hypervisor.h	Wed Jan 14 18:05:25 2004 +0000
    15.2 +++ b/xenolinux-2.4.24-sparse/include/asm-xeno/hypervisor.h	Thu Jan 15 19:13:38 2004 +0000
    15.3 @@ -230,7 +230,7 @@ static inline int HYPERVISOR_net_io_op(n
    15.4      __asm__ __volatile__ (
    15.5          TRAP_INSTR
    15.6          : "=a" (ret) : "0" (__HYPERVISOR_net_io_op),
    15.7 -        "b" (op) );
    15.8 +        "b" (op) : "memory" );
    15.9  
   15.10      return ret;
   15.11  }
   15.12 @@ -297,18 +297,18 @@ static inline int HYPERVISOR_network_op(
   15.13      __asm__ __volatile__ (
   15.14          TRAP_INSTR
   15.15          : "=a" (ret) : "0" (__HYPERVISOR_network_op),
   15.16 -        "b" (network_op) );
   15.17 +        "b" (network_op) : "memory" );
   15.18  
   15.19      return ret;
   15.20  }
   15.21  
   15.22 -static inline int HYPERVISOR_block_io_op(void * block_io_op)
   15.23 +static inline int HYPERVISOR_block_io_op(void *block_io_op)
   15.24  {
   15.25      int ret;
   15.26      __asm__ __volatile__ (
   15.27          TRAP_INSTR
   15.28          : "=a" (ret) : "0" (__HYPERVISOR_block_io_op),
   15.29 -        "b" (block_io_op) ); 
   15.30 +        "b" (block_io_op) : "memory" ); 
   15.31  
   15.32      return ret;
   15.33  }