aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>2003-02-26 19:16:57 +0000
committerach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>2003-02-26 19:16:57 +0000
commit47b95f44ede3bb13fd5d22e29921255274f87926 (patch)
tree2a9c5a4ab49718f738ea8f196bf677af47006257
parent7218befbfab0c96a243fb8345f7e0e574b4926eb (diff)
downloadxen-47b95f44ede3bb13fd5d22e29921255274f87926.tar.gz
xen-47b95f44ede3bb13fd5d22e29921255274f87926.tar.bz2
xen-47b95f44ede3bb13fd5d22e29921255274f87926.zip
bitkeeper revision 1.100.1.1 (3e5d12a9XS1t15We3dHlj4sxiwEeWQ)
add create segment code in xen, /proc/xeno/dom0/vhd in xenolinux
-rw-r--r--.rootkeys3
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--xen/Makefile2
-rw-r--r--xen/drivers/block/xen_block.c67
-rw-r--r--xen/drivers/block/xen_segment.c137
-rw-r--r--xen/drivers/ide/ide-xeno.c13
-rw-r--r--xen/include/hypervisor-ifs/block.h58
-rw-r--r--xen/include/xeno/sched.h3
-rw-r--r--xen/include/xeno/segment.h52
-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.c25
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c43
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c275
-rw-r--r--xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c1
14 files changed, 648 insertions, 34 deletions
diff --git a/.rootkeys b/.rootkeys
index 79b0d1d197..bd815702a8 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -249,6 +249,7 @@
3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c
3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
+3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c
3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/xen_serial.c
@@ -438,6 +439,7 @@
3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xeno/prefetch.h
3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h
3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h
+3e5d129a2bbGTpVSZFN_mAnbm97ixw xen/include/xeno/segment.h
3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h
3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h
3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h
@@ -466,6 +468,7 @@
3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
+3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/Makefile
3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/console.c
3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/Makefile
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index f4f9934995..cc166e6358 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -1,3 +1,4 @@
+ach61@labyrinth.cl.cam.ac.uk
akw27@boulderdash.cl.cam.ac.uk
akw27@labyrinth.cl.cam.ac.uk
akw27@plucky.localdomain
diff --git a/xen/Makefile b/xen/Makefile
index 3bd4299075..85e4514919 100644
--- a/xen/Makefile
+++ b/xen/Makefile
@@ -39,3 +39,5 @@ TAGS:
find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
find $(SUBDIRS) -name '*.[ch]' | xargs etags -a
+MAP:
+ nm image | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
diff --git a/xen/drivers/block/xen_block.c b/xen/drivers/block/xen_block.c
index 805fd9e1ae..8e1ff1188b 100644
--- a/xen/drivers/block/xen_block.c
+++ b/xen/drivers/block/xen_block.c
@@ -1,5 +1,5 @@
/*
- * xen-block.c
+ * xen_block.c
*
* process incoming block io requests from guestos's.
*/
@@ -16,6 +16,7 @@
#include <asm/spinlock.h>
#include <xeno/keyhandler.h>
#include <xeno/interrupt.h>
+#include <xeno/segment.h>
#if 0
#define DPRINTK(_f, _a...) printk( _f , ## _a )
@@ -42,7 +43,10 @@ static int do_block_io_op_domain(struct task_struct *p, int max_to_do);
static void dispatch_rw_block_io(struct task_struct *p, int index);
static void dispatch_probe_block_io(struct task_struct *p, int index);
static void dispatch_debug_block_io(struct task_struct *p, int index);
-static void make_response(struct task_struct *p, void *id, unsigned long st);
+static void dispatch_create_segment(struct task_struct *p, int index);
+static void dispatch_delete_segment(struct task_struct *p, int index);
+static void make_response(struct task_struct *p, void *id, int op,
+ unsigned long st);
/******************************************************************
@@ -149,7 +153,8 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate)
}
atomic_dec(&nr_pending);
- make_response(bh->b_xen_domain, bh->b_xen_id, uptodate ? 0 : 1);
+ make_response(bh->b_xen_domain, bh->b_xen_id,
+ XEN_BLOCK_READ, uptodate ? 0 : 1);
kmem_cache_free(buffer_head_cachep, bh);
@@ -205,6 +210,14 @@ static int do_block_io_op_domain(struct task_struct* p, int max_to_do)
dispatch_debug_block_io(p, i);
break;
+ case XEN_BLOCK_SEG_CREATE:
+ dispatch_create_segment(p, i);
+ break;
+
+ case XEN_BLOCK_SEG_DELETE:
+ dispatch_delete_segment(p, i);
+ break;
+
default:
panic("error: unknown block io operation [%d]\n",
blk_ring->ring[i].req.operation);
@@ -220,16 +233,43 @@ static void dispatch_debug_block_io(struct task_struct *p, int index)
DPRINTK("dispatch_debug_block_io: unimplemented\n");
}
+static void dispatch_create_segment(struct task_struct *p, int index)
+{
+ blk_ring_t *blk_ring = p->blk_ring_base;
+ xv_disk_t *xvd;
+ int result;
+
+ if (p->domain != 0)
+ {
+ printk (KERN_ALERT "dispatch_create_segment called by dom%d\n", p->domain);
+ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1);
+ return;
+ }
+
+ xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
+ result = xen_segment_create(xvd);
+ make_response(p, blk_ring->ring[index].req.id,
+ XEN_BLOCK_SEG_CREATE, result);
+ return;
+}
+
+static void dispatch_delete_segment(struct task_struct *p, int index)
+{
+ DPRINTK("dispatch_delete_segment: unimplemented\n");
+}
+
static void dispatch_probe_block_io(struct task_struct *p, int index)
{
- extern void ide_probe_devices(xen_disk_info_t *xdi);
+ extern void ide_probe_devices(xen_disk_info_t *xdi, int *count,
+ drive_t xdrives[]);
blk_ring_t *blk_ring = p->blk_ring_base;
xen_disk_info_t *xdi;
xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
- ide_probe_devices(xdi);
+ ide_probe_devices(xdi, &num_xdrives, xdrives);
+ /* scsi_probe_devices(xdi, &num_xdrives, xdrives); */ /* future */
- make_response(p, blk_ring->ring[index].req.id, 0);
+ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, 0);
}
static void dispatch_rw_block_io(struct task_struct *p, int index)
@@ -333,9 +373,9 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
return;
bad_descriptor:
- make_response(p, blk_ring->ring[index].req.id, 1);
+ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_READ, 1);
return;
-}
+}
@@ -343,7 +383,8 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
* MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
*/
-static void make_response(struct task_struct *p, void *id, unsigned long st)
+static void make_response(struct task_struct *p, void *id,
+ int op, unsigned long st)
{
unsigned long cpu_mask, flags;
int position;
@@ -353,8 +394,9 @@ static void make_response(struct task_struct *p, void *id, unsigned long st)
spin_lock_irqsave(&p->blk_ring_lock, flags);
blk_ring = p->blk_ring_base;
position = blk_ring->resp_prod;
- blk_ring->ring[position].resp.id = id;
- blk_ring->ring[position].resp.status = st;
+ blk_ring->ring[position].resp.id = id;
+ blk_ring->ring[position].resp.operation = op;
+ blk_ring->ring[position].resp.status = st;
blk_ring->resp_prod = BLK_RING_INC(position);
spin_unlock_irqrestore(&p->blk_ring_lock, flags);
@@ -377,6 +419,7 @@ void init_blkdev_info(struct task_struct *p)
clear_page(p->blk_ring_base);
SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p->domain);
p->blkdev_list.next = NULL;
+ p->segment_count = 0;
}
/* End-of-day teardown for a domain. XXX Outstanding requests? */
@@ -397,6 +440,8 @@ void initialize_block_io ()
buffer_head_cachep = kmem_cache_create(
"buffer_head_cache", sizeof(struct buffer_head),
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+ xen_segment_initialize();
add_key_handler('b', dump_blockq, "dump xen ide blkdev stats");
}
diff --git a/xen/drivers/block/xen_segment.c b/xen/drivers/block/xen_segment.c
new file mode 100644
index 0000000000..1105afe1c7
--- /dev/null
+++ b/xen/drivers/block/xen_segment.c
@@ -0,0 +1,137 @@
+/*
+ * xen_segment.c
+ */
+
+#include <xeno/config.h>
+#include <xeno/types.h>
+#include <xeno/lib.h>
+#include <asm/io.h>
+#include <xeno/slab.h>
+#include <xeno/segment.h>
+#include <xeno/sched.h>
+#include <xeno/keyhandler.h>
+#include <hypervisor-ifs/block.h>
+
+int num_xdrives;
+drive_t xdrives[XEN_MAX_DISK_COUNT];
+
+segment_t xsegments[XEN_MAX_SEGMENTS];
+
+/*
+ * xen_refresh_segment_list
+ *
+ * find all segments associated with a domain and assign
+ * them to the domain
+ */
+void xen_refresh_segment_list (struct task_struct *p)
+{
+ int loop;
+
+ for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
+ {
+ if (xsegments[loop].mode != XEN_SEGMENT_UNUSED &&
+ xsegments[loop].domain == p->domain)
+ {
+ p->segment_list[xsegments[loop].segment_number] = &xsegments[loop];
+ p->segment_count++;
+ }
+ }
+ return;
+}
+
+/*
+ * create a new segment for a domain
+ *
+ * return 0 on success, 1 on failure
+ *
+ * TODO: need to check to see if the DOM#/SEG# combination
+ * already exists. if so, reuse the slot in the segment table.
+ */
+int xen_segment_create(xv_disk_t *xvd_in)
+{
+ int idx;
+ int loop;
+ xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
+
+ for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++)
+ {
+ if (xsegments[idx].mode == XEN_SEGMENT_UNUSED) break;
+ }
+ if (idx == XEN_MAX_SEGMENTS)
+ {
+ printk (KERN_ALERT "error: xen_segment_create unable to find free slot\n");
+ return 1;
+ }
+
+ xsegments[idx].mode = xvd->mode;
+ xsegments[idx].domain = xvd->domain;
+ xsegments[idx].segment_number = xvd->segment;
+ xsegments[idx].num_extents = xvd->ext_count;
+ xsegments[idx].extents = (extent_t *)kmalloc(sizeof(extent_t)*xvd->ext_count,
+ GFP_KERNEL);
+
+ /* could memcpy, but this is safer */
+ for (loop = 0; loop < xvd->ext_count; loop++)
+ {
+ xsegments[idx].extents[loop].disk = xvd->extents[loop].disk;
+ xsegments[idx].extents[loop].offset = xvd->extents[loop].offset;
+ xsegments[idx].extents[loop].size = xvd->extents[loop].size;
+ }
+
+ return 0;
+}
+
+/*
+ * delete a segment from a domain
+ *
+ * return 0 on success, 1 on failure
+ *
+ * TODO: caller must ensure that only domain 0 calls this function
+ */
+int xen_segment_delete(struct task_struct *p, xv_disk_t *xvd)
+{
+ return 0;
+}
+
+static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs)
+{
+ int loop, i;
+
+ printk (KERN_ALERT "xdrives\n");
+ for (loop = 0; loop < num_xdrives; loop++)
+ {
+ printk (KERN_ALERT " %2d: major: 0x%d\n", loop, xdrives[loop].major);
+ }
+
+ printk (KERN_ALERT "segments\n");
+ for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
+ {
+ if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
+ {
+ printk (KERN_ALERT " %2d: %s dom%d, seg# %d, num_exts: %d\n",
+ loop,
+ xsegments[loop].mode == XEN_SEGMENT_RO ? "RO" : "RW",
+ xsegments[loop].domain, xsegments[loop].segment_number,
+ xsegments[loop].num_extents);
+ for (i = 0; i < xsegments[loop].num_extents; i++)
+ {
+ printk (KERN_ALERT " ext %d: disk %d, offset 0x%lx, size 0x%lx\n",
+ i, xsegments[loop].extents[i].disk,
+ xsegments[loop].extents[i].offset,
+ xsegments[loop].extents[i].size);
+ }
+ }
+ }
+}
+
+/*
+ * initialize segments
+ */
+
+void xen_segment_initialize(void)
+{
+ memset (xdrives, 0, sizeof(xdrives));
+ memset (xsegments, 0, sizeof(xsegments));
+
+ add_key_handler('S', dump_segments, "dump segments");
+}
diff --git a/xen/drivers/ide/ide-xeno.c b/xen/drivers/ide/ide-xeno.c
index 0b7e481ddf..9da5a89b9b 100644
--- a/xen/drivers/ide/ide-xeno.c
+++ b/xen/drivers/ide/ide-xeno.c
@@ -2,11 +2,12 @@
#include <xeno/types.h>
#include <xeno/lib.h>
#include <xeno/ide.h>
+#include <xeno/segment.h>
#include <hypervisor-ifs/block.h>
#include <asm/domain_page.h>
#include <asm/io.h>
-void ide_probe_devices (xen_disk_info_t* xdi)
+void ide_probe_devices (xen_disk_info_t* xdi, int *count, drive_t xdrives[])
{
int loop;
unsigned int unit;
@@ -21,21 +22,27 @@ void ide_probe_devices (xen_disk_info_t* xdi)
unsigned long capacity;
ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
- capacity = current_capacity (drive);
+ /* only count drives with capacity > 0. this excludes cdroms */
+ if (drive->present && (capacity = current_capacity(drive)))
+ {
xen_xdi->disks[xen_xdi->count].type = XEN_DISK_IDE;
xen_xdi->disks[xen_xdi->count].capacity = capacity;
+ xdrives[xen_xdi->count].major = hwif->major;
xen_xdi->count++;
+ /*
printk (KERN_ALERT "IDE-XENO %d\n", xen_xdi->count);
printk (KERN_ALERT " capacity 0x%lx\n", capacity);
printk (KERN_ALERT " head 0x%x\n", drive->bios_head);
printk (KERN_ALERT " sector 0x%x\n", drive->bios_sect);
printk (KERN_ALERT " cylinder 0x%x\n", drive->bios_cyl);
+ printk (KERN_ALERT " major 0x%x\n", hwif->major);
+ */
}
}
}
}
+ *count = xen_xdi->count;
unmap_domain_mem(xen_xdi);
}
diff --git a/xen/include/hypervisor-ifs/block.h b/xen/include/hypervisor-ifs/block.h
index 627055bf0b..908f8382cc 100644
--- a/xen/include/hypervisor-ifs/block.h
+++ b/xen/include/hypervisor-ifs/block.h
@@ -1,10 +1,7 @@
/******************************************************************************
* block.h
*
- * Block IO communication rings.
- *
- * These are the ring data structures for buffering messages between
- * the hypervisor and guestos's.
+ * shared structures for block IO.
*
*/
@@ -13,6 +10,13 @@
#include <linux/kdev_t.h>
+/*
+ *
+ * These are the ring data structures for buffering messages between
+ * the hypervisor and guestos's.
+ *
+ */
+
/* the first four definitions match fs.h */
#define XEN_BLOCK_READ 0
#define XEN_BLOCK_WRITE 1
@@ -20,6 +24,8 @@
#define XEN_BLOCK_SPECIAL 4 /* currently unused */
#define XEN_BLOCK_PROBE 8 /* determine io configuration from hypervisor */
#define XEN_BLOCK_DEBUG 16 /* debug */
+#define XEN_BLOCK_SEG_CREATE 32 /* create segment (vhd) */
+#define XEN_BLOCK_SEG_DELETE 64 /* delete segment (vhd) */
#define BLK_RING_SIZE 128
#define BLK_RING_MAX_ENTRIES (BLK_RING_SIZE - 2)
@@ -29,7 +35,7 @@
typedef struct blk_ring_req_entry
{
void * id; /* for guest os use */
- int operation; /* XEN_BLOCK_READ or XEN_BLOCK_WRITE */
+ int operation; /* from above */
char * buffer;
unsigned long block_number; /* block number */
unsigned short block_size; /* block size */
@@ -39,8 +45,9 @@ typedef struct blk_ring_req_entry
typedef struct blk_ring_resp_entry
{
- void *id;
- unsigned long status;
+ void * id; /* for guest os use */
+ int operation; /* from above */
+ unsigned long status;
} blk_ring_resp_entry_t;
typedef struct blk_ring_st
@@ -53,7 +60,13 @@ typedef struct blk_ring_st
} ring[BLK_RING_SIZE];
} blk_ring_t;
-#define MAX_XEN_DISK_COUNT 100
+/*
+ *
+ * physical disk (xhd) info, used by XEN_BLOCK_PROBE
+ *
+ */
+
+#define XEN_MAX_DISK_COUNT 100
#define XEN_DISK_IDE 1
#define XEN_DISK_SCSI 2
@@ -71,8 +84,33 @@ typedef struct xen_disk /* physical disk */
typedef struct xen_disk_info
{
- int count; /* number of subsequent xen_disk_t structures to follow */
- xen_disk_t disks[100];
+ int count; /* number of xen_disk_t structures to follow */
+ xen_disk_t disks[XEN_MAX_DISK_COUNT];
} xen_disk_info_t;
+/*
+ *
+ * virtual disk (vhd) structures, used by XEN_BLOCK_SEG_{CREATE, DELETE}
+ *
+ */
+
+#define XEN_DISK_READ_WRITE 1
+#define XEN_DISK_READ_ONLY 2
+
+typedef struct xv_extent
+{
+ int disk; /* physical disk number */
+ unsigned long offset; /* offset in blocks into physical disk */
+ unsigned long size; /* size in blocks */
+} xv_extent_t;
+
+typedef struct xv_disk
+{
+ int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */
+ int domain; /* domain */
+ int segment; /* segment number */
+ int ext_count; /* number of xv_extent_t to follow */
+ xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */
+} xv_disk_t;
+
#endif
diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h
index b0855f7b0a..0b7d96d790 100644
--- a/xen/include/xeno/sched.h
+++ b/xen/include/xeno/sched.h
@@ -55,6 +55,7 @@ extern struct mm_struct init_mm;
#include <xeno/vif.h>
#include <xeno/block.h>
+#include <xeno/segment.h>
struct task_struct {
@@ -79,6 +80,8 @@ struct task_struct {
unsigned int blk_req_cons; /* request consumer */
struct list_head blkdev_list;
spinlock_t blk_ring_lock;
+ segment_t *segment_list[XEN_MAX_SEGMENTS]; /* vhd */
+ int segment_count;
int has_cpu, policy, counter;
diff --git a/xen/include/xeno/segment.h b/xen/include/xeno/segment.h
new file mode 100644
index 0000000000..f0bf08ffbd
--- /dev/null
+++ b/xen/include/xeno/segment.h
@@ -0,0 +1,52 @@
+#ifndef __SEGMENT_H__
+#define __SEGMENT_H__
+
+#include <hypervisor-ifs/block.h>
+
+void xen_segment_initialize(void);
+void xen_refresh_segment_list (struct task_struct *p);
+int xen_segment_create(xv_disk_t *xvd);
+
+#define XEN_MAX_SEGMENTS 100 /* total number of segments across all doms */
+
+/*
+ * every physical disk that xen has access to is listed in the drives array.
+ * we export the drive# to domain 0. to xen, each drive is just one long
+ * array of blocks.
+ */
+
+typedef struct drive
+{
+ unsigned int major;
+} drive_t;
+
+extern int num_xdrives;
+extern drive_t xdrives[XEN_MAX_DISK_COUNT];
+
+/*
+ * virtual hard disks
+ *
+ * each segment is composed of a number of extents
+ */
+
+typedef struct extent
+{
+ int disk; /* index into drives array of where this extent lives */
+ unsigned long offset; /* offset into disk */
+ unsigned long size; /* size of this extent */
+} extent_t;
+
+#define XEN_SEGMENT_UNUSED 0 /* bzero default */
+#define XEN_SEGMENT_RO XEN_DISK_READ_WRITE
+#define XEN_SEGMENT_RW XEN_DISK_READ_ONLY
+
+typedef struct segment
+{
+ int mode; /* UNUSED, RO, or RW */
+ int domain;
+ int segment_number; /* segment number for domain */
+ int num_extents; /* number of extents */
+ extent_t *extents;
+} segment_t;
+
+#endif
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 74a0c6c565..c6d1c7dc63 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_block_test.o
+obj-y := xl_block.o xl_segment.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 0b77e5536e..6e7e713c86 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
@@ -22,6 +22,7 @@
#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 XLBLK_MAJOR /* force defns in blk.h, must precede include */
@@ -58,6 +59,7 @@ 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;
+atomic_t xlblk_control_count;
int hypervisor_request(void * id,
int operation,
@@ -166,7 +168,7 @@ static int xenolinux_block_revalidate(kdev_t dev)
* virtual address in the guest os.
* block_number: block to read
* block_size: size of each block
- * device: ide/hda is 768 or 0x300
+ * device: ide/hda is 768 or 0x300 should be disk#!!!
*/
int hypervisor_request(void * id,
int operation,
@@ -193,6 +195,8 @@ int hypervisor_request(void * id,
switch ( operation )
{
+ case XEN_BLOCK_SEG_CREATE:
+ case XEN_BLOCK_SEG_DELETE:
case XEN_BLOCK_PROBE:
phys_device = (kdev_t) 0;
sector_number = 0;
@@ -321,7 +325,21 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
i = BLK_RING_INC(i) )
{
blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp;
- if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1);
+ switch (bret->operation)
+ {
+ case XEN_BLOCK_READ :
+ case XEN_BLOCK_WRITE :
+ if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1);
+ break;
+
+ case XEN_BLOCK_SEG_CREATE :
+ case XEN_BLOCK_SEG_DELETE :
+ atomic_dec(&xlblk_control_count);
+ break;
+
+ default:
+ break;
+ }
}
resp_cons = i;
@@ -337,6 +355,8 @@ int __init xlblk_init(void)
{
int i, error, result;
+ atomic_set(&xlblk_control_count, 0);
+
/* This mapping was created early at boot time. */
blk_ring = (blk_ring_t *)fix_to_virt(FIX_BLKRING_BASE);
blk_ring->req_prod = blk_ring->resp_prod = resp_cons = 0;
@@ -356,6 +376,7 @@ int __init xlblk_init(void)
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 " %2d: type: %d, capacity: %ld\n",
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 2ddef271e5..8d695689ba 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
@@ -138,6 +138,11 @@ int proc_write_bdt(struct file *file, const char *buffer,
sscanf(local, "%c %i %i %i",
&opcode, &block_number, &block_size, &device);
+ if (data)
+ {
+ kfree(data);
+ }
+
if (opcode == 'r' || opcode == 'R')
{
meta.operation = XEN_BLOCK_READ;
@@ -151,6 +156,31 @@ int proc_write_bdt(struct file *file, const char *buffer,
meta.operation = XEN_BLOCK_DEBUG;
block_size = 10000;
}
+ else if (opcode == 'c' || opcode == 'C')
+ {
+ xv_disk_t *xvd;
+ int loop;
+
+ meta.operation = XEN_BLOCK_SEG_CREATE;
+ data = kmalloc (sizeof(xv_disk_t), GFP_KERNEL);
+ if (data == NULL)
+ {
+ kfree(local);
+ return -ENOMEM;
+ }
+
+ xvd = (xv_disk_t *)data;
+ xvd->mode = XEN_DISK_READ_WRITE;
+ xvd->domain = block_number;
+ xvd->segment = block_size;
+ xvd->ext_count = device;
+ for (loop = 0; loop < xvd->ext_count; loop++)
+ {
+ xvd->extents[loop].disk = block_number + 1; /* random */
+ xvd->extents[loop].offset = block_size + 1;
+ xvd->extents[loop].size = device + 1;
+ }
+ }
else
{
printk(KERN_ALERT
@@ -158,15 +188,14 @@ int proc_write_bdt(struct file *file, const char *buffer,
return -EINVAL;
}
- if (data)
- {
- kfree(data);
- }
- data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
if (data == NULL)
{
- kfree(local);
- return -ENOMEM;
+ data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
+ if (data == NULL)
+ {
+ kfree(local);
+ return -ENOMEM;
+ }
}
meta.block_number = block_number;
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
new file mode 100644
index 0000000000..da14be14df
--- /dev/null
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
@@ -0,0 +1,275 @@
+/*
+ * xl_segment.c
+ *
+ * XenoLinux virtual disk driver.
+ */
+
+
+#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 */
+
+/******************************************************************/
+
+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_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;
+ }
+ 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 */
+ }
+
+ hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
+ 0, 0, (kdev_t) 0);
+ HYPERVISOR_block_io_op();
+
+ while (atomic_read(&xlblk_control_count) != counter) barrier();
+
+ /* while ( blk_ring->resp_prod != 1 ) barrier(); */
+
+ /* mdelay(1000); */
+
+ return count;
+}
+
+/******************************************************************/
+
+int __init xlseg_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 Driver installed\n");
+ return 0;
+}
+
+static void __exit xlseg_cleanup(void)
+{
+ printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver uninstalled\n");
+}
+
+#ifdef MODULE
+module_init(xlseg_init);
+module_exit(xlseg_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 4fd98e94a5..470b206726 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
@@ -1504,6 +1504,7 @@ int __init blk_dev_init(void)
#ifdef CONFIG_XENOLINUX_BLOCK
xlblk_init();
+ xlseg_init();
#endif
return 0;