aboutsummaryrefslogtreecommitdiffstats
path: root/xenolinux-2.4.21-pre4-sparse
diff options
context:
space:
mode:
authorach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>2003-03-06 15:52:22 +0000
committerach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>2003-03-06 15:52:22 +0000
commit454a736db481ae4527360d5630ca9cd4148567c9 (patch)
treed80087eb7811b798b3d695f36bb292baaa2140bb /xenolinux-2.4.21-pre4-sparse
parentf3c8dfc6270a0d4ac5f81d64b59a42623e45f82e (diff)
downloadxen-454a736db481ae4527360d5630ca9cd4148567c9.tar.gz
xen-454a736db481ae4527360d5630ca9cd4148567c9.tar.bz2
xen-454a736db481ae4527360d5630ca9cd4148567c9.zip
bitkeeper revision 1.108 (3e676eb6Jy0anfrUlVCNnVZnDDSlQg)
virtual block device support
Diffstat (limited to 'xenolinux-2.4.21-pre4-sparse')
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile2
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c152
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c3
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c586
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c280
-rw-r--r--xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c1
-rw-r--r--xenolinux-2.4.21-pre4-sparse/include/linux/blk.h7
-rw-r--r--xenolinux-2.4.21-pre4-sparse/include/linux/major.h3
-rw-r--r--xenolinux-2.4.21-pre4-sparse/init/do_mounts.c4
9 files changed, 773 insertions, 265 deletions
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
index c6d1c7dc63..594aab25b8 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
@@ -1,3 +1,3 @@
O_TARGET := blk.o
-obj-y := xl_block.o xl_segment.o xl_block_test.o
+obj-y := xl_block.o xl_segment.o xl_segment_proc.o xl_block_test.o
include $(TOPDIR)/Rules.make
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
index 6e7e713c86..bc87e7eb7b 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
@@ -1,7 +1,7 @@
/******************************************************************************
* xl_block.c
*
- * Xenolinux virtual block-device driver.
+ * Xenolinux virtual block-device driver (xhd).
*
*/
@@ -32,8 +32,6 @@ static int xlblk_major = XLBLK_MAJOR;
/* Copied from linux/ide.h */
typedef unsigned char byte;
-void xlblk_ide_register_disk(int, unsigned long);
-
#define XLBLK_MAX 32 /* Maximum minor devices we support */
#define XLBLK_MAJOR_NAME "xhd"
#define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
@@ -58,15 +56,18 @@ static int xlblk_max_sectors[XLBLK_MAX];
static blk_ring_t *blk_ring;
static unsigned int resp_cons; /* Response consumer for comms ring. */
-static xen_disk_info_t xen_disk_info;
+static xen_disk_info_t xlblk_disk_info;
atomic_t xlblk_control_count;
-int hypervisor_request(void * id,
- int operation,
- char * buffer,
- unsigned long block_number,
- unsigned short block_size,
- kdev_t device);
+void xlblk_ide_register_disk(int, unsigned long);
+void do_xlseg_requestX (request_queue_t *rq);
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd);
/* ------------------------------------------------------------------------
@@ -103,22 +104,39 @@ static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
switch (command)
{
- case BLKGETSIZE:
+ case BLKGETSIZE: /* get size */
DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE,
- (long) xen_disk_info.disks[0].capacity);
- return put_user(xen_disk_info.disks[0].capacity,
+ (long) xlblk_disk_info.disks[0].capacity);
+ return put_user(xlblk_disk_info.disks[0].capacity,
(unsigned long *) argument);
- case BLKRRPART:
+ case BLKRRPART: /* re-read partition table */
DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART);
break;
- case BLKSSZGET:
+ case BLKBSZGET: /* get block size */
+ DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET);
+ break;
+
+ case BLKBSZSET: /* set block size */
+ DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET);
+ break;
+
+ case BLKRASET: /* set read-ahead */
+ DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET);
+ break;
+
+ case BLKRAGET: /* get read-ahead */
+ DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET);
+ break;
+
+ case BLKSSZGET: /* get sector size */
DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
xlblk_hardsect_size[minor_dev]);
return xlblk_hardsect_size[minor_dev];
case HDIO_GETGEO:
+ /* note: these values are complete garbage */
DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO);
if (!argument) return -EINVAL;
if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
@@ -128,13 +146,13 @@ static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
return 0;
case HDIO_GETGEO_BIG:
+ /* note: these values are complete garbage */
DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
if (!argument) return -EINVAL;
if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT;
if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT;
if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
-
return 0;
default:
@@ -163,26 +181,27 @@ static int xenolinux_block_revalidate(kdev_t dev)
* request block io
*
* id: for guest use only.
- * operation: XEN_BLOCK_READ, XEN_BLOCK_WRITE or XEN_BLOCK_PROBE
+ * operation: XEN_BLOCK_{READ,WRITE,PROBE*,SEG*}
* buffer: buffer to read/write into. this should be a
* virtual address in the guest os.
* block_number: block to read
* block_size: size of each block
- * device: ide/hda is 768 or 0x300 should be disk#!!!
+ * device: xhd or vhd
+ * gd: partition information if XEN_BLOCK_{READ,WRITE}
*/
-int hypervisor_request(void * id,
- int operation,
- char * buffer,
- unsigned long block_number,
- unsigned short block_size,
- kdev_t device)
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd)
{
int position;
void *buffer_ma;
kdev_t phys_device = (kdev_t) 0;
unsigned long sector_number = 0;
- struct gendisk *gd;
-
+
/*
* Bail if there's no room in the request communication ring. This may be
* because we have a whole bunch of outstanding responses to process. No
@@ -197,21 +216,38 @@ int hypervisor_request(void * id,
{
case XEN_BLOCK_SEG_CREATE:
case XEN_BLOCK_SEG_DELETE:
- case XEN_BLOCK_PROBE:
+ case XEN_BLOCK_PROBE_BLK:
+ case XEN_BLOCK_PROBE_SEG:
phys_device = (kdev_t) 0;
sector_number = 0;
break;
case XEN_BLOCK_READ:
case XEN_BLOCK_WRITE:
- if ( MAJOR(device) != XLBLK_MAJOR )
+ /* only accept requests for xhd and vhd devices */
+ if (!IS_XHD_MAJOR(MAJOR(device)) && !IS_VHD_MAJOR(MAJOR(device)))
panic("error: xl_block::hypervisor_request: "
"unknown device [0x%x]\n", device);
- phys_device = MKDEV(IDE0_MAJOR, 0);
- /* Compute real buffer location on disk */
+ phys_device = MAJOR(device);
+
+ /* Compute real buffer location on disk.
+ * note: gd will be null when we read the partition table.
+ */
sector_number = block_number;
- if ( (gd = (struct gendisk *)xen_disk_info.disks[0].gendisk) != NULL )
- sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect;
+ if ( gd != NULL )
+ {
+ sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect;
+ }
+
+ /*
+ if (IS_VHD_MAJOR(MAJOR(device)))
+ {
+ printk (KERN_ALERT "%lx + %lx = %lx (%x)\n",
+ block_number,
+ gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect,
+ sector_number, device);
+ }
+ */
break;
default:
@@ -266,8 +302,9 @@ static void do_xlblk_request (request_queue_t *rq)
{
full = hypervisor_request(
bh, (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE,
- bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev);
-
+ bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev,
+ (struct gendisk *)xlblk_disk_info.disks[0].gendisk);
+
if ( full ) goto out;
queued++;
@@ -334,6 +371,7 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
case XEN_BLOCK_SEG_CREATE :
case XEN_BLOCK_SEG_DELETE :
+ case XEN_BLOCK_PROBE_SEG :
atomic_dec(&xlblk_control_count);
break;
@@ -345,7 +383,9 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
resp_cons = i;
/* KAF: We can push work down at this point. We have the lock. */
- do_xlblk_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ /* aho: okay, so this is a bit of a hack. we'll kick every queue... */
+ do_xlblk_request(BLK_DEFAULT_QUEUE(XLBLK_MAJOR));
+ do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
spin_unlock_irqrestore(&io_request_lock, flags);
}
@@ -368,20 +408,23 @@ int __init xlblk_init(void)
goto fail;
}
- memset (&xen_disk_info, 0, sizeof(xen_disk_info));
- xen_disk_info.count = 0;
+ /* probe for disk information */
+ memset (&xlblk_disk_info, 0, sizeof(xlblk_disk_info));
+ xlblk_disk_info.count = 0;
- if ( hypervisor_request(NULL, XEN_BLOCK_PROBE, (char *) &xen_disk_info,
- 0, 0, (kdev_t) 0) )
+ if ( hypervisor_request(NULL, XEN_BLOCK_PROBE_BLK,
+ (char *) &xlblk_disk_info,
+ 0, 0, (kdev_t) 0,
+ (struct gendisk *) NULL))
BUG();
HYPERVISOR_block_io_op();
while ( blk_ring->resp_prod != 1 ) barrier();
- printk (KERN_ALERT "block device probe:\n");
- for ( i = 0; i < xen_disk_info.count; i++ )
+ printk (KERN_ALERT "xhd block device probe:\n");
+ for ( i = 0; i < xlblk_disk_info.count; i++ )
{
printk (KERN_ALERT " %2d: type: %d, capacity: %ld\n",
- i, xen_disk_info.disks[i].type,
- xen_disk_info.disks[i].capacity);
+ i, xlblk_disk_info.disks[i].type,
+ xlblk_disk_info.disks[i].capacity);
}
SET_MODULE_OWNER(&xenolinux_block_fops);
@@ -394,7 +437,7 @@ int __init xlblk_init(void)
/* initialize global arrays in drivers/block/ll_rw_block.c */
for (i = 0; i < XLBLK_MAX; i++) {
- xlblk_blk_size[i] = xen_disk_info.disks[0].capacity;
+ xlblk_blk_size[i] = xlblk_disk_info.disks[0].capacity;
xlblk_blksize_size[i] = 512;
xlblk_hardsect_size[i] = 512;
xlblk_max_sectors[i] = 128;
@@ -415,7 +458,7 @@ int __init xlblk_init(void)
*/
blk_queue_headactive(BLK_DEFAULT_QUEUE(xlblk_major), 0);
- xlblk_ide_register_disk(0, xen_disk_info.disks[0].capacity);
+ xlblk_ide_register_disk(0, xlblk_disk_info.disks[0].capacity);
printk(KERN_ALERT
"XenoLinux Virtual Block Device Driver installed [device: %d]\n",
@@ -461,13 +504,26 @@ void xlblk_ide_register_disk(int idx, unsigned long capacity)
add_gendisk(gd);
- xen_disk_info.disks[idx].gendisk = gd;
+ xlblk_disk_info.disks[idx].gendisk = gd;
- /* default disk size is just a big number. in the future, we
- need a message to probe the devices to determine the actual size */
register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS,
&xenolinux_block_fops, capacity);
+ {
+ int loop = 0;
+ printk (KERN_ALERT "Partition Table: (capacity: %lx)\n", capacity);
+ for (loop = 0; loop < minors; loop++)
+ {
+ if (gd->part[loop].start_sect && gd->part[loop].nr_sects)
+ {
+ printk (KERN_ALERT
+ " %2d: 0x%6lx %8ld 0x%6lx %7ld\n", loop,
+ gd->part[loop].start_sect, gd->part[loop].start_sect,
+ gd->part[loop].nr_sects, gd->part[loop].nr_sects);
+ }
+ }
+ }
+
return;
}
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
index 8d695689ba..b239655794 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
@@ -206,7 +206,8 @@ int proc_write_bdt(struct file *file, const char *buffer,
/* submit request */
hypervisor_request(0, meta.operation, meta.buffer,
meta.block_number, meta.block_size,
- meta.device);
+ meta.device,
+ (struct gendisk *) NULL);
HYPERVISOR_block_io_op();
mdelay(1000); /* should wait for a proper acknowledgement/response. */
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
index da14be14df..0754daa9a3 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
@@ -1,274 +1,432 @@
-/*
+/******************************************************************************
* xl_segment.c
*
- * XenoLinux virtual disk driver.
+ * Xenolinux virtual block-device driver (vhd).
+ *
*/
-
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include <linux/fs.h>
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/major.h>
#include <asm/hypervisor-ifs/block.h>
#include <asm/hypervisor-ifs/hypervisor-if.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+
+#define MAJOR_NR XLSEG_MAJOR /* force defns in blk.h, must precede include */
+static int xlseg_major = XLSEG_MAJOR;
+#include <linux/blk.h>
+
+/* Copied from linux/ide.h */
+typedef unsigned char byte;
-static struct proc_dir_entry *vhd;
-xv_disk_t xvd;
+#define XLSEG_MAX 32 /* Maximum minor devices we support */
+#define XLSEG_MAJOR_NAME "xhd"
+
+static int xlseg_blk_size[XLSEG_MAX];
+static int xlseg_blksize_size[XLSEG_MAX];
+static int xlseg_read_ahead;
+static int xlseg_hardsect_size[XLSEG_MAX];
+static int xlseg_max_sectors[XLSEG_MAX];
extern atomic_t xlblk_control_count; /* xl_block.c */
-/******************************************************************/
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd);
+void xlseg_register_disk(int idx, unsigned long capacity);
+
+#if 0
+#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a )
+#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a )
+#else
+#define DPRINTK(_f, _a...) ((void)0)
+#define DPRINTK_IOCTL(_f, _a...) ((void)0)
+#endif
+
+static xen_disk_info_t xlseg_disk_info;
-static int proc_read_vhd(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+/* ------------------------------------------------------------------------
+ */
+
+static int xenolinux_segment_open(struct inode *inode, struct file *filep)
{
- return 0;
+ DPRINTK("xenolinux_segment_release\n");
+ return 0;
}
-#define isdelim(c) \
- (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
+static int xenolinux_segment_release(struct inode *inode, struct file *filep)
+{
+ DPRINTK("xenolinux_segment_release\n");
+ return 0;
+}
-char *get_string(char *string) /* a bit like strtok */
+static int xenolinux_segment_ioctl(struct inode *inode, struct file *filep,
+ unsigned command, unsigned long argument)
{
- static char *temp;
- int loop = 0;
+ int minor_dev;
+ struct hd_geometry *geo = (struct hd_geometry *)argument;
+ struct gendisk *gd = (struct gendisk *)xlseg_disk_info.disks[0].gendisk;
+
+ DPRINTK("xenolinux_segment_ioctl\n");
+
+ /* check permissions */
+ if (!capable(CAP_SYS_ADMIN)) return -EPERM;
+ if (!inode) return -EINVAL;
+ minor_dev = MINOR(inode->i_rdev);
+ if (minor_dev >= XLSEG_MAX) return -ENODEV;
+
+ DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
+ command, (long) argument, minor_dev);
+
+ switch (command)
+ {
+ case BLKGETSIZE:
+ if (gd != NULL)
+ {
+ printk(KERN_ALERT "minordev: %d\n", minor_dev);
+ printk(KERN_ALERT "[0] start: %lx\n", gd->part[0].start_sect);
+ printk(KERN_ALERT "[0] count: %lx\n", gd->part[0].nr_sects);
+ printk(KERN_ALERT "[1] start: %lx\n", gd->part[1].start_sect);
+ printk(KERN_ALERT "[1] count: %lx\n", gd->part[1].nr_sects);
+ printk(KERN_ALERT "[2] start: %lx\n", gd->part[2].start_sect);
+ printk(KERN_ALERT "[2] count: %lx\n", gd->part[2].nr_sects);
+
+ DPRINTK_IOCTL(" BLKGETSIZE gd: %x %lx\n", BLKGETSIZE,
+ gd->part[minor_dev].nr_sects);
+ return put_user(gd->part[minor_dev].nr_sects,
+ (unsigned long *)argument);
+ }
+ else
+ {
+ DPRINTK_IOCTL(" BLKGETSIZE disk: %x %lx\n", BLKGETSIZE,
+ xlseg_disk_info.disks[0].capacity);
+ return put_user(xlseg_disk_info.disks[0].capacity,
+ (unsigned long *) argument);
+ }
+
+ case BLKRRPART:
+ DPRINTK_IOCTL(" BLKRRPART: \n");
+ /* we don't have re-validate drive yet... so you need to reboot! */
+ break;
+
+ case BLKSSZGET:
+ DPRINTK_IOCTL(" BLKSSZGET: %d\n",
+ xlseg_hardsect_size[minor_dev]);
+ return xlseg_hardsect_size[minor_dev];
+
+ case HDIO_GETGEO:
+ /* note: these values are complete garbage */
+ DPRINTK_IOCTL(" HDIO_GETGEO: \n");
+ if (!argument) return -EINVAL;
+ if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
+ if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT;
+ if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT;
+ if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT;
+ return 0;
+
+ case HDIO_GETGEO_BIG:
+ /* note: these values are complete garbage */
+ DPRINTK_IOCTL(" HDIO_GETGEO_BIG\n");
+ if (!argument) return -EINVAL;
+ if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
+ if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT;
+ if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT;
+ if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
+ return 0;
+
+ default:
+ DPRINTK_IOCTL(" eh? unknown ioctl\n");
+ break;
+ }
+
+ return 0;
+}
- if (string != NULL)
- temp = string;
- else
- string = temp;
+static int xenolinux_segment_check(kdev_t dev)
+{
+ DPRINTK("xenolinux_segment_check\n");
+ return 0;
+}
- try_again:
+static int xenolinux_segment_revalidate(kdev_t dev)
+{
+ DPRINTK("xenolinux_segment_revalidate\n");
+ return 0;
+}
- while (!isdelim(string[loop]))
- {
- if (string[loop] == '\0')
- return NULL;
- loop++;
- }
+void do_xlseg_requestX (request_queue_t *rq)
+{
+ /* this is a bit dumb. do_xlseg_request is defined in blk.h
+ and this is thus static. but we have cooperative
+ device drivers... */
+ do_xlseg_request(rq);
+}
- string[loop] = '\0';
- temp = (string + loop + 1);
+/*
+ * do_xlseg_request
+ * read a block; request is in a request queue
+ */
+static void do_xlseg_request (request_queue_t *rq)
+{
+ struct request *req;
+ struct buffer_head *bh;
+ int rw, nsect, full, queued = 0;
+
+ /* DPRINTK("do_xlseg_request for '%s'\n", DEVICE_NAME); */
- if (loop == 0)
- {
- string = temp;
- goto try_again;
- }
+ while ( !rq->plugged && !QUEUE_EMPTY )
+ {
+ if ( (req = CURRENT) == NULL ) goto out;
+
+ DPRINTK("do_xlseg_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
+ req, req->cmd, req->sector,
+ req->current_nr_sectors, req->nr_sectors, req->bh);
+
+ rw = req->cmd;
+ if ( rw == READA ) rw = READ;
+ if ((rw != READ) && (rw != WRITE))
+ panic("XenoLinux Virtual Segment Device: bad cmd: %d\n", rw);
+
+ req->errors = 0;
+
+ bh = req->bh;
+ while ( bh != NULL )
+ {
+ full = hypervisor_request(
+ bh, (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE,
+ bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev,
+ (struct gendisk *)xlseg_disk_info.disks[0].gendisk);
+
+ if ( full )
+ {
+ goto out;
+ }
+
+ queued++;
+
+ /* Dequeue the buffer head from the request. */
+ nsect = bh->b_size >> 9;
+ req->bh = bh->b_reqnext;
+ bh->b_reqnext = NULL;
+ bh = req->bh;
+
+ if ( bh != NULL )
+ {
+ /* There's another buffer head to do. Update the request. */
+ req->hard_sector += nsect;
+ req->hard_nr_sectors -= nsect;
+ req->sector = req->hard_sector;
+ req->nr_sectors = req->hard_nr_sectors;
+ req->current_nr_sectors = bh->b_size >> 9;
+ req->buffer = bh->b_data;
+ }
+ else
+ {
+ /* That was the last buffer head. Finalise the request. */
+ if ( end_that_request_first(req, 1, "XenSeg") ) BUG();
+ blkdev_dequeue_request(req);
+ end_that_request_last(req);
+ }
+ }
+ }
- return string;
+ out:
+ if ( queued != 0 ) HYPERVISOR_block_io_op();
}
-#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
-unsigned long to_number(char *string) /* atoi */
+static struct block_device_operations xenolinux_segment_fops =
{
- unsigned long value = 0;
+ open: xenolinux_segment_open,
+ release: xenolinux_segment_release,
+ ioctl: xenolinux_segment_ioctl,
+ check_media_change: xenolinux_segment_check,
+ revalidate: xenolinux_segment_revalidate,
+};
- if (string == NULL) return 0;
- while (!isdigit(*string) && *string != '\0') string++;
+int __init xlseg_init(void)
+{
+ int i, result;
+ int counter;
- while (isdigit(*string))
- {
- value = value * 10 + (*string - '0');
- string++;
- }
+ /* probe for disk information */
+ memset (&xlseg_disk_info, 0, sizeof(xlseg_disk_info));
+ xlseg_disk_info.count = 0;
- return value;
-}
-static int proc_write_vhd(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
- char *string;
- int loop;
- int counter;
- xv_disk_t xvd;
-
- memset (&xvd, 0, sizeof(xvd));
-
- if (copy_from_user(local, buffer, count))
- {
- return -EFAULT;
- }
- local[count] = '\0';
-
- string = get_string(local); /* look for Domain */
- if (string == NULL) /* empty string */
- {
- return count;
- }
- if (*string != 'd' && *string != 'D')
- {
- printk (KERN_ALERT
- "error: domain specifier missing [%s]. should be \"domain\".\n",
- string);
- return count;
- }
-
- string = get_string(NULL); /* domain number */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: domain number missing\n");
- return count;
- }
- xvd.domain = (int) to_number(string);
-
- string = get_string(NULL);
- if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
- {
- xvd.mode = XEN_DISK_READ_ONLY;
- }
- else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
- {
- xvd.mode = XEN_DISK_READ_ONLY;
- }
- else
- {
- printk (KERN_ALERT
- "error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
- string);
- return count;
- }
-
- string = get_string(NULL); /* look for Segment */
- if (string == NULL || (*string != 's' && *string != 'S'))
- {
- printk (KERN_ALERT
- "error: segment specifier missing [%s]. should be \"segment\".\n",
- string);
- return count;
- }
-
- string = get_string(NULL); /* segment number */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: segment number missing\n");
- return count;
- }
- xvd.segment = (int) to_number(string);
-
- string = get_string(NULL); /* look for Extents */
- if (string == NULL || (*string != 'e' && *string != 'E'))
- {
- printk (KERN_ALERT
- "error: extents specifier missing [%s]. should be \"extents\".\n",
- string);
- return count;
- }
-
- string = get_string(NULL); /* number of extents */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: number of extents missing\n");
- return count;
- }
- xvd.ext_count = (int) to_number(string);
-
- /* ignore parenthesis */
-
- for (loop = 0; loop < xvd.ext_count; loop++)
- {
- string = get_string(NULL); /* look for Disk */
- if (string == NULL || (*string != 'd' && *string != 'D'))
{
- printk (KERN_ALERT
- "hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
- string);
- return count;
+ /* get lock xlblk_control_lock */
+ counter = atomic_read(&xlblk_control_count);
+ atomic_inc(&xlblk_control_count);
+ /* release lock xlblk_control_lock */
}
- string = get_string(NULL); /* disk number */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: disk number missing\n");
- return count;
+ if ( hypervisor_request(NULL, XEN_BLOCK_PROBE_SEG,
+ (char *) &xlseg_disk_info,
+ 0, 0, (kdev_t) 0,
+ (struct gendisk *)NULL) )
+ BUG();
+ HYPERVISOR_block_io_op();
+ while (atomic_read(&xlblk_control_count) != counter) barrier();
+
+ printk (KERN_ALERT "vhd block device probe:\n");
+ for ( i = 0; i < xlseg_disk_info.count; i++ )
+ {
+ printk (KERN_ALERT " %2d: type: %d, capacity: %ld\n",
+ i, xlseg_disk_info.disks[i].type,
+ xlseg_disk_info.disks[i].capacity);
}
- xvd.extents[loop].disk = (int) to_number(string);
- string = get_string(NULL); /* look for Offset */
- if (string == NULL || (*string != 'o' && *string != 'O'))
- {
- printk (KERN_ALERT
- "error: disk offset missing [%s]. should be \"offset\".\n",
- string);
- return count;
+ SET_MODULE_OWNER(&xenolinux_segment_fops);
+ result = register_blkdev(xlseg_major, "segment", &xenolinux_segment_fops);
+ if (result < 0) {
+ printk (KERN_ALERT "xenolinux segment: can't get major %d\n",
+ xlseg_major);
+ return result;
}
- string = get_string(NULL); /* offset */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: offset missing\n");
- return count;
- }
- xvd.extents[loop].offset = to_number(string);
- string = get_string(NULL); /* look for Size */
- if (string == NULL || (*string != 's' && *string != 'S'))
- {
- printk (KERN_ALERT
- "error: extent size missing [%s]. should be \"size\".\n",
- string);
- return count;
- }
- string = get_string(NULL); /* size */
- if (string == NULL)
+ /* initialize global arrays in drivers/block/ll_rw_block.c */
+ for (i = 0; i < XLSEG_MAX; i++)
{
- printk (KERN_ALERT "error: extent size missing\n");
- return count;
+ xlseg_blk_size[i] = xlseg_disk_info.disks[0].capacity ;
+ xlseg_blksize_size[i] = 512;
+ xlseg_hardsect_size[i] = 512;
+ xlseg_max_sectors[i] = 128;
}
- xvd.extents[loop].size = to_number(string);
- }
+ xlseg_read_ahead = 8;
- {
- /* get lock xlblk_control_lock */
- counter = atomic_read(&xlblk_control_count);
- atomic_inc(&xlblk_control_count);
- /* release lock xlblk_control_lock */
- }
+ blk_size[xlseg_major] = xlseg_blk_size;
+ blksize_size[xlseg_major] = xlseg_blksize_size;
+ hardsect_size[xlseg_major] = xlseg_hardsect_size;
+ read_ahead[xlseg_major] = xlseg_read_ahead;
+ max_sectors[xlseg_major] = xlseg_max_sectors;
- hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
- 0, 0, (kdev_t) 0);
- HYPERVISOR_block_io_op();
+ blk_init_queue(BLK_DEFAULT_QUEUE(xlseg_major), do_xlseg_request);
- while (atomic_read(&xlblk_control_count) != counter) barrier();
+ /*
+ * Turn off barking 'headactive' mode. We dequeue buffer heads as
+ * soon as we pass them down to Xen.
+ */
+ blk_queue_headactive(BLK_DEFAULT_QUEUE(xlseg_major), 0);
- /* while ( blk_ring->resp_prod != 1 ) barrier(); */
+ xlseg_register_disk(0, xlseg_disk_info.disks[0].capacity);
- /* mdelay(1000); */
-
- return count;
+ printk(KERN_ALERT
+ "XenoLinux Virtual Segment Device Driver installed [device: %d]\n",
+ xlseg_major);
+ return 0;
}
-/******************************************************************/
-
-int __init xlseg_init(void)
+void xlseg_register_disk(int idx, unsigned long capacity)
{
- vhd = create_proc_entry("xeno/dom0/vhd", 0644, NULL);
- if (vhd == NULL)
- {
- panic ("xlseg_init: unable to create vhd proc entry\n");
- }
- vhd->data = NULL;
- vhd->read_proc = proc_read_vhd;
- vhd->write_proc = proc_write_vhd;
- vhd->owner = THIS_MODULE;
-
- memset(&xvd, 0, sizeof(xvd));
-
- printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver installed\n");
- return 0;
+ int units;
+ int minors;
+ struct gendisk *gd;
+
+ /* plagarized from ide-probe.c::init_gendisk */
+
+ units = 2; /* from ide.h::MAX_DRIVES */
+
+#define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
+
+ minors = units * (1<<IDE_PARTN_BITS);
+ gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
+ gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
+ gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
+ memset(gd->part, 0, minors * sizeof(struct hd_struct));
+
+ gd->major = xlseg_major;
+ gd->major_name = XLSEG_MAJOR_NAME;
+ gd->minor_shift = IDE_PARTN_BITS;
+ gd->max_p = 1<<IDE_PARTN_BITS;
+ gd->nr_real = units;
+ gd->real_devices = NULL;
+ gd->next = NULL;
+ gd->fops = &xenolinux_segment_fops;
+ gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
+ gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
+
+ if (gd->de_arr)
+ memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
+
+ if (gd->flags)
+ memset (gd->flags, 0, sizeof *gd->flags * units);
+
+ add_gendisk(gd);
+
+ xlseg_disk_info.disks[idx].gendisk = gd;
+
+ register_disk(gd, MKDEV(xlseg_major, 0), 1<<IDE_PARTN_BITS,
+ &xenolinux_segment_fops, capacity);
+
+ {
+ int loop = 0;
+ printk (KERN_ALERT "Partition Table: (capacity: %lx)\n", capacity);
+ for (loop = 0; loop < minors; loop++)
+ {
+ if (gd->part[loop].start_sect && gd->part[loop].nr_sects)
+ {
+ printk (KERN_ALERT
+ " %2d: 0x%6lx %8ld 0x%6lx %7ld\n", loop,
+ gd->part[loop].start_sect, gd->part[loop].start_sect,
+ gd->part[loop].nr_sects, gd->part[loop].nr_sects);
+ }
+ }
+ }
+
+ return;
}
+
static void __exit xlseg_cleanup(void)
{
- printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver uninstalled\n");
+ /* CHANGE FOR MULTIQUEUE */
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlseg_major));
+
+ /* clean up global arrays */
+ read_ahead[xlseg_major] = 0;
+
+ if (blk_size[xlseg_major])
+ kfree(blk_size[xlseg_major]);
+ blk_size[xlseg_major] = NULL;
+
+ if (blksize_size[xlseg_major])
+ kfree(blksize_size[xlseg_major]);
+ blksize_size[xlseg_major] = NULL;
+
+ if (hardsect_size[xlseg_major])
+ kfree(hardsect_size[xlseg_major]);
+ hardsect_size[xlseg_major] = NULL;
+
+ /* XXX: free each gendisk */
+ if (unregister_blkdev(xlseg_major, "block"))
+ printk(KERN_ALERT
+ "XenoLinux Virtual Segment Device Driver uninstalled w/ errs\n");
+ else
+ printk(KERN_ALERT
+ "XenoLinux Virtual Segment Device Driver uninstalled\n");
+
+ return;
}
+
#ifdef MODULE
module_init(xlseg_init);
module_exit(xlseg_cleanup);
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c
new file mode 100644
index 0000000000..8525d7855e
--- /dev/null
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c
@@ -0,0 +1,280 @@
+/*
+ * xl_segment_proc.c
+ *
+ * XenoLinux virtual disk proc interface .
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+
+#include <asm/hypervisor-ifs/block.h>
+#include <asm/hypervisor-ifs/hypervisor-if.h>
+
+static struct proc_dir_entry *vhd;
+xv_disk_t xvd;
+
+extern atomic_t xlblk_control_count; /* xl_block.c */
+
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd);
+
+/******************************************************************/
+
+static int proc_read_vhd(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ return 0;
+}
+
+#define isdelim(c) \
+ (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
+
+char *get_string(char *string) /* a bit like strtok */
+{
+ static char *temp;
+ int loop = 0;
+
+ if (string != NULL)
+ temp = string;
+ else
+ string = temp;
+
+ try_again:
+
+ while (!isdelim(string[loop]))
+ {
+ if (string[loop] == '\0')
+ return NULL;
+ loop++;
+ }
+
+ string[loop] = '\0';
+ temp = (string + loop + 1);
+
+ if (loop == 0)
+ {
+ string = temp;
+ goto try_again;
+ }
+
+ return string;
+}
+
+
+#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
+unsigned long to_number(char *string) /* atoi */
+{
+ unsigned long value = 0;
+
+ if (string == NULL) return 0;
+
+ while (!isdigit(*string) && *string != '\0') string++;
+
+ while (isdigit(*string))
+ {
+ value = value * 10 + (*string - '0');
+ string++;
+ }
+
+ return value;
+}
+
+static int proc_write_vhd(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
+ char *string;
+ int loop;
+ int counter;
+ xv_disk_t xvd;
+
+ memset (&xvd, 0, sizeof(xvd));
+
+ if (copy_from_user(local, buffer, count))
+ {
+ return -EFAULT;
+ }
+ local[count] = '\0';
+
+ string = get_string(local); /* look for Domain */
+ if (string == NULL) /* empty string */
+ {
+ return count;
+ }
+ if (*string != 'd' && *string != 'D')
+ {
+ printk (KERN_ALERT
+ "error: domain specifier missing [%s]. should be \"domain\".\n",
+ string);
+ return count;
+ }
+
+ string = get_string(NULL); /* domain number */
+ if (string == NULL)
+ {
+ printk (KERN_ALERT "error: domain number missing\n");
+ return count;
+ }
+ xvd.domain = (int) to_number(string);
+
+ string = get_string(NULL);
+ if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
+ {
+ xvd.mode = XEN_DISK_READ_ONLY;
+ }
+ else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
+ {
+ xvd.mode = XEN_DISK_READ_WRITE;
+ }
+ else
+ {
+ printk (KERN_ALERT
+ "error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
+ string);
+ return count;
+ }
+
+ string = get_string(NULL); /* look for Segment */
+ if (string == NULL || (*string != 's' && *string != 'S'))
+ {
+ printk (KERN_ALERT
+ "error: segment specifier missing [%s]. should be \"segment\".\n",
+ string);
+ return count;
+ }
+
+ string = get_string(NULL); /* segment number */
+ if (string == NULL)
+ {
+ printk (KERN_ALERT "error: segment number missing\n");
+ return count;
+ }
+ xvd.segment = (int) to_number(string);
+
+ string = get_string(NULL); /* look for Extents */
+ if (string == NULL || (*string != 'e' && *string != 'E'))
+ {
+ printk (KERN_ALERT
+ "error: extents specifier missing [%s]. should be \"extents\".\n",
+ string);
+ return count;
+ }
+
+ string = get_string(NULL); /* number of extents */
+ if (string == NULL)
+ {
+ printk (KERN_ALERT "error: number of extents missing\n");
+ return count;
+ }
+ xvd.ext_count = (int) to_number(string);
+
+ /* ignore parenthesis */
+
+ for (loop = 0; loop < xvd.ext_count; loop++)
+ {
+ string = get_string(NULL); /* look for Disk */
+ if (string == NULL || (*string != 'd' && *string != 'D'))
+ {
+ printk (KERN_ALERT
+ "hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
+ string);
+ return count;
+ }
+ string = get_string(NULL); /* disk number */
+ if (string == NULL)
+ {
+ printk (KERN_ALERT "error: disk number missing\n");
+ return count;
+ }
+ xvd.extents[loop].disk = (int) to_number(string);
+
+ string = get_string(NULL); /* look for Offset */
+ if (string == NULL || (*string != 'o' && *string != 'O'))
+ {
+ printk (KERN_ALERT
+ "error: disk offset missing [%s]. should be \"offset\".\n",
+ string);
+ return count;
+ }
+ string = get_string(NULL); /* offset */
+ if (string == NULL)
+ {
+ printk (KERN_ALERT "error: offset missing\n");
+ return count;
+ }
+ xvd.extents[loop].offset = to_number(string);
+
+ string = get_string(NULL); /* look for Size */
+ if (string == NULL || (*string != 's' && *string != 'S'))
+ {
+ printk (KERN_ALERT
+ "error: extent size missing [%s]. should be \"size\".\n",
+ string);
+ return count;
+ }
+ string = get_string(NULL); /* size */
+ if (string == NULL)
+ {
+ printk (KERN_ALERT "error: extent size missing\n");
+ return count;
+ }
+ xvd.extents[loop].size = to_number(string);
+ }
+
+ {
+ /* get lock xlblk_control_lock */
+ counter = atomic_read(&xlblk_control_count);
+ atomic_inc(&xlblk_control_count);
+ /* release lock xlblk_control_lock */
+ }
+ if (hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
+ 0, 0, (kdev_t) 0,
+ (struct gendisk *)NULL))
+ BUG();
+ HYPERVISOR_block_io_op();
+
+ while (atomic_read(&xlblk_control_count) != counter) barrier();
+
+ return count;
+}
+
+/******************************************************************/
+
+int __init xlseg_proc_init(void)
+{
+ vhd = create_proc_entry("xeno/dom0/vhd", 0644, NULL);
+ if (vhd == NULL)
+ {
+ panic ("xlseg_init: unable to create vhd proc entry\n");
+ }
+ vhd->data = NULL;
+ vhd->read_proc = proc_read_vhd;
+ vhd->write_proc = proc_write_vhd;
+ vhd->owner = THIS_MODULE;
+
+ memset(&xvd, 0, sizeof(xvd));
+
+ printk(KERN_ALERT "XenoLinux Virtual Disk Device Monitor installed\n");
+ return 0;
+}
+
+static void __exit xlseg_proc_cleanup(void)
+{
+ printk(KERN_ALERT "XenoLinux Virtual Disk Device Monitor uninstalled\n");
+}
+
+#ifdef MODULE
+module_init(xlseg_proc_init);
+module_exit(xlseg_proc_cleanup);
+#endif
diff --git a/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c b/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c
index 470b206726..842dd069f1 100644
--- a/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c
+++ b/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c
@@ -1505,6 +1505,7 @@ int __init blk_dev_init(void)
#ifdef CONFIG_XENOLINUX_BLOCK
xlblk_init();
xlseg_init();
+ xlseg_proc_init();
#endif
return 0;
diff --git a/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h b/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h
index 0be65ab99d..e7fa201955 100644
--- a/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h
+++ b/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h
@@ -328,6 +328,13 @@ static void floppy_off(unsigned int nr);
/* #define DEVICE_INTR */
#define DEVICE_NR(device) (MINOR(device))
+#elif (MAJOR_NR == XLSEG_MAJOR)
+
+#define DEVICE_NAME "xeno segment"
+#define DEVICE_REQUEST do_xlseg_request
+/* #define DEVICE_INTR */
+#define DEVICE_NR(device) (MINOR(device))
+
#endif /* MAJOR_NR == whatever */
/* provide DEVICE_xxx defaults, if not explicitly defined
diff --git a/xenolinux-2.4.21-pre4-sparse/include/linux/major.h b/xenolinux-2.4.21-pre4-sparse/include/linux/major.h
index dfcb6f79f0..9cac1c2881 100644
--- a/xenolinux-2.4.21-pre4-sparse/include/linux/major.h
+++ b/xenolinux-2.4.21-pre4-sparse/include/linux/major.h
@@ -145,7 +145,8 @@
#define UMEM_MAJOR 116 /* http://www.umem.com/ Battery Backed RAM */
-#define XLBLK_MAJOR 123 /* XenoLinux Block Device */
+/* note: 123, 124, 125, 126 and 234, 235, 236, 237 are defined in xeno_major */
+#include <asm/hypervisor-ifs/xeno-major.h>
#define RTF_MAJOR 150
#define RAW_MAJOR 162
diff --git a/xenolinux-2.4.21-pre4-sparse/init/do_mounts.c b/xenolinux-2.4.21-pre4-sparse/init/do_mounts.c
index b0b143a264..ddf2f96a39 100644
--- a/xenolinux-2.4.21-pre4-sparse/init/do_mounts.c
+++ b/xenolinux-2.4.21-pre4-sparse/init/do_mounts.c
@@ -235,6 +235,10 @@ static struct dev_name_struct {
{ "xhdb", 0x7C00 },
{ "xhdc", 0x7D00 },
{ "xhdd", 0x7E00 },
+ { "vhda", 0xEA00 },
+ { "vhdb", 0xEB00 },
+ { "vhdc", 0xEC00 },
+ { "vhdd", 0xED00 },
#endif
{ "nftla", 0x5d00 },
{ "nftlb", 0x5d10 },