From 47b95f44ede3bb13fd5d22e29921255274f87926 Mon Sep 17 00:00:00 2001 From: "ach61@labyrinth.cl.cam.ac.uk" Date: Wed, 26 Feb 2003 19:16:57 +0000 Subject: bitkeeper revision 1.100.1.1 (3e5d12a9XS1t15We3dHlj4sxiwEeWQ) add create segment code in xen, /proc/xeno/dom0/vhd in xenolinux --- .rootkeys | 3 + BitKeeper/etc/logging_ok | 1 + xen/Makefile | 2 + xen/drivers/block/xen_block.c | 67 ++++- xen/drivers/block/xen_segment.c | 137 ++++++++++ xen/drivers/ide/ide-xeno.c | 13 +- xen/include/hypervisor-ifs/block.h | 58 ++++- xen/include/xeno/sched.h | 3 + xen/include/xeno/segment.h | 52 ++++ .../arch/xeno/drivers/block/Makefile | 2 +- .../arch/xeno/drivers/block/xl_block.c | 25 +- .../arch/xeno/drivers/block/xl_block_test.c | 43 +++- .../arch/xeno/drivers/block/xl_segment.c | 275 +++++++++++++++++++++ .../drivers/block/ll_rw_blk.c | 1 + 14 files changed, 648 insertions(+), 34 deletions(-) create mode 100644 xen/drivers/block/xen_segment.c create mode 100644 xen/include/xeno/segment.h create mode 100644 xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c 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 #include #include +#include #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 +#include +#include +#include +#include +#include +#include +#include +#include + +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 #include #include +#include #include #include #include -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 +/* + * + * 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 #include +#include 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 + +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 #include #include +#include #include #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 +#include + +#include +#include +#include +#include + +#include +#include + +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; -- cgit v1.2.3