ia64/xen-unstable

changeset 248:6c2320ec1f38

bitkeeper revision 1.100.1.1 (3e5d12a9XS1t15We3dHlj4sxiwEeWQ)

add create segment code in xen,
/proc/xeno/dom0/vhd in xenolinux
author ach61@labyrinth.cl.cam.ac.uk
date Wed Feb 26 19:16:57 2003 +0000 (2003-02-26)
parents 7b3edf42feae
children 3cc17656be66
files .rootkeys BitKeeper/etc/logging_ok xen/Makefile xen/drivers/block/xen_block.c xen/drivers/block/xen_segment.c xen/drivers/ide/ide-xeno.c xen/include/hypervisor-ifs/block.h xen/include/xeno/sched.h xen/include/xeno/segment.h xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c
line diff
     1.1 --- a/.rootkeys	Mon Feb 24 23:45:39 2003 +0000
     1.2 +++ b/.rootkeys	Wed Feb 26 19:16:57 2003 +0000
     1.3 @@ -249,6 +249,7 @@ 3ddb79beME_0abStePF6fU8XLuQnWw xen/drive
     1.4  3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c
     1.5  3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
     1.6  3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
     1.7 +3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
     1.8  3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
     1.9  3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c
    1.10  3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/xen_serial.c
    1.11 @@ -438,6 +439,7 @@ 3e54c38de9SUSYSAwxDf_DwkpAnQFA xen/inclu
    1.12  3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xeno/prefetch.h
    1.13  3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h
    1.14  3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h
    1.15 +3e5d129a2bbGTpVSZFN_mAnbm97ixw xen/include/xeno/segment.h
    1.16  3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h
    1.17  3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h
    1.18  3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h
    1.19 @@ -466,6 +468,7 @@ 3e5a4e65TNEycLeXqPSXQJQm_xGecA xenolinux
    1.20  3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
    1.21  3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
    1.22  3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
    1.23 +3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
    1.24  3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/Makefile
    1.25  3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/console.c
    1.26  3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/Makefile
     2.1 --- a/BitKeeper/etc/logging_ok	Mon Feb 24 23:45:39 2003 +0000
     2.2 +++ b/BitKeeper/etc/logging_ok	Wed Feb 26 19:16:57 2003 +0000
     2.3 @@ -1,3 +1,4 @@
     2.4 +ach61@labyrinth.cl.cam.ac.uk
     2.5  akw27@boulderdash.cl.cam.ac.uk
     2.6  akw27@labyrinth.cl.cam.ac.uk
     2.7  akw27@plucky.localdomain
     3.1 --- a/xen/Makefile	Mon Feb 24 23:45:39 2003 +0000
     3.2 +++ b/xen/Makefile	Wed Feb 26 19:16:57 2003 +0000
     3.3 @@ -39,3 +39,5 @@ TAGS:
     3.4  	find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
     3.5  	find $(SUBDIRS) -name '*.[ch]' | xargs etags -a
     3.6  
     3.7 +MAP:
     3.8 +	nm image | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
     4.1 --- a/xen/drivers/block/xen_block.c	Mon Feb 24 23:45:39 2003 +0000
     4.2 +++ b/xen/drivers/block/xen_block.c	Wed Feb 26 19:16:57 2003 +0000
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * xen-block.c
     4.6 + * xen_block.c
     4.7   *
     4.8   * process incoming block io requests from guestos's.
     4.9   */
    4.10 @@ -16,6 +16,7 @@
    4.11  #include <asm/spinlock.h>
    4.12  #include <xeno/keyhandler.h>
    4.13  #include <xeno/interrupt.h>
    4.14 +#include <xeno/segment.h>
    4.15  
    4.16  #if 0
    4.17  #define DPRINTK(_f, _a...) printk( _f , ## _a )
    4.18 @@ -42,7 +43,10 @@ static int do_block_io_op_domain(struct 
    4.19  static void dispatch_rw_block_io(struct task_struct *p, int index);
    4.20  static void dispatch_probe_block_io(struct task_struct *p, int index);
    4.21  static void dispatch_debug_block_io(struct task_struct *p, int index);
    4.22 -static void make_response(struct task_struct *p, void *id, unsigned long st);
    4.23 +static void dispatch_create_segment(struct task_struct *p, int index);
    4.24 +static void dispatch_delete_segment(struct task_struct *p, int index);
    4.25 +static void make_response(struct task_struct *p, void *id, int op, 
    4.26 +			  unsigned long st);
    4.27  
    4.28  
    4.29  /******************************************************************
    4.30 @@ -149,7 +153,8 @@ static void end_block_io_op(struct buffe
    4.31      }
    4.32  
    4.33      atomic_dec(&nr_pending);
    4.34 -    make_response(bh->b_xen_domain, bh->b_xen_id, uptodate ? 0 : 1);
    4.35 +    make_response(bh->b_xen_domain, bh->b_xen_id, 
    4.36 +		  XEN_BLOCK_READ, uptodate ? 0 : 1);
    4.37  
    4.38      kmem_cache_free(buffer_head_cachep, bh);
    4.39  
    4.40 @@ -205,6 +210,14 @@ static int do_block_io_op_domain(struct 
    4.41  	    dispatch_debug_block_io(p, i);
    4.42  	    break;
    4.43  
    4.44 +	case XEN_BLOCK_SEG_CREATE:
    4.45 +	    dispatch_create_segment(p, i);
    4.46 +	    break;
    4.47 +
    4.48 +	case XEN_BLOCK_SEG_DELETE:
    4.49 +	    dispatch_delete_segment(p, i);
    4.50 +	    break;
    4.51 +
    4.52  	default:
    4.53  	    panic("error: unknown block io operation [%d]\n",
    4.54                    blk_ring->ring[i].req.operation);
    4.55 @@ -220,16 +233,43 @@ static void dispatch_debug_block_io(stru
    4.56      DPRINTK("dispatch_debug_block_io: unimplemented\n"); 
    4.57  }
    4.58  
    4.59 +static void dispatch_create_segment(struct task_struct *p, int index)
    4.60 +{
    4.61 +  blk_ring_t *blk_ring = p->blk_ring_base;
    4.62 +  xv_disk_t *xvd;
    4.63 +  int result;
    4.64 +
    4.65 +  if (p->domain != 0)
    4.66 +  {
    4.67 +    printk (KERN_ALERT "dispatch_create_segment called by dom%d\n", p->domain);
    4.68 +    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1); 
    4.69 +    return;
    4.70 +  }
    4.71 +
    4.72 +  xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);    
    4.73 +  result = xen_segment_create(xvd);
    4.74 +  make_response(p, blk_ring->ring[index].req.id, 
    4.75 +		XEN_BLOCK_SEG_CREATE, result); 
    4.76 +  return;
    4.77 +}
    4.78 +
    4.79 +static void dispatch_delete_segment(struct task_struct *p, int index)
    4.80 +{
    4.81 +    DPRINTK("dispatch_delete_segment: unimplemented\n"); 
    4.82 +}
    4.83 +
    4.84  static void dispatch_probe_block_io(struct task_struct *p, int index)
    4.85  {
    4.86 -    extern void ide_probe_devices(xen_disk_info_t *xdi);
    4.87 +    extern void ide_probe_devices(xen_disk_info_t *xdi, int *count, 
    4.88 +				  drive_t xdrives[]);
    4.89      blk_ring_t *blk_ring = p->blk_ring_base;
    4.90      xen_disk_info_t *xdi;
    4.91  
    4.92      xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);    
    4.93 -    ide_probe_devices(xdi);
    4.94 +    ide_probe_devices(xdi, &num_xdrives, xdrives);
    4.95 +    /* scsi_probe_devices(xdi, &num_xdrives, xdrives); */          /* future */
    4.96  
    4.97 -    make_response(p, blk_ring->ring[index].req.id, 0);
    4.98 +    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, 0);
    4.99  }
   4.100  
   4.101  static void dispatch_rw_block_io(struct task_struct *p, int index)
   4.102 @@ -333,9 +373,9 @@ static void dispatch_rw_block_io(struct 
   4.103      return;
   4.104  
   4.105   bad_descriptor:
   4.106 -    make_response(p, blk_ring->ring[index].req.id, 1);
   4.107 +    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_READ, 1);
   4.108      return;
   4.109 -}
   4.110 +} 
   4.111  
   4.112  
   4.113  
   4.114 @@ -343,7 +383,8 @@ static void dispatch_rw_block_io(struct 
   4.115   * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
   4.116   */
   4.117  
   4.118 -static void make_response(struct task_struct *p, void *id, unsigned long st)
   4.119 +static void make_response(struct task_struct *p, void *id, 
   4.120 +			  int op, unsigned long st)
   4.121  {
   4.122      unsigned long cpu_mask, flags;
   4.123      int position;
   4.124 @@ -353,8 +394,9 @@ static void make_response(struct task_st
   4.125      spin_lock_irqsave(&p->blk_ring_lock, flags);
   4.126      blk_ring = p->blk_ring_base;
   4.127      position = blk_ring->resp_prod;
   4.128 -    blk_ring->ring[position].resp.id     = id;
   4.129 -    blk_ring->ring[position].resp.status = st;
   4.130 +    blk_ring->ring[position].resp.id        = id;
   4.131 +    blk_ring->ring[position].resp.operation = op;
   4.132 +    blk_ring->ring[position].resp.status    = st;
   4.133      blk_ring->resp_prod = BLK_RING_INC(position);
   4.134      spin_unlock_irqrestore(&p->blk_ring_lock, flags);
   4.135      
   4.136 @@ -377,6 +419,7 @@ void init_blkdev_info(struct task_struct
   4.137      clear_page(p->blk_ring_base);
   4.138      SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p->domain);
   4.139      p->blkdev_list.next = NULL;
   4.140 +    p->segment_count = 0;
   4.141  }
   4.142  
   4.143  /* End-of-day teardown for a domain. XXX Outstanding requests? */
   4.144 @@ -397,6 +440,8 @@ void initialize_block_io ()
   4.145      buffer_head_cachep = kmem_cache_create(
   4.146          "buffer_head_cache", sizeof(struct buffer_head),
   4.147          0, SLAB_HWCACHE_ALIGN, NULL, NULL);
   4.148 +
   4.149 +    xen_segment_initialize();
   4.150      
   4.151      add_key_handler('b', dump_blockq, "dump xen ide blkdev stats");     
   4.152  }
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/drivers/block/xen_segment.c	Wed Feb 26 19:16:57 2003 +0000
     5.3 @@ -0,0 +1,137 @@
     5.4 +/*
     5.5 + * xen_segment.c
     5.6 + */
     5.7 +
     5.8 +#include <xeno/config.h>
     5.9 +#include <xeno/types.h>
    5.10 +#include <xeno/lib.h>
    5.11 +#include <asm/io.h>
    5.12 +#include <xeno/slab.h>
    5.13 +#include <xeno/segment.h>
    5.14 +#include <xeno/sched.h>
    5.15 +#include <xeno/keyhandler.h>
    5.16 +#include <hypervisor-ifs/block.h>
    5.17 +
    5.18 +int     num_xdrives;
    5.19 +drive_t xdrives[XEN_MAX_DISK_COUNT];
    5.20 +
    5.21 +segment_t xsegments[XEN_MAX_SEGMENTS];
    5.22 +
    5.23 +/*
    5.24 + * xen_refresh_segment_list
    5.25 + *
    5.26 + * find all segments associated with a domain and assign
    5.27 + * them to the domain
    5.28 + */
    5.29 +void xen_refresh_segment_list (struct task_struct *p)
    5.30 +{
    5.31 +  int loop;
    5.32 +
    5.33 +  for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
    5.34 +  {
    5.35 +    if (xsegments[loop].mode != XEN_SEGMENT_UNUSED &&
    5.36 +	xsegments[loop].domain == p->domain)
    5.37 +    {
    5.38 +      p->segment_list[xsegments[loop].segment_number] = &xsegments[loop];
    5.39 +      p->segment_count++;
    5.40 +    }
    5.41 +  }
    5.42 +  return;
    5.43 +}
    5.44 +
    5.45 +/*
    5.46 + * create a new segment for a domain
    5.47 + *
    5.48 + * return 0 on success, 1 on failure
    5.49 + *
    5.50 + * TODO: need to check to see if the DOM#/SEG# combination
    5.51 + *       already exists. if so, reuse the slot in the segment table.
    5.52 + */
    5.53 +int xen_segment_create(xv_disk_t *xvd_in)
    5.54 +{
    5.55 +  int idx;
    5.56 +  int loop;
    5.57 +  xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
    5.58 +
    5.59 +  for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++)
    5.60 +  {
    5.61 +    if (xsegments[idx].mode == XEN_SEGMENT_UNUSED) break;
    5.62 +  }
    5.63 +  if (idx == XEN_MAX_SEGMENTS)
    5.64 +  {
    5.65 +    printk (KERN_ALERT "error: xen_segment_create unable to find free slot\n");
    5.66 +    return 1;
    5.67 +  }
    5.68 +
    5.69 +  xsegments[idx].mode = xvd->mode;
    5.70 +  xsegments[idx].domain = xvd->domain;
    5.71 +  xsegments[idx].segment_number = xvd->segment;
    5.72 +  xsegments[idx].num_extents = xvd->ext_count;
    5.73 +  xsegments[idx].extents = (extent_t *)kmalloc(sizeof(extent_t)*xvd->ext_count,
    5.74 +					       GFP_KERNEL);
    5.75 + 
    5.76 +  /* could memcpy, but this is safer */
    5.77 +  for (loop = 0; loop < xvd->ext_count; loop++)
    5.78 +  {
    5.79 +    xsegments[idx].extents[loop].disk = xvd->extents[loop].disk;
    5.80 +    xsegments[idx].extents[loop].offset = xvd->extents[loop].offset;
    5.81 +    xsegments[idx].extents[loop].size = xvd->extents[loop].size;
    5.82 +  }
    5.83 +
    5.84 +  return 0;
    5.85 +}
    5.86 +
    5.87 +/*
    5.88 + * delete a segment from a domain
    5.89 + *
    5.90 + * return 0 on success, 1 on failure
    5.91 + *
    5.92 + * TODO: caller must ensure that only domain 0 calls this function
    5.93 + */
    5.94 +int xen_segment_delete(struct task_struct *p, xv_disk_t *xvd)
    5.95 +{
    5.96 +  return 0;
    5.97 +}
    5.98 +
    5.99 +static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs) 
   5.100 +{
   5.101 +  int loop, i;
   5.102 +
   5.103 +  printk (KERN_ALERT "xdrives\n");
   5.104 +  for (loop = 0; loop < num_xdrives; loop++)
   5.105 +  {
   5.106 +    printk (KERN_ALERT " %2d: major: 0x%d\n", loop, xdrives[loop].major);
   5.107 +  }
   5.108 +  
   5.109 +  printk (KERN_ALERT "segments\n");
   5.110 +  for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
   5.111 +  {
   5.112 +    if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
   5.113 +    {
   5.114 +      printk (KERN_ALERT " %2d: %s dom%d, seg# %d, num_exts: %d\n",
   5.115 +	      loop, 
   5.116 +	      xsegments[loop].mode == XEN_SEGMENT_RO ? "RO" : "RW",
   5.117 +	      xsegments[loop].domain, xsegments[loop].segment_number,
   5.118 +	      xsegments[loop].num_extents);
   5.119 +      for (i = 0; i < xsegments[loop].num_extents; i++)
   5.120 +      {
   5.121 +	printk (KERN_ALERT "     ext %d: disk %d, offset 0x%lx, size 0x%lx\n",
   5.122 +		i, xsegments[loop].extents[i].disk,
   5.123 +		xsegments[loop].extents[i].offset,
   5.124 +		xsegments[loop].extents[i].size);
   5.125 +      } 
   5.126 +    }
   5.127 +  }
   5.128 +}
   5.129 +
   5.130 +/*
   5.131 + * initialize segments
   5.132 + */
   5.133 +
   5.134 +void xen_segment_initialize(void)
   5.135 +{
   5.136 +  memset (xdrives, 0, sizeof(xdrives));
   5.137 +  memset (xsegments, 0, sizeof(xsegments));
   5.138 +
   5.139 +  add_key_handler('S', dump_segments, "dump segments");
   5.140 +}
     6.1 --- a/xen/drivers/ide/ide-xeno.c	Mon Feb 24 23:45:39 2003 +0000
     6.2 +++ b/xen/drivers/ide/ide-xeno.c	Wed Feb 26 19:16:57 2003 +0000
     6.3 @@ -2,11 +2,12 @@
     6.4  #include <xeno/types.h>
     6.5  #include <xeno/lib.h>
     6.6  #include <xeno/ide.h>
     6.7 +#include <xeno/segment.h>
     6.8  #include <hypervisor-ifs/block.h>
     6.9  #include <asm/domain_page.h>
    6.10  #include <asm/io.h>
    6.11  
    6.12 -void ide_probe_devices (xen_disk_info_t* xdi)
    6.13 +void ide_probe_devices (xen_disk_info_t* xdi, int *count, drive_t xdrives[])
    6.14  {
    6.15      int loop;
    6.16      unsigned int unit;
    6.17 @@ -21,21 +22,27 @@ void ide_probe_devices (xen_disk_info_t*
    6.18  		unsigned long capacity;
    6.19  		ide_drive_t *drive = &hwif->drives[unit];
    6.20  
    6.21 -		if (drive->present) {
    6.22 -		    capacity = current_capacity (drive);
    6.23 +		/* only count drives with capacity > 0. this excludes cdroms */
    6.24 +		if (drive->present && (capacity = current_capacity(drive)))
    6.25 +		{
    6.26  		    xen_xdi->disks[xen_xdi->count].type = XEN_DISK_IDE;
    6.27  		    xen_xdi->disks[xen_xdi->count].capacity = capacity;
    6.28 +		    xdrives[xen_xdi->count].major = hwif->major;
    6.29  		    xen_xdi->count++;
    6.30  
    6.31 +		    /*
    6.32  		    printk (KERN_ALERT "IDE-XENO %d\n", xen_xdi->count);
    6.33  		    printk (KERN_ALERT "  capacity 0x%lx\n", capacity);
    6.34  		    printk (KERN_ALERT "  head     0x%x\n",  drive->bios_head);
    6.35  		    printk (KERN_ALERT "  sector   0x%x\n",  drive->bios_sect);
    6.36  		    printk (KERN_ALERT "  cylinder 0x%x\n",  drive->bios_cyl);
    6.37 +		    printk (KERN_ALERT "  major    0x%x\n",  hwif->major);
    6.38 +		    */
    6.39  		}
    6.40  	    }
    6.41  	}
    6.42      }
    6.43 +    *count = xen_xdi->count;
    6.44  
    6.45      unmap_domain_mem(xen_xdi);
    6.46  }
     7.1 --- a/xen/include/hypervisor-ifs/block.h	Mon Feb 24 23:45:39 2003 +0000
     7.2 +++ b/xen/include/hypervisor-ifs/block.h	Wed Feb 26 19:16:57 2003 +0000
     7.3 @@ -1,10 +1,7 @@
     7.4  /******************************************************************************
     7.5   * block.h
     7.6   *
     7.7 - * Block IO communication rings.
     7.8 - *
     7.9 - * These are the ring data structures for buffering messages between 
    7.10 - * the hypervisor and guestos's.  
    7.11 + * shared structures for block IO.
    7.12   *
    7.13   */
    7.14  
    7.15 @@ -13,6 +10,13 @@
    7.16  
    7.17  #include <linux/kdev_t.h>
    7.18  
    7.19 +/*
    7.20 + *
    7.21 + * These are the ring data structures for buffering messages between 
    7.22 + * the hypervisor and guestos's.  
    7.23 + *
    7.24 + */
    7.25 +
    7.26  /* the first four definitions match fs.h */
    7.27  #define XEN_BLOCK_READ  0
    7.28  #define XEN_BLOCK_WRITE 1
    7.29 @@ -20,6 +24,8 @@
    7.30  #define XEN_BLOCK_SPECIAL 4                              /* currently unused */
    7.31  #define XEN_BLOCK_PROBE 8      /* determine io configuration from hypervisor */
    7.32  #define XEN_BLOCK_DEBUG 16                                          /* debug */
    7.33 +#define XEN_BLOCK_SEG_CREATE 32                      /* create segment (vhd) */
    7.34 +#define XEN_BLOCK_SEG_DELETE 64                      /* delete segment (vhd) */
    7.35  
    7.36  #define BLK_RING_SIZE        128
    7.37  #define BLK_RING_MAX_ENTRIES (BLK_RING_SIZE - 2)
    7.38 @@ -29,7 +35,7 @@
    7.39  typedef struct blk_ring_req_entry 
    7.40  {
    7.41      void *          id;                /* for guest os use */
    7.42 -    int             operation;         /* XEN_BLOCK_READ or XEN_BLOCK_WRITE */
    7.43 +    int             operation;         /* from above */
    7.44      char *          buffer;
    7.45      unsigned long   block_number;      /* block number */
    7.46      unsigned short  block_size;        /* block size */
    7.47 @@ -39,8 +45,9 @@ typedef struct blk_ring_req_entry
    7.48  
    7.49  typedef struct blk_ring_resp_entry
    7.50  {
    7.51 -    void *id;
    7.52 -    unsigned long status;
    7.53 +    void *          id;                                  /* for guest os use */
    7.54 +    int             operation;                                 /* from above */
    7.55 +    unsigned long   status;
    7.56  } blk_ring_resp_entry_t;
    7.57  
    7.58  typedef struct blk_ring_st 
    7.59 @@ -53,7 +60,13 @@ typedef struct blk_ring_st
    7.60      } ring[BLK_RING_SIZE];
    7.61  } blk_ring_t;
    7.62  
    7.63 -#define MAX_XEN_DISK_COUNT 100
    7.64 +/*
    7.65 + *
    7.66 + * physical disk (xhd) info, used by XEN_BLOCK_PROBE
    7.67 + *
    7.68 + */
    7.69 +
    7.70 +#define XEN_MAX_DISK_COUNT 100
    7.71  
    7.72  #define XEN_DISK_IDE  1
    7.73  #define XEN_DISK_SCSI 2
    7.74 @@ -71,8 +84,33 @@ typedef struct xen_disk                 
    7.75  
    7.76  typedef struct xen_disk_info
    7.77  {
    7.78 -  int         count; /* number of subsequent xen_disk_t structures to follow */
    7.79 -  xen_disk_t  disks[100];
    7.80 +  int         count;            /* number of xen_disk_t structures to follow */
    7.81 +  xen_disk_t  disks[XEN_MAX_DISK_COUNT];
    7.82  } xen_disk_info_t;
    7.83  
    7.84 +/*
    7.85 + *
    7.86 + * virtual disk (vhd) structures, used by XEN_BLOCK_SEG_{CREATE, DELETE}
    7.87 + *
    7.88 + */
    7.89 +
    7.90 +#define XEN_DISK_READ_WRITE  1
    7.91 +#define XEN_DISK_READ_ONLY   2
    7.92 +
    7.93 +typedef struct xv_extent
    7.94 +{
    7.95 +  int disk;                                          /* physical disk number */
    7.96 +  unsigned long offset;               /* offset in blocks into physical disk */
    7.97 +  unsigned long size;                                      /* size in blocks */
    7.98 +} xv_extent_t;
    7.99 +
   7.100 +typedef struct xv_disk
   7.101 +{
   7.102 +  int mode;                     /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */
   7.103 +  int domain;                                                      /* domain */
   7.104 +  int segment;                                             /* segment number */
   7.105 +  int ext_count;                          /* number of xv_extent_t to follow */
   7.106 +  xv_extent_t extents[XEN_MAX_DISK_COUNT];    /* arbitrary reuse of constant */
   7.107 +} xv_disk_t;
   7.108 +
   7.109  #endif
     8.1 --- a/xen/include/xeno/sched.h	Mon Feb 24 23:45:39 2003 +0000
     8.2 +++ b/xen/include/xeno/sched.h	Wed Feb 26 19:16:57 2003 +0000
     8.3 @@ -55,6 +55,7 @@ extern struct mm_struct init_mm;
     8.4  
     8.5  #include <xeno/vif.h>
     8.6  #include <xeno/block.h>
     8.7 +#include <xeno/segment.h>
     8.8  
     8.9  struct task_struct {
    8.10  
    8.11 @@ -79,6 +80,8 @@ struct task_struct {
    8.12      unsigned int blk_req_cons; /* request consumer */
    8.13      struct list_head blkdev_list;
    8.14      spinlock_t blk_ring_lock;
    8.15 +    segment_t *segment_list[XEN_MAX_SEGMENTS];                        /* vhd */
    8.16 +    int segment_count;
    8.17  
    8.18      int has_cpu, policy, counter;
    8.19  
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/include/xeno/segment.h	Wed Feb 26 19:16:57 2003 +0000
     9.3 @@ -0,0 +1,52 @@
     9.4 +#ifndef __SEGMENT_H__
     9.5 +#define __SEGMENT_H__
     9.6 +
     9.7 +#include <hypervisor-ifs/block.h>
     9.8 +
     9.9 +void xen_segment_initialize(void);
    9.10 +void xen_refresh_segment_list (struct task_struct *p);
    9.11 +int xen_segment_create(xv_disk_t *xvd);
    9.12 +
    9.13 +#define XEN_MAX_SEGMENTS 100     /* total number of segments across all doms */
    9.14 +
    9.15 +/*
    9.16 + * every physical disk that xen has access to is listed in the drives array.
    9.17 + * we export the drive# to domain 0.  to xen, each drive is just one long
    9.18 + * array of blocks.
    9.19 + */
    9.20 +
    9.21 +typedef struct drive
    9.22 +{
    9.23 +  unsigned int major; 
    9.24 +} drive_t;
    9.25 +
    9.26 +extern int     num_xdrives;
    9.27 +extern drive_t xdrives[XEN_MAX_DISK_COUNT];
    9.28 +
    9.29 +/*
    9.30 + * virtual hard disks
    9.31 + *
    9.32 + * each segment is composed of a number of extents
    9.33 + */
    9.34 +
    9.35 +typedef struct extent
    9.36 +{
    9.37 +  int disk;            /* index into drives array of where this extent lives */
    9.38 +  unsigned long offset;                                  /* offset into disk */
    9.39 +  unsigned long size;                                 /* size of this extent */
    9.40 +} extent_t;
    9.41 +
    9.42 +#define XEN_SEGMENT_UNUSED 0                                /* bzero default */
    9.43 +#define XEN_SEGMENT_RO XEN_DISK_READ_WRITE
    9.44 +#define XEN_SEGMENT_RW XEN_DISK_READ_ONLY
    9.45 +
    9.46 +typedef struct segment
    9.47 +{
    9.48 +  int mode;                                             /* UNUSED, RO, or RW */
    9.49 +  int domain;
    9.50 +  int segment_number;                           /* segment number for domain */
    9.51 +  int num_extents;                                      /* number of extents */
    9.52 +  extent_t *extents;
    9.53 +} segment_t;
    9.54 +
    9.55 +#endif
    10.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile	Mon Feb 24 23:45:39 2003 +0000
    10.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile	Wed Feb 26 19:16:57 2003 +0000
    10.3 @@ -1,3 +1,3 @@
    10.4  O_TARGET := blk.o
    10.5 -obj-y := xl_block.o xl_block_test.o
    10.6 +obj-y := xl_block.o xl_segment.o xl_block_test.o
    10.7  include $(TOPDIR)/Rules.make
    11.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c	Mon Feb 24 23:45:39 2003 +0000
    11.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c	Wed Feb 26 19:16:57 2003 +0000
    11.3 @@ -22,6 +22,7 @@
    11.4  #include <asm/hypervisor-ifs/block.h>
    11.5  #include <asm/hypervisor-ifs/hypervisor-if.h>
    11.6  #include <asm/io.h>
    11.7 +#include <asm/atomic.h>
    11.8  #include <asm/uaccess.h>
    11.9  
   11.10  #define MAJOR_NR XLBLK_MAJOR   /* force defns in blk.h, must precede include */
   11.11 @@ -58,6 +59,7 @@ static int xlblk_max_sectors[XLBLK_MAX];
   11.12  static blk_ring_t *blk_ring;
   11.13  static unsigned int resp_cons; /* Response consumer for comms ring. */
   11.14  static xen_disk_info_t xen_disk_info;
   11.15 +atomic_t xlblk_control_count;
   11.16  
   11.17  int hypervisor_request(void *         id,
   11.18                         int            operation,
   11.19 @@ -166,7 +168,7 @@ static int xenolinux_block_revalidate(kd
   11.20   *   virtual address in the guest os.
   11.21   * block_number:  block to read
   11.22   * block_size:  size of each block
   11.23 - * device:  ide/hda is 768 or 0x300
   11.24 + * device:  ide/hda is 768 or 0x300           should be disk#!!!
   11.25   */
   11.26  int hypervisor_request(void *         id,
   11.27                         int            operation,
   11.28 @@ -193,6 +195,8 @@ int hypervisor_request(void *         id
   11.29  
   11.30      switch ( operation )
   11.31      {
   11.32 +    case XEN_BLOCK_SEG_CREATE:
   11.33 +    case XEN_BLOCK_SEG_DELETE:
   11.34      case XEN_BLOCK_PROBE:
   11.35  	phys_device = (kdev_t) 0;
   11.36  	sector_number = 0;
   11.37 @@ -321,7 +325,21 @@ static void xlblk_response_int(int irq, 
   11.38  	  i  = BLK_RING_INC(i) )
   11.39      {
   11.40  	blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp;
   11.41 -        if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1);
   11.42 +	switch (bret->operation)
   11.43 +	{
   11.44 +	  case XEN_BLOCK_READ :
   11.45 +  	  case XEN_BLOCK_WRITE :
   11.46 +	    if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1);
   11.47 +	    break;
   11.48 +	    
   11.49 +	  case XEN_BLOCK_SEG_CREATE :
   11.50 +	  case XEN_BLOCK_SEG_DELETE :
   11.51 +	    atomic_dec(&xlblk_control_count);
   11.52 +	    break;
   11.53 +	  
   11.54 +	  default:
   11.55 +	    break;
   11.56 +	}
   11.57      }
   11.58      
   11.59      resp_cons = i;
   11.60 @@ -337,6 +355,8 @@ int __init xlblk_init(void)
   11.61  {
   11.62      int i, error, result;
   11.63  
   11.64 +    atomic_set(&xlblk_control_count, 0);
   11.65 +
   11.66      /* This mapping was created early at boot time. */
   11.67      blk_ring = (blk_ring_t *)fix_to_virt(FIX_BLKRING_BASE);
   11.68      blk_ring->req_prod = blk_ring->resp_prod = resp_cons = 0;
   11.69 @@ -356,6 +376,7 @@ int __init xlblk_init(void)
   11.70          BUG();
   11.71      HYPERVISOR_block_io_op();
   11.72      while ( blk_ring->resp_prod != 1 ) barrier();
   11.73 +    printk (KERN_ALERT "block device probe:\n");
   11.74      for ( i = 0; i < xen_disk_info.count; i++ )
   11.75      { 
   11.76  	printk (KERN_ALERT "  %2d: type: %d, capacity: %ld\n",
    12.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c	Mon Feb 24 23:45:39 2003 +0000
    12.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c	Wed Feb 26 19:16:57 2003 +0000
    12.3 @@ -138,6 +138,11 @@ int proc_write_bdt(struct file *file, co
    12.4    sscanf(local, "%c %i %i %i", 
    12.5  	 &opcode, &block_number, &block_size, &device);
    12.6  
    12.7 +  if (data)
    12.8 +  {
    12.9 +    kfree(data);
   12.10 +  }
   12.11 +
   12.12    if (opcode == 'r' || opcode == 'R')
   12.13    {
   12.14      meta.operation = XEN_BLOCK_READ;
   12.15 @@ -151,6 +156,31 @@ int proc_write_bdt(struct file *file, co
   12.16      meta.operation = XEN_BLOCK_DEBUG;
   12.17      block_size = 10000;
   12.18    }
   12.19 +  else if (opcode == 'c' || opcode == 'C')
   12.20 +  {
   12.21 +    xv_disk_t *xvd;
   12.22 +    int loop;
   12.23 +
   12.24 +    meta.operation = XEN_BLOCK_SEG_CREATE;
   12.25 +    data = kmalloc (sizeof(xv_disk_t), GFP_KERNEL);
   12.26 +    if (data == NULL)
   12.27 +    {
   12.28 +      kfree(local);
   12.29 +      return -ENOMEM;
   12.30 +    }
   12.31 +    
   12.32 +    xvd = (xv_disk_t *)data;
   12.33 +    xvd->mode = XEN_DISK_READ_WRITE;
   12.34 +    xvd->domain = block_number;
   12.35 +    xvd->segment = block_size;
   12.36 +    xvd->ext_count = device;
   12.37 +    for (loop = 0; loop < xvd->ext_count; loop++)
   12.38 +    {
   12.39 +      xvd->extents[loop].disk = block_number + 1;                  /* random */
   12.40 +      xvd->extents[loop].offset = block_size + 1;
   12.41 +      xvd->extents[loop].size = device + 1;
   12.42 +    }
   12.43 +  }
   12.44    else
   12.45    {
   12.46      printk(KERN_ALERT 
   12.47 @@ -158,15 +188,14 @@ int proc_write_bdt(struct file *file, co
   12.48      return -EINVAL;
   12.49    }
   12.50  
   12.51 -  if (data)
   12.52 -  {
   12.53 -    kfree(data);
   12.54 -  }
   12.55 -  data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
   12.56    if (data == NULL)
   12.57    {
   12.58 -    kfree(local);
   12.59 -    return -ENOMEM;
   12.60 +    data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
   12.61 +    if (data == NULL)
   12.62 +    {
   12.63 +      kfree(local);
   12.64 +      return -ENOMEM;
   12.65 +    }
   12.66    }
   12.67  
   12.68    meta.block_number = block_number;
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c	Wed Feb 26 19:16:57 2003 +0000
    13.3 @@ -0,0 +1,275 @@
    13.4 +/*
    13.5 + * xl_segment.c
    13.6 + * 
    13.7 + * XenoLinux virtual disk driver.
    13.8 + */
    13.9 +
   13.10 +
   13.11 +#include <linux/config.h>
   13.12 +#include <linux/module.h>
   13.13 +
   13.14 +#include <linux/proc_fs.h>
   13.15 +#include <linux/delay.h>
   13.16 +#include <asm/uaccess.h>
   13.17 +#include <asm/atomic.h>
   13.18 +
   13.19 +#include <asm/hypervisor-ifs/block.h>
   13.20 +#include <asm/hypervisor-ifs/hypervisor-if.h>
   13.21 +
   13.22 +static struct proc_dir_entry *vhd;
   13.23 +xv_disk_t xvd;
   13.24 +
   13.25 +extern atomic_t xlblk_control_count;                           /* xl_block.c */
   13.26 +
   13.27 +/******************************************************************/
   13.28 +
   13.29 +static int proc_read_vhd(char *page, char **start, off_t off,
   13.30 +			 int count, int *eof, void *data)
   13.31 +{
   13.32 +  return 0;
   13.33 +}
   13.34 +
   13.35 +#define isdelim(c) \
   13.36 +  (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
   13.37 +
   13.38 +char *get_string(char *string)                          /* a bit like strtok */
   13.39 +{
   13.40 +  static char *temp;
   13.41 +  int loop = 0;
   13.42 +
   13.43 +  if (string != NULL)	
   13.44 +    temp = string;
   13.45 +  else
   13.46 +    string = temp;
   13.47 +
   13.48 + try_again:
   13.49 +
   13.50 +  while (!isdelim(string[loop]))
   13.51 +  {
   13.52 +    if (string[loop] == '\0')
   13.53 +      return NULL;
   13.54 +    loop++;
   13.55 +  }
   13.56 +
   13.57 +  string[loop] = '\0';	
   13.58 +  temp = (string + loop + 1);
   13.59 +
   13.60 +  if (loop == 0)
   13.61 +  {
   13.62 +    string = temp;
   13.63 +    goto try_again;
   13.64 +  }
   13.65 +
   13.66 +  return string;
   13.67 +}
   13.68 +
   13.69 +
   13.70 +#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
   13.71 +unsigned long to_number(char *string)                                /* atoi */
   13.72 +{
   13.73 +  unsigned long value = 0;
   13.74 +
   13.75 +  if (string == NULL) return 0;
   13.76 +
   13.77 +  while (!isdigit(*string) && *string != '\0') string++;
   13.78 +
   13.79 +  while (isdigit(*string))
   13.80 +  {
   13.81 +    value = value * 10 + (*string - '0');
   13.82 +    string++;
   13.83 +  }
   13.84 +
   13.85 +  return value;
   13.86 +}
   13.87 +
   13.88 +static int proc_write_vhd(struct file *file, const char *buffer,
   13.89 +			  unsigned long count, void *data)
   13.90 +{
   13.91 +  char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
   13.92 +  char *string;
   13.93 +  int loop;
   13.94 +  int counter;
   13.95 +  xv_disk_t xvd;
   13.96 +
   13.97 +  memset (&xvd, 0, sizeof(xvd));
   13.98 +
   13.99 +  if (copy_from_user(local, buffer, count))
  13.100 +  {
  13.101 +    return -EFAULT;
  13.102 +  }
  13.103 +  local[count] = '\0';
  13.104 +
  13.105 +  string = get_string(local);                             /* look for Domain */
  13.106 +  if (string == NULL)                                        /* empty string */
  13.107 +  {
  13.108 +    return count;
  13.109 +  }
  13.110 +  if (*string != 'd' && *string != 'D')
  13.111 +  {
  13.112 +    printk (KERN_ALERT 
  13.113 +	    "error: domain specifier missing [%s]. should be \"domain\".\n",
  13.114 +	    string);
  13.115 +    return count;
  13.116 +  }
  13.117 +
  13.118 +  string = get_string(NULL);                                /* domain number */
  13.119 +  if (string == NULL)
  13.120 +  {
  13.121 +    printk (KERN_ALERT "error: domain number missing\n");
  13.122 +    return count;
  13.123 +  }
  13.124 +  xvd.domain = (int) to_number(string);
  13.125 +
  13.126 +  string = get_string(NULL);
  13.127 +  if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
  13.128 +  {
  13.129 +    xvd.mode = XEN_DISK_READ_ONLY;
  13.130 +  }
  13.131 +  else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
  13.132 +  {
  13.133 +    xvd.mode = XEN_DISK_READ_ONLY;
  13.134 +  }
  13.135 +  else
  13.136 +  {
  13.137 +    printk (KERN_ALERT 
  13.138 +	    "error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
  13.139 +	    string);
  13.140 +    return count;
  13.141 +  }
  13.142 +
  13.143 +  string = get_string(NULL);                             /* look for Segment */
  13.144 +  if (string == NULL || (*string != 's' && *string != 'S'))
  13.145 +  {
  13.146 +    printk (KERN_ALERT 
  13.147 +	    "error: segment specifier missing [%s]. should be \"segment\".\n",
  13.148 +	    string);
  13.149 +    return count;
  13.150 +  }
  13.151 +
  13.152 +  string = get_string(NULL);                               /* segment number */
  13.153 +  if (string == NULL)
  13.154 +  {
  13.155 +    printk (KERN_ALERT "error: segment number missing\n");
  13.156 +    return count;
  13.157 +  }
  13.158 +  xvd.segment = (int) to_number(string);
  13.159 +
  13.160 +  string = get_string(NULL);                             /* look for Extents */
  13.161 +  if (string == NULL || (*string != 'e' && *string != 'E'))
  13.162 +  {
  13.163 +    printk (KERN_ALERT 
  13.164 +	    "error: extents specifier missing [%s]. should be \"extents\".\n",
  13.165 +	    string);
  13.166 +    return count;
  13.167 +  }
  13.168 +
  13.169 +  string = get_string(NULL);                            /* number of extents */
  13.170 +  if (string == NULL)
  13.171 +  {
  13.172 +    printk (KERN_ALERT "error: number of extents missing\n");
  13.173 +    return count;
  13.174 +  }
  13.175 +  xvd.ext_count = (int) to_number(string);
  13.176 +
  13.177 +  /* ignore parenthesis */
  13.178 +
  13.179 +  for (loop = 0; loop < xvd.ext_count; loop++)
  13.180 +  {
  13.181 +    string = get_string(NULL);                              /* look for Disk */
  13.182 +    if (string == NULL || (*string != 'd' && *string != 'D'))
  13.183 +    {
  13.184 +      printk (KERN_ALERT 
  13.185 +	      "hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
  13.186 +	      string);
  13.187 +      return count;
  13.188 +    }
  13.189 +    string = get_string(NULL);                                /* disk number */
  13.190 +    if (string == NULL)
  13.191 +    {
  13.192 +      printk (KERN_ALERT "error: disk number missing\n");
  13.193 +      return count;
  13.194 +    }
  13.195 +    xvd.extents[loop].disk = (int) to_number(string);
  13.196 +
  13.197 +    string = get_string(NULL);                            /* look for Offset */
  13.198 +    if (string == NULL || (*string != 'o' && *string != 'O'))
  13.199 +    {
  13.200 +      printk (KERN_ALERT 
  13.201 +	      "error: disk offset missing [%s]. should be \"offset\".\n",
  13.202 +	    string);
  13.203 +      return count;
  13.204 +    }
  13.205 +    string = get_string(NULL);                                     /* offset */
  13.206 +    if (string == NULL)
  13.207 +    {
  13.208 +      printk (KERN_ALERT "error: offset missing\n");
  13.209 +      return count;
  13.210 +    }
  13.211 +    xvd.extents[loop].offset =  to_number(string);
  13.212 +
  13.213 +    string = get_string(NULL);                              /* look for Size */
  13.214 +    if (string == NULL || (*string != 's' && *string != 'S'))
  13.215 +    {
  13.216 +      printk (KERN_ALERT 
  13.217 +	      "error: extent size missing [%s]. should be \"size\".\n",
  13.218 +	    string);
  13.219 +      return count;
  13.220 +    }
  13.221 +    string = get_string(NULL);                                       /* size */
  13.222 +    if (string == NULL)
  13.223 +    {
  13.224 +      printk (KERN_ALERT "error: extent size missing\n");
  13.225 +      return count;
  13.226 +    }
  13.227 +    xvd.extents[loop].size =  to_number(string);
  13.228 +  }
  13.229 +
  13.230 +  {
  13.231 +    /* get lock xlblk_control_lock     */
  13.232 +    counter = atomic_read(&xlblk_control_count);
  13.233 +    atomic_inc(&xlblk_control_count);
  13.234 +    /* release lock xlblk_control_lock */
  13.235 +  }
  13.236 +
  13.237 +  hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
  13.238 +		      0, 0, (kdev_t) 0);
  13.239 +  HYPERVISOR_block_io_op();
  13.240 +
  13.241 +  while (atomic_read(&xlblk_control_count) != counter) barrier();
  13.242 +
  13.243 +  /* while ( blk_ring->resp_prod != 1 ) barrier(); */
  13.244 +
  13.245 +  /*  mdelay(1000); */
  13.246 +
  13.247 +  return count;
  13.248 +}
  13.249 +
  13.250 +/******************************************************************/
  13.251 +
  13.252 +int __init xlseg_init(void)
  13.253 +{
  13.254 +  vhd = create_proc_entry("xeno/dom0/vhd", 0644, NULL);
  13.255 +  if (vhd == NULL)
  13.256 +  {
  13.257 +    panic ("xlseg_init: unable to create vhd proc entry\n");
  13.258 +  }
  13.259 +  vhd->data       = NULL;
  13.260 +  vhd->read_proc  = proc_read_vhd;
  13.261 +  vhd->write_proc = proc_write_vhd;
  13.262 +  vhd->owner      = THIS_MODULE;
  13.263 +
  13.264 +  memset(&xvd, 0, sizeof(xvd));
  13.265 +
  13.266 +  printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver installed\n");
  13.267 +  return 0;
  13.268 +}
  13.269 +
  13.270 +static void __exit xlseg_cleanup(void)
  13.271 +{
  13.272 +  printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver uninstalled\n");
  13.273 +}
  13.274 +
  13.275 +#ifdef MODULE
  13.276 +module_init(xlseg_init);
  13.277 +module_exit(xlseg_cleanup);
  13.278 +#endif
    14.1 --- a/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c	Mon Feb 24 23:45:39 2003 +0000
    14.2 +++ b/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c	Wed Feb 26 19:16:57 2003 +0000
    14.3 @@ -1504,6 +1504,7 @@ int __init blk_dev_init(void)
    14.4  
    14.5  #ifdef CONFIG_XENOLINUX_BLOCK
    14.6      xlblk_init();
    14.7 +    xlseg_init();
    14.8  #endif
    14.9  
   14.10  	return 0;