diff options
author | smh22@labyrinth.cl.cam.ac.uk <smh22@labyrinth.cl.cam.ac.uk> | 2003-11-05 11:48:22 +0000 |
---|---|---|
committer | smh22@labyrinth.cl.cam.ac.uk <smh22@labyrinth.cl.cam.ac.uk> | 2003-11-05 11:48:22 +0000 |
commit | 1f84a5b71495d69429091ee4c3d7167f1c23d600 (patch) | |
tree | 6f01519e73d1c29a1dd282bb97eb5313e5ce0328 | |
parent | 589d8fae088b3a9092e2206abc6ad46e8a0d20dd (diff) | |
download | xen-1f84a5b71495d69429091ee4c3d7167f1c23d600.tar.gz xen-1f84a5b71495d69429091ee4c3d7167f1c23d600.tar.bz2 xen-1f84a5b71495d69429091ee4c3d7167f1c23d600.zip |
bitkeeper revision 1.558.1.1 (3fa8e386Q1b8azxmK348LEgk5Ph0JQ)
simpler unified vbd / physdisk stuff
30 files changed, 659 insertions, 2381 deletions
@@ -169,8 +169,6 @@ 3ec43c5dmQxGDvgJJXbV1yLxT30Y1A tools/internal/xi_helper 3f108ad5wQm0ZaQ4GXFoUhH1W1aW9w tools/internal/xi_list.c 3f0458aaXhD8BQAggO81gv30RQ-ifA tools/internal/xi_phys_grant.c -3f0458aaJHmlzkDwf0qxEzAcjX55sg tools/internal/xi_phys_probe.c -3f0458aaVAbFSwptQbQAnDOiZlwQ3w tools/internal/xi_phys_revoke.c 3f108adb2b5OkKL6-faG3lMiOYDf_w tools/internal/xi_sched_domain.c 3f108ade1v8weyh1sKx890VTd240Hw tools/internal/xi_sched_global.c 3eb781fd8oRfPgH7qTh7xvgmwD6NgA tools/internal/xi_start.c @@ -571,8 +569,6 @@ 3f689056Vxx_8K8DQTRysOxx_ikmLg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/info.c 3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c 3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h -3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_ide.c -3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_scsi.c 3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c 3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.22-sparse/arch/xeno/drivers/console/Makefile 3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.22-sparse/arch/xeno/drivers/console/console.c @@ -607,11 +603,6 @@ 3f108aeaLcGDgQdFAANLTUEid0a05w xenolinux-2.4.22-sparse/drivers/char/mem.c 3e5a4e66rw65CxyolW9PKz4GG42RcA xenolinux-2.4.22-sparse/drivers/char/tty_io.c 3e5a4e669uzIE54VwucPYtGwXLAbzA xenolinux-2.4.22-sparse/fs/exec.c -3f05a939l8s0eQb_fpMvYiI06cTGlA xenolinux-2.4.22-sparse/fs/partitions/Config.in -3f05a939W65febbeWrBtuQgsQDK2Bg xenolinux-2.4.22-sparse/fs/partitions/Makefile -3f05a939phguW4R5PelNQZ8o_EcYZA xenolinux-2.4.22-sparse/fs/partitions/check.c -3f05a939ZSKN7gX2sfTLzPcYJvPkcQ xenolinux-2.4.22-sparse/fs/partitions/xeno.c -3f05a939_I9vPADPgyVBwUDUxtoeOQ xenolinux-2.4.22-sparse/fs/partitions/xeno.h 3e5a4e66wbeCpsJgVf_U8Jde-CNcsA xenolinux-2.4.22-sparse/include/asm-xeno/bugs.h 3e5a4e66HdSkvIV6SJ1evG_xmTmXHA xenolinux-2.4.22-sparse/include/asm-xeno/desc.h 3e5a4e66SYp_UpAVcF8Lc1wa3Qtgzw xenolinux-2.4.22-sparse/include/asm-xeno/fixmap.h diff --git a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore index 25b9a3bed3..d04d658996 100644 --- a/BitKeeper/etc/ignore +++ b/BitKeeper/etc/ignore @@ -480,3 +480,4 @@ tools/misc/xen_log tools/misc/xen_refresh_dev xenolinux-2.4.22-sparse/arch/xeno/drivers/block/device xen/common/debug.c~ +xen/common/debug.o diff --git a/tools/internal/Makefile b/tools/internal/Makefile index 3fb527fd07..c8b8dcffaf 100644 --- a/tools/internal/Makefile +++ b/tools/internal/Makefile @@ -8,7 +8,7 @@ SRCS = $(wildcard *.c) OBJS = $(patsubst %.c,%.o,$(SRCS)) TARGETS = xi_create xi_start xi_stop xi_destroy xi_build -TARGETS += xi_phys_grant xi_phys_revoke xi_phys_probe xi_list +TARGETS += xi_phys_grant xi_list TARGETS += xi_sched_global xi_sched_domain xi_usage xi_vif_params INSTALL = $(TARGETS) xi_vifinit xi_helper diff --git a/tools/internal/dom0_defs.h b/tools/internal/dom0_defs.h index 13162534d2..40181db15a 100644 --- a/tools/internal/dom0_defs.h +++ b/tools/internal/dom0_defs.h @@ -58,18 +58,6 @@ static inline int do_privcmd(unsigned int cmd, unsigned long data) return ret; } -static inline int xldev_to_physdev(int xldev) -{ - return do_privcmd(IOCTL_PRIVCMD_LINDEV_TO_XENDEV, - (unsigned long)xldev); -} - -static inline int physdev_to_xldev(int physdev) -{ - return do_privcmd(IOCTL_PRIVCMD_XENDEV_TO_LINDEV, - (unsigned long)physdev); -} - static inline int do_xen_blkmsg(privcmd_blkmsg_t *blkmsg) { return do_privcmd(IOCTL_PRIVCMD_BLKMSG, (unsigned long)blkmsg); @@ -133,4 +121,28 @@ static inline int do_network_op(network_op_t *op) out1: return ret; } + +static inline int do_block_io_op(block_io_op_t *op) +{ + int ret = -1; + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_block_io_op; + hypercall.arg[0] = (unsigned long)op; + + if ( mlock(op, sizeof(*op)) != 0 ) + { + PERROR("Could not lock memory for Xen hypercall"); + goto out1; + } + + if ( do_xen_hypercall(&hypercall) < 0 ) + goto out2; + + ret = 0; + + out2: (void)munlock(op, sizeof(*op)); + out1: return ret; +} + #endif /* __DOM0_DEFS_H__ */ diff --git a/tools/internal/xi_phys_grant.c b/tools/internal/xi_phys_grant.c index 05630e2429..9267c5f85d 100644 --- a/tools/internal/xi_phys_grant.c +++ b/tools/internal/xi_phys_grant.c @@ -2,42 +2,67 @@ #define _GNU_SOURCE #include "dom0_defs.h" + int main(int argc, char *argv[]) { - privcmd_blkmsg_t blkmsg; - xp_disk_t xpd; + block_io_op_t op; + unsigned int domain; + unsigned short vdevice, device; + int ret; if ( argc != 7 ) { - fprintf(stderr, "Usage: xi_physdev_grant <r/rw> <domain> " + fprintf(stderr, "Usage: xi_physdev_grant_new <r/rw> <domain> " "<device> <start sector> <n_sectors> <partition>\n"); return 1; } - xpd.mode = 0; - if ( strchr(argv[1], 'r') ) - xpd.mode |= PHYSDISK_MODE_R; - if ( strchr(argv[1], 'w') ) - xpd.mode |= PHYSDISK_MODE_W; - xpd.domain = atol(argv[2]); - xpd.device = xldev_to_physdev(atol(argv[3])); - xpd.start_sect = atol(argv[4]); - xpd.n_sectors = atol(argv[5]); - xpd.partition = atol(argv[6]); + /* + ** XXX SMH: guests can refer to 'real' devices as anything; however + ** for this particular use ("physdisk access") we want to use the + ** same device number in the guest as is used in xen => both 'vdevice' + ** (XL name) and "device" (Xen name) are the same. + */ + domain = atoi(argv[2]); + device = atoi(argv[3]); + /* XXX SMH: hack -- generate device name by addition ptn number */ + vdevice = device + atoi(argv[6]); + + op.cmd = BLOCK_IO_OP_VBD_CREATE; + op.u.create_info.domain = domain; + op.u.create_info.vdevice = vdevice; - if ( xpd.device == 0 ) - { - ERROR("Unrecognised device"); - return 1; + ret = do_block_io_op(&op); + + if(ret < 0) { + fprintf(stderr, "error %d attempting to create VBD %04x\n", ret, + atoi(argv[2])); + return ret; } - blkmsg.op = XEN_BLOCK_PHYSDEV_GRANT; - blkmsg.buf = &xpd; - blkmsg.buf_size = sizeof(xpd); - if ( do_xen_blkmsg(&blkmsg) < 0 ) - return 1; + op.cmd = BLOCK_IO_OP_VBD_ADD; + op.u.add_info.domain = domain; + op.u.add_info.vdevice = vdevice; + + op.u.add_info.extent.device = device; + op.u.add_info.extent.start_sector = atol(argv[4]); + op.u.add_info.extent.nr_sectors = atol(argv[5]); + op.u.add_info.extent.mode = 0; + if ( strchr(argv[1], 'r') ) + op.u.add_info.extent.mode |= PHYSDISK_MODE_R; + if ( strchr(argv[1], 'w') ) + op.u.add_info.extent.mode |= PHYSDISK_MODE_W; + + + ret = do_block_io_op(&op); + + if(ret < 0) { + fprintf(stderr, "error %d attempting to add extent to VBD %04x\n", + ret, atoi(argv[2])); + return ret; + } return 0; } diff --git a/tools/internal/xi_phys_probe.c b/tools/internal/xi_phys_probe.c deleted file mode 100644 index a933e11276..0000000000 --- a/tools/internal/xi_phys_probe.c +++ /dev/null @@ -1,46 +0,0 @@ - -#define _GNU_SOURCE -#include "dom0_defs.h" - -int main(int argc, char *argv[]) -{ - privcmd_blkmsg_t blkmsg; - physdisk_probebuf_t buf; - int i; - - if ( argc != 2 ) - { - fprintf(stderr, "Usage: xi_phys_probe <domain_nr>\n"); - return 1; - } - - memset(&buf, 0, sizeof(buf)); - - do { - buf.domain = atol(argv[1]); - buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST; - - blkmsg.op = XEN_BLOCK_PHYSDEV_PROBE; - blkmsg.buf = &buf; - blkmsg.buf_size = sizeof(buf); - - if ( do_xen_blkmsg(&blkmsg) < 0 ) - return 1; - - for ( i = 0; i < buf.n_aces; i++ ) - { - char read = (buf.entries[i].mode & 1 ? 'r' : ' '); - char write = (buf.entries[i].mode & 2 ? 'w' : ' '); - printf("%x %x %lx %lx %c%c\n", - physdev_to_xldev(buf.entries[i].device), - buf.entries[i].partition, - buf.entries[i].start_sect, - buf.entries[i].n_sectors, read, write); - } - - buf.start_ind += buf.n_aces; - } - while ( buf.n_aces == PHYSDISK_MAX_ACES_PER_REQUEST ); - - return 0; -} diff --git a/tools/internal/xi_phys_revoke.c b/tools/internal/xi_phys_revoke.c deleted file mode 100644 index b018b03a24..0000000000 --- a/tools/internal/xi_phys_revoke.c +++ /dev/null @@ -1,37 +0,0 @@ - -#define _GNU_SOURCE -#include "dom0_defs.h" - -int main(int argc, char *argv[]) -{ - privcmd_blkmsg_t blkmsg; - xp_disk_t xpd; - - if ( argc != 5 ) - { - fprintf(stderr, "Usage: xi_physdev_revoke <domain> " - "<device> <start sector> <n_sectors>\n"); - return 1; - } - - xpd.mode = 0; - xpd.domain = atol(argv[1]); - xpd.device = xldev_to_physdev(atol(argv[2])); - xpd.start_sect = atol(argv[3]); - xpd.n_sectors = atol(argv[4]); - - if ( xpd.device == 0 ) - { - ERROR("Unrecognised device"); - return 1; - } - - blkmsg.op = XEN_BLOCK_PHYSDEV_GRANT; - blkmsg.buf = &xpd; - blkmsg.buf_size = sizeof(xpd); - - if ( do_xen_blkmsg(&blkmsg) < 0 ) - return 1; - - return 0; -} diff --git a/tools/misc/Makefile b/tools/misc/Makefile index ede01c7f8a..988440836d 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -9,7 +9,7 @@ OBJS = $(patsubst %.c,%.o,$(SRCS)) TARGETS = xen_read_console xen_log xen_cpuperf xen_refresh_dev -INSTALL = $(TARGETS) xen-mkdevnodes xen-clone xen_log +INSTALL = $(TARGETS) xen-mkdevnodes xen-clone all: $(TARGETS) $(MAKE) -C miniterm diff --git a/xen/common/domain.c b/xen/common/domain.c index b8b015f8c4..9fb90ff6f8 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -132,8 +132,10 @@ void __kill_domain(struct task_struct *p) unlink_blkdev_info(p); +#if 0 for ( i = 0; i < XEN_MAX_VBDS; i++ ) xen_vbd_delete(p, i); +#endif for ( i = 0; i < MAX_DOMAIN_VIFS; i++ ) unlink_net_vif(p->net_vif_list[i]); @@ -305,8 +307,10 @@ void release_task(struct task_struct *p) */ destroy_blkdev_info(p); +#if 0 /* Free up the physdisk access control info */ destroy_physdisk_aces(p); +#endif /* Free all memory associated with this domain. */ free_page((unsigned long)p->mm.perdomain_pt); diff --git a/xen/drivers/block/xen_block.c b/xen/drivers/block/xen_block.c index c96c7f5326..f989f2ed06 100644 --- a/xen/drivers/block/xen_block.c +++ b/xen/drivers/block/xen_block.c @@ -20,7 +20,7 @@ #include <xeno/vbd.h> #include <xeno/slab.h> -#if 0 +#if 1 #define DPRINTK(_f, _a...) printk( _f , ## _a ) #else #define DPRINTK(_f, _a...) ((void)0) @@ -58,33 +58,6 @@ static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED; static kmem_cache_t *buffer_head_cachep; static atomic_t nr_pending; -#define NR_IDE_DEVS 20 -#define NR_SCSI_DEVS 16 - -static kdev_t ide_devs[NR_IDE_DEVS] = { - MKDEV(IDE0_MAJOR, 0), MKDEV(IDE0_MAJOR, 64), /* hda, hdb */ - MKDEV(IDE1_MAJOR, 0), MKDEV(IDE1_MAJOR, 64), /* hdc, hdd */ - MKDEV(IDE2_MAJOR, 0), MKDEV(IDE2_MAJOR, 64), /* hde, hdf */ - MKDEV(IDE3_MAJOR, 0), MKDEV(IDE3_MAJOR, 64), /* hdg, hdh */ - MKDEV(IDE4_MAJOR, 0), MKDEV(IDE4_MAJOR, 64), /* hdi, hdj */ - MKDEV(IDE5_MAJOR, 0), MKDEV(IDE5_MAJOR, 64), /* hdk, hdl */ - MKDEV(IDE6_MAJOR, 0), MKDEV(IDE6_MAJOR, 64), /* hdm, hdn */ - MKDEV(IDE7_MAJOR, 0), MKDEV(IDE7_MAJOR, 64), /* hdo, hdp */ - MKDEV(IDE8_MAJOR, 0), MKDEV(IDE8_MAJOR, 64), /* hdq, hdr */ - MKDEV(IDE9_MAJOR, 0), MKDEV(IDE9_MAJOR, 64) /* hds, hdt */ -}; - -static kdev_t scsi_devs[NR_SCSI_DEVS] = { - MKDEV(SCSI_DISK0_MAJOR, 0), MKDEV(SCSI_DISK0_MAJOR, 16), /* sda, sdb */ - MKDEV(SCSI_DISK0_MAJOR, 32), MKDEV(SCSI_DISK0_MAJOR, 48), /* sdc, sdd */ - MKDEV(SCSI_DISK0_MAJOR, 64), MKDEV(SCSI_DISK0_MAJOR, 80), /* sde, sdf */ - MKDEV(SCSI_DISK0_MAJOR, 96), MKDEV(SCSI_DISK0_MAJOR, 112), /* sdg, sdh */ - MKDEV(SCSI_DISK0_MAJOR, 128), MKDEV(SCSI_DISK0_MAJOR, 144), /* sdi, sdj */ - MKDEV(SCSI_DISK0_MAJOR, 160), MKDEV(SCSI_DISK0_MAJOR, 176), /* sdk, sdl */ - MKDEV(SCSI_DISK0_MAJOR, 192), MKDEV(SCSI_DISK0_MAJOR, 208), /* sdm, sdn */ - MKDEV(SCSI_DISK0_MAJOR, 224), MKDEV(SCSI_DISK0_MAJOR, 240), /* sdo, sdp */ -}; - static int __buffer_is_valid(struct task_struct *p, unsigned long buffer, unsigned short size, @@ -102,10 +75,6 @@ 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(struct task_struct *p, int index); static void dispatch_debug_block_io(struct task_struct *p, int index); -static void dispatch_create_vbd(struct task_struct *p, int index); -static void dispatch_delete_vbd(struct task_struct *p, int index); -static void dispatch_grant_physdev(struct task_struct *p, int index); -static void dispatch_probe_physdev(struct task_struct *p, int index); static void make_response(struct task_struct *p, unsigned long id, unsigned short op, unsigned long st); @@ -232,14 +201,6 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate) kmem_cache_free(buffer_head_cachep, bh); } - - -long vbd_attach(vbd_attach_t *info) -{ - printk("vbd_attach called!!!\n"); - return -ENOSYS; -} - /* ----[ Syscall Interface ]------------------------------------------------*/ long do_block_io_op(block_io_op_t *u_block_io_op) @@ -259,13 +220,6 @@ long do_block_io_op(block_io_op_t *u_block_io_op) maybe_trigger_io_schedule(); break; - case BLOCK_IO_OP_ATTACH_VBD: - /* attach a VBD to a given domain; caller must be privileged */ - if( !IS_PRIV(p) ) - return -EPERM; - ret = vbd_attach(&op.u.attach_info); - break; - case BLOCK_IO_OP_RESET: /* Avoid a race with the tasklet. */ remove_from_blkdev_list(p); @@ -281,6 +235,34 @@ long do_block_io_op(block_io_op_t *u_block_io_op) } break; + case BLOCK_IO_OP_VBD_CREATE: + /* create a new VBD for a given domain; caller must be privileged */ + if(!IS_PRIV(p)) + return -EPERM; + ret = vbd_create(&op.u.create_info); + break; + + case BLOCK_IO_OP_VBD_ADD: + /* add an extent to a VBD; caller must be privileged */ + if(!IS_PRIV(p)) + return -EPERM; + ret = vbd_add(&op.u.add_info); + break; + + case BLOCK_IO_OP_VBD_REMOVE: + /* remove an extnet from a VBD; caller must be privileged */ + if(!IS_PRIV(p)) + return -EPERM; + ret = vbd_remove(&op.u.remove_info); + break; + + case BLOCK_IO_OP_VBD_DELETE: + /* delete a VBD; caller must be privileged */ + if(!IS_PRIV(p)) + return -EPERM; + ret = vbd_delete(&op.u.delete_info); + break; + default: ret = -ENOSYS; } @@ -424,22 +406,6 @@ 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_VBD_CREATE: - dispatch_create_vbd(p, i); - break; - - case XEN_BLOCK_VBD_DELETE: - dispatch_delete_vbd(p, i); - break; - - case XEN_BLOCK_PHYSDEV_GRANT: - dispatch_grant_physdev(p, i); - break; - - case XEN_BLOCK_PHYSDEV_PROBE: - dispatch_probe_physdev(p, i); - break; - default: DPRINTK("error: unknown block io operation [%d]\n", blk_ring->ring[i].req.operation); @@ -458,113 +424,6 @@ static void dispatch_debug_block_io(struct task_struct *p, int index) DPRINTK("dispatch_debug_block_io: unimplemented\n"); } -static void dispatch_probe_physdev(struct task_struct *p, int index) -{ - blk_ring_t *blk_ring = p->blk_ring_base; - unsigned long flags, buffer; - physdisk_probebuf_t *buf; - int result; - - buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF; - - spin_lock_irqsave(&p->page_lock, flags); - if ( !__buffer_is_valid(p, buffer, sizeof(*buf), 1) ) - { - spin_unlock_irqrestore(&p->page_lock, flags); - result = 1; - goto out; - } - __lock_buffer(buffer, sizeof(*buf), 1); - spin_unlock_irqrestore(&p->page_lock, flags); - - buf = phys_to_virt(buffer); - result = xen_physdisk_probe(p, buf); - - unlock_buffer(p, buffer, sizeof(*buf), 1); - - out: - make_response(p, blk_ring->ring[index].req.id, - XEN_BLOCK_PHYSDEV_PROBE, result); -} - -static void dispatch_grant_physdev(struct task_struct *p, int index) -{ - blk_ring_t *blk_ring = p->blk_ring_base; - unsigned long flags, buffer; - xp_disk_t *xpd; - int result; - - if ( p->domain != 0 ) - { - DPRINTK("dispatch_grant_physdev called by dom%d\n", p->domain); - result = 1; - goto out; - } - - buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF; - - spin_lock_irqsave(&p->page_lock, flags); - if ( !__buffer_is_valid(p, buffer, sizeof(xv_disk_t), 1) ) - { - DPRINTK("Bad buffer in dispatch_grant_physdev\n"); - spin_unlock_irqrestore(&p->page_lock, flags); - result = 1; - goto out; - } - __lock_buffer(buffer, sizeof(xv_disk_t), 1); - spin_unlock_irqrestore(&p->page_lock, flags); - - xpd = phys_to_virt(buffer); - result = xen_physdisk_grant(xpd); - - unlock_buffer(p, buffer, sizeof(xp_disk_t), 1); - - out: - make_response(p, blk_ring->ring[index].req.id, - XEN_BLOCK_PHYSDEV_GRANT, result); -} - -static void dispatch_create_vbd(struct task_struct *p, int index) -{ - blk_ring_t *blk_ring = p->blk_ring_base; - unsigned long flags, buffer; - xv_disk_t *xvd; - int result; - - if ( p->domain != 0 ) - { - DPRINTK("dispatch_create_vbd called by dom%d\n", p->domain); - result = 1; - goto out; - } - - buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF; - - spin_lock_irqsave(&p->page_lock, flags); - if ( !__buffer_is_valid(p, buffer, sizeof(xv_disk_t), 1) ) - { - DPRINTK("Bad buffer in dispatch_create_vbd\n"); - spin_unlock_irqrestore(&p->page_lock, flags); - result = 1; - goto out; - } - __lock_buffer(buffer, sizeof(xv_disk_t), 1); - spin_unlock_irqrestore(&p->page_lock, flags); - - xvd = phys_to_virt(buffer); - result = xen_vbd_create(xvd); - - unlock_buffer(p, buffer, sizeof(xv_disk_t), 1); - - out: - make_response(p, blk_ring->ring[index].req.id, - XEN_BLOCK_VBD_CREATE, result); -} - -static void dispatch_delete_vbd(struct task_struct *p, int index) -{ - DPRINTK("dispatch_delete_vbd: unimplemented\n"); -} static void dispatch_probe(struct task_struct *p, int index) { @@ -599,15 +458,12 @@ static void dispatch_probe(struct task_struct *p, int index) */ xdi = map_domain_mem(buffer); xdi->count = 0; -#if 0 // XXX SMH: fix below once done proper vbd/physd rewrit + if(IS_PRIV(p)) { -#endif - /* privilege domains always gets access to the 'real' devices */ + /* privileged domains always get access to the 'real' devices */ ide_probe_devices(xdi); scsi_probe_devices(xdi); -#if 0 } -#endif vbd_probe_devices(xdi, p); unmap_domain_mem(xdi); @@ -626,7 +482,7 @@ static void dispatch_rw_block_io(struct task_struct *p, int index) int operation = (req->operation == XEN_BLOCK_WRITE) ? WRITE : READ; unsigned short nr_sects; unsigned long buffer, flags; - int i, tot_sects; + int i, rc, tot_sects; pending_req_t *pending_req; /* We map virtual scatter/gather segments to physical segments. */ @@ -665,41 +521,25 @@ static void dispatch_rw_block_io(struct task_struct *p, int index) goto bad_descriptor; } - /* Get the physical device and block index. */ - if ( (req->device & XENDEV_TYPE_MASK) == XENDEV_VIRTUAL ) - { - new_segs = xen_vbd_map_request( - &phys_seg[nr_psegs], p, operation, - req->device, - req->sector_number + tot_sects, - buffer, nr_sects); - if ( new_segs <= 0 ) - { - DPRINTK("bogus xen_vbd_map_request\n"); - goto bad_descriptor; - } - } - else - { - phys_seg[nr_psegs].dev = req->device; - phys_seg[nr_psegs].sector_number = req->sector_number + tot_sects; - phys_seg[nr_psegs].buffer = buffer; - phys_seg[nr_psegs].nr_sects = nr_sects; - if (p->domain != 0 && - !xen_physdisk_access_okay(&phys_seg[nr_psegs], p, operation)) { - DPRINTK("access denied: dev=%04x off=%ld nr=%ld\n", - req->device, req->sector_number + tot_sects, nr_sects); - goto bad_descriptor; - } - phys_seg[nr_psegs].dev = xendev_to_physdev(req->device); - if ( phys_seg[nr_psegs].dev == 0 ) - { - DPRINTK("bad device: %04x\n", req->device); - goto bad_descriptor; - } - new_segs = 1; - } - + phys_seg[nr_psegs].dev = req->device; + phys_seg[nr_psegs].sector_number = req->sector_number + tot_sects; + phys_seg[nr_psegs].buffer = buffer; + phys_seg[nr_psegs].nr_sects = nr_sects; + + /* Translate the request into the relevant 'physical device' */ + new_segs = 1; + rc = vbd_translate(&phys_seg[nr_psegs], &new_segs, p, operation); + + /* If it fails we bail (unless the caller is priv => has raw access) */ + if(rc && !IS_PRIV(p)) { + printk("access denied: attempted %s of [%ld,%ld] on dev=%04x\n", + operation == READ ? "read" : "write", + req->sector_number + tot_sects, + req->sector_number + tot_sects + nr_sects, + req->device); + goto bad_descriptor; + } + nr_psegs += new_segs; if ( nr_psegs >= (MAX_BLK_SEGS*2) ) BUG(); } @@ -762,36 +602,6 @@ static void dispatch_rw_block_io(struct task_struct *p, int index) * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING */ -kdev_t xendev_to_physdev(unsigned short xendev) -{ - switch ( (xendev & XENDEV_TYPE_MASK) ) - { - case XENDEV_IDE: - xendev &= XENDEV_IDX_MASK; - if ( xendev >= NR_IDE_DEVS ) - { - DPRINTK("IDE device number out of range %d\n", xendev); - goto fail; - } - return ide_devs[xendev]; - - case XENDEV_SCSI: - xendev &= XENDEV_IDX_MASK; - if ( xendev >= NR_SCSI_DEVS ) - { - DPRINTK("SCSI device number out of range %d\n", xendev); - goto fail; - } - return scsi_devs[xendev]; - - case XENDEV_VIRTUAL: - default: - DPRINTK("xendev_to_physdev: unknown device %d\n", xendev); - } - - fail: - return (kdev_t)0; -} static void make_response(struct task_struct *p, unsigned long id, unsigned short op, unsigned long st) @@ -848,11 +658,6 @@ 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; - - memset(p->vbd_list, 0, sizeof(p->vbd_list)); - - /* Get any previously created segments. */ - xen_refresh_vbd_list(p); } /* End-of-day teardown for a domain. */ @@ -893,7 +698,5 @@ void initialize_block_io () "buffer_head_cache", sizeof(struct buffer_head), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - xen_vbd_initialize(); - add_key_handler('b', dump_blockq, "dump xen ide blkdev statistics"); } diff --git a/xen/drivers/block/xen_vbd.c b/xen/drivers/block/xen_vbd.c index 1fdf03154e..dae8e9343a 100644 --- a/xen/drivers/block/xen_vbd.c +++ b/xen/drivers/block/xen_vbd.c @@ -14,21 +14,6 @@ #include <asm/current.h> #include <asm/domain_page.h> -/* Global list of all possible vbds. This can be changed in - the following way: - - 1) UNUSED vbd -> RO or RW vbd. This requires the spinlock. - - 2) RO or RW -> UNUSED. This requires the lock and can only happen - during process teardown. - - This means that processes can access entries in the list safely - without having to hold any lock at all: they already have an entry - allocated, and we know that entry can't become unused, as vbds - are only torn down when the domain is dieing, by which point it - can't be accessing them anymore. */ -static vbd_t xvbds[XEN_MAX_VBDS]; -static spinlock_t xvbd_lock = SPIN_LOCK_UNLOCKED; #if 0 #define DPRINTK(_f, _a...) printk( _f , ## _a ) @@ -36,631 +21,186 @@ static spinlock_t xvbd_lock = SPIN_LOCK_UNLOCKED; #define DPRINTK(_f, _a...) ((void)0) #endif -/* - * xen_vbd_map_request - * - * xen_device must be a valid device. - * - * NB. All offsets and sizes here are in sector units. - * eg. 'size == 1' means an actual size of 512 bytes. - * - * Note that no locking is performed here whatsoever -- - * we rely on the fact that once vbd information is - * established, it is only modified by domain shutdown, - * and so if this is being called, noone is trying - * to modify the vbd list. - */ -int xen_vbd_map_request( - phys_seg_t *pseg, struct task_struct *p, int operation, - unsigned short vbd_number, - unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects) -{ - vbd_t *seg; - extent_t *ext; - int sum, i; - - vbd_number &= XENDEV_IDX_MASK; - if ( vbd_number >= XEN_MAX_VBDS ) - { - DPRINTK("invalid vbd number. %d %d\n", - vbd_number, XEN_MAX_VBDS); - goto fail; - } - - seg = p->vbd_list[vbd_number]; - if ( seg == NULL ) - { - DPRINTK("vbd is null. %d\n", vbd_number); - goto fail; - } - /* check domain permissions */ - if ( seg->domain != p->domain ) - { - DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain); - goto fail; - } +/* XXX SMH: crappy 'hash function' .. fix when care. */ +#define HSH(_x) (((_x) >> 6) & (VBD_HTAB_SZ - 1)) - /* check rw access */ - if ( ((operation == WRITE) && (seg->mode != XEN_VBD_RW)) || - ((operation == READ) && (seg->mode == XEN_VBD_UNUSED)) ) - { - DPRINTK("illegal operation: %d %d\n", operation, seg->mode); - goto fail; - } +/* +** Create a new VBD; all this involves is adding an entry to the domain's +** vbd hash table. +*/ +long vbd_create(vbd_create_t *create_info) +{ + struct task_struct *p; + vbd_t *new_vbd, *v; + int h; - if ( (nr_sects + sect_nr) <= sect_nr ) - { - DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects); - goto fail; - } + p = find_domain_by_id(create_info->domain); - /* find extent, check size */ - sum = 0; - i = 0; - ext = seg->extents; - while ( (i < seg->num_extents) && ((sum + ext->nr_sectors) <= sect_nr) ) - { - sum += ext->nr_sectors; - ext++; i++; + if (!p) { + printk("vbd_create attempted for non-existent domain %d\n", + create_info->domain); + return -EINVAL; } - if ( (sum + ext->nr_sectors) <= sect_nr ) - { - DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n", - i, seg->num_extents, sum, ext->nr_sectors, sect_nr); - goto fail; - } + new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL); + new_vbd->vdevice = create_info->vdevice; + new_vbd->extents = (xen_extent_le_t *)NULL; + new_vbd->next = (vbd_t *)NULL; - pseg->sector_number = (sect_nr - sum) + ext->start_sector; - pseg->buffer = buffer; - pseg->nr_sects = nr_sects; - pseg->dev = xendev_to_physdev(ext->raw_device); - if ( pseg->dev == 0 ) - { - DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n", - ext->raw_device, ext->start_sector, ext->nr_sectors); - goto fail; - } + h = HSH(create_info->vdevice); + if(p->vbdtab[h]) { + for(v = p->vbdtab[h]; v->next; v = v->next) + ; + v->next = new_vbd; + } else p->vbdtab[h] = new_vbd; - /* We're finished if the virtual extent didn't overrun the phys extent. */ - if ( (sum + ext->nr_sectors) >= (sect_nr + nr_sects) ) - return 1; /* entire read fits in this extent */ + put_task_struct(p); + + return 0; +} - /* Hmmm... make sure there's another extent to overrun onto! */ - if ( (i+1) == seg->num_extents ) - { - DPRINTK ("not enough extents %d %d\n", - i, seg->num_extents); - goto fail; - } +/* +** Add an extent to an existing VBD; fails if the VBD doesn't exist. +** Doesn't worry about overlapping extents (e.g. merging etc) for now. +*/ +long vbd_add(vbd_add_t *add_info) +{ + struct task_struct *p; + xen_extent_le_t *x, *xele; + vbd_t *v; + int h; - pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->nr_sectors); - pseg[0].nr_sects = sum + ext->nr_sectors - sect_nr; - pseg[1].buffer = buffer + (pseg->nr_sects << 9); - pseg[1].sector_number = ext[1].start_sector; - pseg[1].dev = xendev_to_physdev(ext[1].raw_device); - if ( pseg[1].dev == 0 ) - { - DPRINTK ("bogus device for pseg[1] \n"); - goto fail; - } + p = find_domain_by_id(add_info->domain); - /* We don't allow overrun onto a third physical extent. */ - if ( pseg[1].nr_sects > ext[1].nr_sectors ) - { - DPRINTK ("third extent\n"); - DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n", - sum, ext[0].nr_sectors, ext[1].nr_sectors, - pseg[1].sector_number, pseg[1].nr_sects); - goto fail; + if (!p) { + printk("vbd_add attempted for non-existent domain %d\n", + add_info->domain); + return -EINVAL; } - return 2; /* We overran onto a second physical extent. */ + h = HSH(add_info->vdevice); - fail: - DPRINTK ("xen_vbd_map_request failure\n"); - DPRINTK ("operation: %d\n", operation); - DPRINTK ("vbd number: %d\n", vbd_number); - DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr); - DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects); - return -1; -} + for(v = p->vbdtab[h]; v; v = v->next) + if(v->vdevice == add_info->vdevice) + break; -/* - * vbd_probe_devices: - * - * add the virtual block devices for this domain to a xen_disk_info_t; - * we assume xdi->count points to the first unused place in the array. - */ -void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p) -{ - int loop, i; - unsigned long capacity = 0, device; - - spin_lock(&xvbd_lock); - for (loop = 0; loop < XEN_MAX_VBDS; loop++ ) - { - if ( (xvbds[loop].mode == XEN_VBD_UNUSED) || - (xvbds[loop].domain != p->domain) ) - continue; - - device = MK_VIRTUAL_XENDEV(xvbds[loop].vbd_number); - for ( i = 0; i < xvbds[loop].num_extents; i++ ) - capacity += xvbds[loop].extents[i].nr_sectors; - - xdi->disks[xdi->count].device = device; - xdi->disks[xdi->count].capacity = capacity; - xdi->count++; + if(!v) { + printk("vbd_add; attempted to add extent to non-existent VBD.\n"); + return -EINVAL; } - spin_unlock(&xvbd_lock); - return; -} -/* - * xen_refresh_vbd_list - * - * find all vbds associated with a domain and assign - * them to the domain - * - */ -void xen_refresh_vbd_list (struct task_struct *p) -{ - int loop; + xele = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL); + xele->extent.device = add_info->extent.device; + xele->extent.start_sector = add_info->extent.start_sector; + xele->extent.nr_sectors = add_info->extent.nr_sectors; + xele->extent.mode = add_info->extent.mode; + xele->next = (xen_extent_le_t *)NULL; - spin_lock(&xvbd_lock); - for (loop = 0; loop < XEN_MAX_VBDS; loop++) - { - if ( (xvbds[loop].mode == XEN_VBD_UNUSED) || - (xvbds[loop].domain != p->domain) ) - continue; + if(!v->extents) { + v->extents = xele; + } else { + for(x = v->extents; x->next; x = x->next) + ; + x->next = xele; + } - p->vbd_list[xvbds[loop].vbd_number] = &xvbds[loop]; - } - spin_unlock(&xvbd_lock); + put_task_struct(p); + return 0; } -/* - * create a new vbd for a domain - * - * return 0 on success, 1 on failure - * - * if we see the same DOM#/SEG# combination, we reuse the slot in - * the vbd table (overwriting what was there before). - * an alternative would be to raise an error if the slot is reused. - */ -int xen_vbd_create(xv_disk_t *xvd_in) +long vbd_remove(vbd_remove_t *remove_info) { - int idx; - int loop; - xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in)); - struct task_struct *p; - - spin_lock(&xvbd_lock); - for (idx = 0; idx < XEN_MAX_VBDS; idx++) - { - if (xvbds[idx].mode == XEN_VBD_UNUSED || - (xvbds[idx].domain == xvd->domain && - xvbds[idx].vbd_number == xvd->vbd)) break; - } - if (idx == XEN_MAX_VBDS) - { - printk (KERN_ALERT "xen_vbd_create: unable to find free slot\n"); - unmap_domain_mem(xvd); - return 1; - } - - xvbds[idx].mode = xvd->mode; - xvbds[idx].domain = xvd->domain; - xvbds[idx].vbd_number = xvd->vbd; - memcpy(xvbds[idx].key, xvd->key, XEN_VBD_KEYSIZE); - xvbds[idx].num_extents = xvd->ext_count; - - - if (xvbds[idx].extents) - kfree(xvbds[idx].extents); - xvbds[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++) - { - xvbds[idx].extents[loop].raw_device = xvd->extents[loop].disk; - xvbds[idx].extents[loop].start_sector = - xvd->extents[loop].offset; - xvbds[idx].extents[loop].nr_sectors = xvd->extents[loop].size; - if (xvbds[idx].extents[loop].nr_sectors == 0) - { - printk("xen_vbd_create: extent %d is zero length\n", loop); - unmap_domain_mem(xvd); - return 1; - } - } - - /* if the domain exists, assign the vbd to the domain */ - p = find_domain_by_id(xvd->domain); - if (p != NULL) - { - p->vbd_list[xvd->vbd] = &xvbds[idx]; - put_task_struct(p); - } - - spin_unlock(&xvbd_lock); - - unmap_domain_mem(xvd); - return 0; + return -ENOSYS; } -/* - * delete a vbd from a domain - * - * return 0 on success, 1 on failure - * - * This should *only* be called from domain shutdown, or else we - * race with access checking. - */ -int xen_vbd_delete(struct task_struct *p, int segnr) +long vbd_delete(vbd_delete_t *delete_info) { - vbd_t *seg; + return -ENOSYS; +} - if (!p) { - printk("xen_vbd delete called with NULL domain?\n"); - BUG(); - return 1; - } - if (segnr < 0 || segnr > XEN_MAX_VBDS) { - printk("xen_vbd_delete called with bad segnr?\n"); - BUG(); - return 1; - } +int vbd_translate(phys_seg_t * pseg, int *nr_segs, + struct task_struct *p, int operation) +{ + xen_extent_le_t *x; + vbd_t *v; + int h; + long sec; - if (!p->vbd_list[segnr]) - return 1; + h = HSH(pseg->dev); - seg = p->vbd_list[segnr]; + for(v = p->vbdtab[h]; v; v = v->next) + if(v->vdevice == pseg->dev) + break; - /* sanity checking */ - if (seg->domain != p->domain || seg->vbd_number != segnr || - (seg->mode != XEN_VBD_RO && seg->mode != XEN_VBD_RW) || - seg->num_extents <= 0 || seg->extents == NULL) { - printk("vbd is insane!\n"); - BUG(); - return 1; + if(!v) { + if(!IS_PRIV(p)) + printk("vbd_translate; domain %d attempted to access " + "non-existent VBD.\n", p->domain); + return -ENODEV; } - spin_lock(&xvbd_lock); - - p->vbd_list[segnr] = NULL; - seg->domain = -1; - seg->vbd_number = -1; - kfree(seg->extents); - seg->mode = XEN_VBD_UNUSED; - - spin_unlock(&xvbd_lock); - - return 0; -} + /* Now iterate through the list of xen_extents, working out which + should be used to perform the translation. */ + sec = pseg->sector_number; + for(x = v->extents; x; x = x->next) { -static void dump_vbds(u_char key, void *dev_id, struct pt_regs *regs) -{ - int loop, i; - struct task_struct *p; - - printk("vbd list\n"); - for (loop = 0; loop < XEN_MAX_VBDS; loop++) - { - if (xvbds[loop].mode != XEN_VBD_UNUSED) - { - printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n", - loop, - xvbds[loop].mode == XEN_VBD_RO ? "RO" : "RW", - xvbds[loop].domain, xvbds[loop].vbd_number, - xvbds[loop].num_extents); - for (i = 0; i < xvbds[loop].num_extents; i++) - { - printk(" extent %d: raw device 0x%x, start_sector 0x%lx" - " nr_sectors 0x%lx\n", - i, xvbds[loop].extents[i].raw_device, - xvbds[loop].extents[i].start_sector, - xvbds[loop].extents[i].nr_sectors); - } - } - } + if(sec < x->extent.nr_sectors) { - printk("vbds by domain (index into vbds list)\n"); - p = current; - do - { - if(is_idle_task(p)) - continue; - - printk(" domain %d: ", p->domain); - for (loop = 0; loop < XEN_MAX_VBDS; loop++) - { - if (p->vbd_list[loop]) - { - printk (" %d", p->vbd_list[loop] - xvbds); - } - } - printk("\n"); - p = p->next_task; - } while (p != current); -} - -/* - * initialize vbds - */ + /* we've got a match! XXX SMH: should deal with + situation where we span multiple xe's */ -void xen_vbd_initialize(void) -{ - memset (xvbds, 0, sizeof(xvbds)); + if(operation == READ && !(x->extent.mode & PHYSDISK_MODE_R)) + return -EACCES; - add_key_handler('S', dump_vbds, "dump vbds"); -} + if(operation == WRITE && !(x->extent.mode & PHYSDISK_MODE_W)) + return -EACCES; + pseg->dev = x->extent.device; + pseg->sector_number += x->extent.start_sector; -/* The idea is that, for each sector of each disk, each domain has two - bits, saying whether they can read the sector or write it. That - would take too much memory, so instead each process has a list of - (device, start, end, mode) quads which say what it has access to, - and we fake the logical view on top of that. */ -struct physdisk_ace { - struct list_head list; - unsigned short device; - unsigned short partition; - unsigned long start_sect; - unsigned long n_sectors; - int mode; -}; - - -/* Operation is a blkdev constant i.e. READ, WRITE, ... */ -/* Must be called with p->physdev_lock held. */ -static struct physdisk_ace *find_ace(const struct task_struct *p, - unsigned short dev, - unsigned long sect, int operation) -{ - struct list_head *cur_ace_head; - struct physdisk_ace *cur_ace; - - list_for_each(cur_ace_head, &p->physdisk_aces) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - DPRINTK("Is [%lx, %lx) good for %lx?\n", - cur_ace->start_sect, - cur_ace->start_sect + cur_ace->n_sectors, sect); - if ( (sect >= cur_ace->start_sect) && - (sect < (cur_ace->start_sect + cur_ace->n_sectors)) && - (dev == cur_ace->device) && - (((operation == READ) && (cur_ace->mode & PHYSDISK_MODE_R)) || - ((operation == WRITE) && (cur_ace->mode & PHYSDISK_MODE_W))) ) - return cur_ace; - } - return NULL; -} + return 0; -/* Hold the lock on entry, it remains held on exit. */ -static void xen_physdisk_revoke_access(unsigned short dev, - unsigned long start_sect, - unsigned long n_sectors, - struct task_struct *p) -{ - /* Find every ace which intersects [start_sect, start_sect + - n_sectors] and either remove it completely or truncate it - down. */ - struct list_head *cur_ace_head; - struct physdisk_ace *cur_ace, *new_ace; - unsigned long kill_zone_end, ace_end; - - kill_zone_end = start_sect + n_sectors; - list_for_each(cur_ace_head, &p->physdisk_aces) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - ace_end = cur_ace->start_sect + cur_ace->n_sectors; - if ( (cur_ace->start_sect >= kill_zone_end) || - (ace_end <= start_sect) || - (cur_ace->device != dev) ) - continue; - - DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n", - cur_ace->start_sect, ace_end, start_sect, kill_zone_end); - - if ( (cur_ace->start_sect >= start_sect) && - (ace_end <= kill_zone_end) ) - { - /* ace entirely within kill zone -> kill it */ - list_del(cur_ace_head); - cur_ace_head = cur_ace_head->prev; - kfree(cur_ace); - } - else if ( ace_end <= kill_zone_end ) - { - /* ace start before kill start, ace end in kill zone, - move ace end. */ - cur_ace->n_sectors = start_sect - cur_ace->start_sect; } - else if ( cur_ace->start_sect >= start_sect ) - { - /* ace start after kill start, ace end outside kill zone, - move ace start. */ - cur_ace->start_sect = kill_zone_end; - cur_ace->n_sectors = ace_end - cur_ace->start_sect; - } - else - { - /* The fun one: the ace entirely includes the kill zone. */ - /* Cut the current ace down to just the bit before the kzone, - create a new ace for the bit just after it. */ - new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL); - new_ace->device = dev; - new_ace->start_sect = kill_zone_end; - new_ace->n_sectors = ace_end - kill_zone_end; - new_ace->mode = cur_ace->mode; - - cur_ace->n_sectors = start_sect - cur_ace->start_sect; - - list_add(&new_ace->list, cur_ace_head); - } - } -} -/* Hold the lock on entry, it remains held on exit. */ -static int xen_physdisk_grant_access(unsigned short dev, - unsigned short partition, - unsigned long start_sect, - unsigned long n_sectors, - int mode, struct task_struct *p) -{ - struct physdisk_ace *cur_ace; - - /* Make sure it won't overlap with any existing ACEs. */ - /* XXX this isn't quite right if the domain already has read access - and we try to grant write access, or vice versa. */ - xen_physdisk_revoke_access(dev, start_sect, n_sectors, p); - - if ( mode ) - { - cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL); - cur_ace->device = dev; - cur_ace->start_sect = start_sect; - cur_ace->n_sectors = n_sectors; - cur_ace->mode = mode; - cur_ace->partition = partition; - - list_add_tail(&cur_ace->list, &p->physdisk_aces); + sec -= x->extent.nr_sectors; } - return 0; + /* No luck -- return no access */ + return -EACCES; } -static void xen_physdisk_probe_access(physdisk_probebuf_t * buf, - struct task_struct *p) -{ - int n_aces; - struct list_head *cur_ace_head; - struct physdisk_ace *cur_ace; - int x = 0; - - n_aces = 0; - list_for_each(cur_ace_head, &p->physdisk_aces) - { - x++; - if ( x >= buf->start_ind ) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - buf->entries[n_aces].device = cur_ace->device; - buf->entries[n_aces].partition = cur_ace->partition; - buf->entries[n_aces].start_sect = cur_ace->start_sect; - buf->entries[n_aces].n_sectors = cur_ace->n_sectors; - buf->entries[n_aces].mode = cur_ace->mode; - n_aces++; - } - } - buf->n_aces = n_aces; -} -int xen_physdisk_grant(xp_disk_t * xpd_in) +/* + * vbd_probe_devices: + * + * add the virtual block devices for this domain to a xen_disk_info_t; + * we assume xdi->count points to the first unused place in the array. + */ +void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p) { - struct task_struct *p = current; - xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in)); - int res; - - p = find_domain_by_id(xpd->domain); - if ( p == NULL ) - { - DPRINTK("Bad domain!\n"); - res = 1; - goto out; - } - - spin_lock(&p->physdev_lock); - res = xen_physdisk_grant_access(xpd->device, - xpd->partition, - xpd->start_sect, - xpd->n_sectors, xpd->mode, p); - spin_unlock(&p->physdev_lock); - put_task_struct(p); + xen_extent_le_t *x; + vbd_t *v; + int i; + + /* XXX SMH: should allow priv domains to probe vbds for other doms XXX */ + + for(i = 0; i < VBD_HTAB_SZ; i++) { + for(v = p->vbdtab[i]; v; v = v->next) { + xdi->disks[xdi->count].device = v->vdevice; + xdi->disks[xdi->count].type = XD_TYPE_DISK; // always :-) + xdi->disks[xdi->count].capacity = 0; + for(x = v->extents; x; x = x->next) + xdi->disks[xdi->count].capacity += x->extent.nr_sectors; + xdi->count++; + } + } - out: - unmap_domain_mem(xpd); - return res; + return; } -int xen_physdisk_probe(struct task_struct *requesting_domain, - physdisk_probebuf_t * buf_in) -{ - struct task_struct *p; - physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in)); - int res; - - if ( (requesting_domain->domain != 0) && - (requesting_domain->domain != buf->domain) ) - { - res = 1; - goto out; - } - p = find_domain_by_id(buf->domain); - if ( p == NULL ) - { - res = 1; - goto out; - } - spin_lock(&p->physdev_lock); - xen_physdisk_probe_access(buf, p); - spin_unlock(&p->physdev_lock); - put_task_struct(p); - res = 0; - out: - unmap_domain_mem(buf); - return res; -} - -#define MAX(a,b) ((a) > (b) ? (a) : (b)) - -int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p, - int operation) -{ - struct physdisk_ace *cur_ace; - unsigned long sect; - - DPRINTK - ("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n", - p->domain, pseg->sector_number, pseg->nr_sects); - - for ( sect = pseg->sector_number; - sect < pseg->sector_number + pseg->nr_sects; ) - { - /* XXX this would be a lot faster if the aces were sorted on start - address. Also in revoke_access. */ - spin_lock(&p->physdev_lock); - cur_ace = find_ace(p, pseg->dev, sect, operation); - spin_unlock(&p->physdev_lock); - if ( cur_ace == NULL ) - return 0; - sect += - MAX(cur_ace->n_sectors, - pseg->nr_sects + pseg->sector_number - sect); - } - return 1; -} - -void destroy_physdisk_aces(struct task_struct *p) -{ - struct list_head *cur_ace_head, *next_head; - struct physdisk_ace *cur_ace; - - for ( cur_ace_head = p->physdisk_aces.next; - cur_ace_head != &p->physdisk_aces; - cur_ace_head = next_head ) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - next_head = cur_ace_head->next; - kfree(cur_ace); - } -} diff --git a/xen/drivers/ide/ide-xeno.c b/xen/drivers/ide/ide-xeno.c index ff93e6182f..46213fc1c8 100644 --- a/xen/drivers/ide/ide-xeno.c +++ b/xen/drivers/ide/ide-xeno.c @@ -6,6 +6,24 @@ #include <asm/domain_page.h> #include <asm/io.h> +#define NR_IDE_DEVS 20 + +static kdev_t ide_devs[NR_IDE_DEVS] = { + MKDEV(IDE0_MAJOR, 0), MKDEV(IDE0_MAJOR, 64), /* hda, hdb */ + MKDEV(IDE1_MAJOR, 0), MKDEV(IDE1_MAJOR, 64), /* hdc, hdd */ + MKDEV(IDE2_MAJOR, 0), MKDEV(IDE2_MAJOR, 64), /* hde, hdf */ + MKDEV(IDE3_MAJOR, 0), MKDEV(IDE3_MAJOR, 64), /* hdg, hdh */ + MKDEV(IDE4_MAJOR, 0), MKDEV(IDE4_MAJOR, 64), /* hdi, hdj */ + MKDEV(IDE5_MAJOR, 0), MKDEV(IDE5_MAJOR, 64), /* hdk, hdl */ + MKDEV(IDE6_MAJOR, 0), MKDEV(IDE6_MAJOR, 64), /* hdm, hdn */ + MKDEV(IDE7_MAJOR, 0), MKDEV(IDE7_MAJOR, 64), /* hdo, hdp */ + MKDEV(IDE8_MAJOR, 0), MKDEV(IDE8_MAJOR, 64), /* hdq, hdr */ + MKDEV(IDE9_MAJOR, 0), MKDEV(IDE9_MAJOR, 64) /* hds, hdt */ +}; + + + + void ide_probe_devices(xen_disk_info_t* xdi) { int loop; @@ -30,8 +48,10 @@ void ide_probe_devices(xen_disk_info_t* xdi) ** as our 'type' field (XD_TYPE_DISK, XD_TYPE_CDROM, etc). ** Hence must ensure these are kept in sync. */ + + /* SMH: we export 'raw' linux device numbers to domain 0 */ + device = ide_devs[(loop * MAX_DRIVES) + unit]; type = drive->media; - device = MK_IDE_XENDEV((loop * MAX_DRIVES) + unit); capacity = current_capacity(drive); xdi->disks[xdi->count].device = device; diff --git a/xen/drivers/scsi/sd.c b/xen/drivers/scsi/sd.c index aa70bb3ca9..eeb1c5aff2 100644 --- a/xen/drivers/scsi/sd.c +++ b/xen/drivers/scsi/sd.c @@ -1321,17 +1321,34 @@ static void sd_finish() ** easiest place to hook it in :-( ** */ + +#define NR_SCSI_DEVS 16 + +static kdev_t scsi_devs[NR_SCSI_DEVS] = { + MKDEV(SCSI_DISK0_MAJOR, 0), MKDEV(SCSI_DISK0_MAJOR, 16), /* sda, sdb */ + MKDEV(SCSI_DISK0_MAJOR, 32), MKDEV(SCSI_DISK0_MAJOR, 48), /* sdc, sdd */ + MKDEV(SCSI_DISK0_MAJOR, 64), MKDEV(SCSI_DISK0_MAJOR, 80), /* sde, sdf */ + MKDEV(SCSI_DISK0_MAJOR, 96), MKDEV(SCSI_DISK0_MAJOR, 112), /* sdg, sdh */ + MKDEV(SCSI_DISK0_MAJOR, 128), MKDEV(SCSI_DISK0_MAJOR, 144), /* sdi, sdj */ + MKDEV(SCSI_DISK0_MAJOR, 160), MKDEV(SCSI_DISK0_MAJOR, 176), /* sdk, sdl */ + MKDEV(SCSI_DISK0_MAJOR, 192), MKDEV(SCSI_DISK0_MAJOR, 208), /* sdm, sdn */ + MKDEV(SCSI_DISK0_MAJOR, 224), MKDEV(SCSI_DISK0_MAJOR, 240), /* sdo, sdp */ +}; + + void scsi_probe_devices(xen_disk_info_t *xdi) { Scsi_Disk *sd; int i; - unsigned long capacity, device; + unsigned short device; + unsigned long capacity; for ( sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++ ) { if ( sd->device == NULL ) continue; - device = MK_SCSI_XENDEV(i); + /* SMH: we export 'raw' linux device numbers to domain 0 */ + device = scsi_devs[i]; capacity = sd->capacity; /* XXX SMH: if make generic, need to properly determine 'type' */ diff --git a/xen/include/hypervisor-ifs/block.h b/xen/include/hypervisor-ifs/block.h index 9f4a72cfc1..a5e05a647a 100644 --- a/xen/include/hypervisor-ifs/block.h +++ b/xen/include/hypervisor-ifs/block.h @@ -9,28 +9,6 @@ #define __BLOCK_H__ /* - * Device numbers - */ - -#define XENDEV_TYPE_MASK 0xf000 -#define XENDEV_IDX_MASK 0x0fff -#define XENDEV_TYPE_SHIFT 12 -#define XENDEV_IDX_SHIFT 0 - -#define XENDEV_IDE (1 << XENDEV_TYPE_SHIFT) -#define XENDEV_SCSI (2 << XENDEV_TYPE_SHIFT) -#define XENDEV_VIRTUAL (3 << XENDEV_TYPE_SHIFT) - -#define IS_IDE_XENDEV(_d) (((_d) & XENDEV_TYPE_MASK) == XENDEV_IDE) -#define IS_SCSI_XENDEV(_d) (((_d) & XENDEV_TYPE_MASK) == XENDEV_SCSI) -#define IS_VIRTUAL_XENDEV(_d) (((_d) & XENDEV_TYPE_MASK) == XENDEV_VIRTUAL) - -#define MK_IDE_XENDEV(_i) ((_i) | XENDEV_IDE) -#define MK_SCSI_XENDEV(_i) ((_i) | XENDEV_SCSI) -#define MK_VIRTUAL_XENDEV(_i) ((_i) | XENDEV_VIRTUAL) - - -/* * * These are the ring data structures for buffering messages between * the hypervisor and guestos's. diff --git a/xen/include/hypervisor-ifs/vbd.h b/xen/include/hypervisor-ifs/vbd.h index 8cbd059d0b..ed7158c889 100644 --- a/xen/include/hypervisor-ifs/vbd.h +++ b/xen/include/hypervisor-ifs/vbd.h @@ -1,41 +1,11 @@ #ifndef __HYP_IFS_VBD_H__ #define __HYP_IFS_VBD_H__ -#define XEN_MAX_VBDS 100 /* total number of vbds across all doms */ - -#define XEN_VBD_UNUSED 0 /* bzero default */ -#define XEN_DISK_READ_WRITE 1 -#define XEN_DISK_READ_ONLY 2 -#define XEN_VBD_RO XEN_DISK_READ_ONLY -#define XEN_VBD_RW XEN_DISK_READ_WRITE - -/* - * - * virtual disk (vhd) structures, used by XEN_BLOCK_VBD_{CREATE, DELETE} - * - */ - -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; - -#define XEN_VBD_KEYSIZE 10 - -typedef struct xv_disk -{ - int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */ - int domain; /* domain */ - int vbd; /* segment number */ - char key[XEN_VBD_KEYSIZE]; /* key for benefit of dom0 userspace */ - 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; #define PHYSDISK_MODE_R 1 #define PHYSDISK_MODE_W 2 + +#if 0 typedef struct xp_disk { int mode; /* 0 -> revoke existing access, otherwise bitmask of @@ -60,42 +30,52 @@ typedef struct { unsigned mode; } entries[PHYSDISK_MAX_ACES_PER_REQUEST]; } physdisk_probebuf_t; - - -typedef struct xen_vbd_info -{ - int count; - struct { - unsigned domain; - unsigned seg_nr; - char key[XEN_VBD_KEYSIZE]; - unsigned short mode; /* UNUSED, RO, or RW. */ - } vbds[XEN_MAX_VBDS]; -} xen_vbd_info_t; - +#endif /* Block I/O trap operations and associated structures. */ #define BLOCK_IO_OP_SIGNAL 0 /* let xen know we have work to do */ -#define BLOCK_IO_OP_ATTACH_VBD 1 /* attach a VBD to a given domain */ -#define BLOCK_IO_OP_RESET 2 /* reset ring indexes on quiescent i/f */ +#define BLOCK_IO_OP_RESET 1 /* reset ring indexes on quiescent i/f */ +#define BLOCK_IO_OP_VBD_CREATE 2 /* create a new VBD for a given domain */ +#define BLOCK_IO_OP_VBD_ADD 3 /* add an extent to a given VBD */ +#define BLOCK_IO_OP_VBD_REMOVE 4 /* remove an extent from a given VBD */ +#define BLOCK_IO_OP_VBD_DELETE 5 /* delete a VBD */ + -typedef struct _extent { - u16 raw_device; +typedef struct _xen_extent { + u16 device; ulong start_sector; ulong nr_sectors; -} extent_t; + u16 mode; +} xen_extent_t; + + +typedef struct _vbd_create { + unsigned domain; + u16 vdevice; +} vbd_create_t; + + +typedef struct _vbd_add { + unsigned domain; + u16 vdevice; + xen_extent_t extent; +} vbd_add_t; + +typedef struct _vbd_remove { + unsigned domain; + u16 vdevice; + xen_extent_t extent; +} vbd_remove_t; + + +typedef struct _vbd_delete { + unsigned domain; + u16 vdevice; +} vbd_delete_t; - -typedef struct _vbd_attach { - int domain; - u16 mode; /* read-only or read-write */ - u16 device; /* how this domain refers to this VBD */ - int nr_extents; /* number of extents in the VBD */ - extent_t *extents; /* pointer to /array/ of extents */ -} vbd_attach_t; typedef struct block_io_op_st @@ -104,7 +84,10 @@ typedef struct block_io_op_st union { /* no entry for BLOCK_IO_OP_SIGNAL */ - vbd_attach_t attach_info; + vbd_create_t create_info; + vbd_add_t add_info; + vbd_remove_t remove_info; + vbd_delete_t delete_info; /* no entry for BLOCK_IO_OP_RESET */ } u; diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h index b01345afe1..a17b7864a3 100644 --- a/xen/include/xeno/sched.h +++ b/xen/include/xeno/sched.h @@ -119,7 +119,7 @@ struct task_struct the process can do raw access to. */ spinlock_t physdev_lock; - vbd_t *vbd_list[XEN_MAX_VBDS]; + vbd_t *vbdtab[VBD_HTAB_SZ]; // mapping from 16bit vdevices to vbds /* VM */ struct mm_struct mm; diff --git a/xen/include/xeno/vbd.h b/xen/include/xeno/vbd.h index dcb4af9167..8c4d6b099d 100644 --- a/xen/include/xeno/vbd.h +++ b/xen/include/xeno/vbd.h @@ -9,7 +9,34 @@ #include <hypervisor-ifs/block.h> #include <hypervisor-ifs/vbd.h> -/* Describes a physical disk extent. */ +/* an entry in a list of xen_extent's */ +typedef struct _xen_extent_le { + xen_extent_t extent; // an individual extent + struct _xen_extent_le *next; // and a pointer to the next +} xen_extent_le_t; + + +/* +** This is what a vbd looks like from the pov of xen: essentially a list +** of xen_extents which a given domain refers to by a particular 16bit id. +** Each domain has a hash table to map from these to the relevant VBD. +*/ +typedef struct _vbd { + unsigned short vdevice; // what the domain refers to this vbd as + xen_extent_le_t *extents; // list of xen_extents making up this vbd + struct _vbd *next; // for chaining in the hash table +} vbd_t; + +#define VBD_HTAB_SZ 16 // no. of entries in the vbd hash table. + +void xen_vbd_initialize(void); +void xen_refresh_vbd_list (struct task_struct *p); +long vbd_create(vbd_create_t *create_info); +long vbd_add(vbd_add_t *add_info); +long vbd_remove(vbd_remove_t *remove_info); +long vbd_delete(vbd_delete_t *delete_info); + +/* Describes a physical disk extent (part of a block io request) */ typedef struct { unsigned short dev; unsigned short nr_sects; @@ -17,34 +44,12 @@ typedef struct { unsigned long buffer; } phys_seg_t; -struct task_struct; - -void xen_vbd_initialize(void); -void xen_refresh_vbd_list (struct task_struct *p); -int xen_vbd_create(xv_disk_t *xvd); -int xen_vbd_delete(struct task_struct *p, int segnr); -int xen_vbd_map_request( - phys_seg_t *pseg, struct task_struct *p, int operation, - unsigned short vbd_number, - unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects); - -typedef struct vbd -{ - int mode; /* UNUSED, RO, or RW */ - int domain; - int vbd_number; /* vbd number for domain */ - char key[XEN_VBD_KEYSIZE]; /* for the userspace tools in dom0 */ - int num_extents; /* number of extents */ - extent_t *extents; -} vbd_t; - -#endif -#ifndef PHYSDISK_ACES__ -#define PHYSDISK_ACES__ +int vbd_translate(phys_seg_t * pseg, int *nr_segs, + struct task_struct *p, int operation); -struct task_struct; +#if 0 void destroy_physdisk_aces(struct task_struct *p); int xen_physdisk_grant(xp_disk_t *); @@ -52,5 +57,7 @@ int xen_physdisk_probe(struct task_struct *requesting_task, physdisk_probebuf_t *); int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p, int operation); +#endif + #endif /* PHYSDISK_ACES__ */ diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile index 2b27356487..55174d619e 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile @@ -1,3 +1,3 @@ O_TARGET := blk.o -obj-y := xl_block.o xl_ide.o xl_scsi.o xl_vbd.o info.o +obj-y := xl_block.o xl_vbd.o info.o include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c index 56dab7e3f3..63c4f4e14a 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c @@ -55,95 +55,11 @@ static inline void signal_requests_to_xen(void) return; } - -inline kdev_t physdev_to_xldev(unsigned short physdev) -{ - switch (physdev & XENDEV_TYPE_MASK) { - case XENDEV_IDE: - if ( (physdev & XENDEV_IDX_MASK) < XLIDE_DEVS_PER_MAJOR) { - return MKDEV(XLIDE_MAJOR_0, - (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT); - } else if ( (physdev & XENDEV_IDX_MASK) < (XLIDE_DEVS_PER_MAJOR * 2)) { - return MKDEV(XLIDE_MAJOR_1, - (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT); - } - break; - case XENDEV_SCSI: - return MKDEV(XLSCSI_MAJOR, - (physdev & XENDEV_IDX_MASK) << XLSCSI_PARTN_SHIFT); - case XENDEV_VIRTUAL: - return MKDEV(XLVIRT_MAJOR, - (physdev & XENDEV_IDX_MASK) << XLVIRT_PARTN_SHIFT); - } - - return 0; -} - - -/* Convert from a XenoLinux major device to the Xen-level 'physical' device */ -inline unsigned short xldev_to_physdev(kdev_t xldev) -{ - unsigned short physdev = 0; - - switch ( MAJOR(xldev) ) - { - case XLIDE_MAJOR_0: - physdev = XENDEV_IDE + (0*XLIDE_DEVS_PER_MAJOR) + - (MINOR(xldev) >> XLIDE_PARTN_SHIFT); - break; - - case XLIDE_MAJOR_1: - physdev = XENDEV_IDE + (1*XLIDE_DEVS_PER_MAJOR) + - (MINOR(xldev) >> XLIDE_PARTN_SHIFT); - break; - - case XLSCSI_MAJOR: - physdev = XENDEV_SCSI + (MINOR(xldev) >> XLSCSI_PARTN_SHIFT); - break; - - case XLVIRT_MAJOR: - physdev = XENDEV_VIRTUAL + (MINOR(xldev) >> XLVIRT_PARTN_SHIFT); - break; - } - - return physdev; -} - - -static inline struct gendisk *xldev_to_gendisk(kdev_t xldev) -{ - struct gendisk *gd = NULL; - - switch ( MAJOR(xldev) ) - { - case XLIDE_MAJOR_0: - gd = xlide_gendisk[0]; - break; - - case XLIDE_MAJOR_1: - gd = xlide_gendisk[1]; - break; - - case XLSCSI_MAJOR: - gd = xlscsi_gendisk; - break; - - case XLVIRT_MAJOR: - gd = xlvbd_gendisk; - break; - } - - if ( gd == NULL ) BUG(); - - return gd; -} - - static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev) { struct gendisk *gd = xldev_to_gendisk(xldev); return (xl_disk_t *)gd->real_devices + - (MINOR(xldev) >> PARTN_SHIFT(xldev)); + (MINOR(xldev) >> gd->minor_shift); } @@ -192,27 +108,7 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep, return xenolinux_block_revalidate(dev); case BLKSSZGET: - switch ( MAJOR(dev) ) - { - case XLIDE_MAJOR_0: - DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlide_hwsect(MINOR(dev))); - return xlide_hwsect(MINOR(dev)); - - case XLSCSI_MAJOR: - DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlscsi_hwsect(MINOR(dev))); - return xlscsi_hwsect(MINOR(dev)); - - case XLVIRT_MAJOR: - DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlsbd_hwsect(MINOR(dev))); - return xlvbd_hwsect(MINOR(dev)); - - default: - printk(KERN_ALERT "BLKSSZGET ioctl() on bogus disk!\n"); - return 0; - } + return hardsect_size[MAJOR(dev)][MINOR(dev)]; case BLKBSZGET: /* get block size */ DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET); @@ -275,7 +171,7 @@ int xenolinux_block_revalidate(kdev_t dev) struct gendisk *gd = xldev_to_gendisk(dev); xl_disk_t *disk = xldev_to_xldisk(dev); unsigned long flags; - int i, partn_shift = PARTN_SHIFT(dev), disk_nr = MINOR(dev) >> partn_shift; + int i, disk_nr = MINOR(dev) >> gd->minor_shift; DPRINTK("xenolinux_block_revalidate: %d\n", dev); @@ -287,13 +183,14 @@ int xenolinux_block_revalidate(kdev_t dev) } spin_unlock_irqrestore(&io_request_lock, flags); - for ( i = (1 << partn_shift) - 1; i >= 0; i-- ) + for ( i = gd->nr_real - 1; i >= 0; i-- ) { invalidate_device(dev+i, 1); gd->part[MINOR(dev+i)].start_sect = 0; gd->part[MINOR(dev+i)].nr_sects = 0; } +#if 0 /* VBDs can change under our feet. Check if that has happened. */ if ( MAJOR(dev) == XLVIRT_MAJOR ) { @@ -311,9 +208,9 @@ int xenolinux_block_revalidate(kdev_t dev) kfree(xdi); } } +#endif - grok_partitions(gd, disk_nr, - 1 << partn_shift, disk->capacity); + grok_partitions(gd, disk_nr, gd->nr_real, disk->capacity); return 0; } @@ -337,7 +234,6 @@ static int hypervisor_request(unsigned long id, kdev_t device) { unsigned long buffer_ma = phys_to_machine(virt_to_phys(buffer)); - kdev_t phys_device = (kdev_t) 0; struct gendisk *gd; blk_ring_req_entry_t *req; struct buffer_head *bh; @@ -350,25 +246,20 @@ static int hypervisor_request(unsigned long id, switch ( operation ) { - case XEN_BLOCK_VBD_CREATE: - case XEN_BLOCK_VBD_DELETE: - case XEN_BLOCK_PHYSDEV_GRANT: - case XEN_BLOCK_PHYSDEV_PROBE: +// case XEN_BLOCK_PHYSDEV_GRANT: +// case XEN_BLOCK_PHYSDEV_PROBE: case XEN_BLOCK_PROBE: if ( RING_PLUGGED ) return 1; - phys_device = (kdev_t) 0; sector_number = 0; DISABLE_SCATTERGATHER(); break; case XEN_BLOCK_READ: case XEN_BLOCK_WRITE: - phys_device = xldev_to_physdev(device); gd = xldev_to_gendisk(device); - sector_number += gd->part[MINOR(device)].start_sect; if ( (sg_operation == operation) && - (sg_dev == phys_device) && + (sg_dev == device) && (sg_next_sect == sector_number) ) { req = &blk_ring->ring[(req_prod-1)&(BLK_RING_SIZE-1)].req; @@ -389,7 +280,7 @@ static int hypervisor_request(unsigned long id, else { sg_operation = operation; - sg_dev = phys_device; + sg_dev = device; sg_next_sect = sector_number + nr_sectors; } break; @@ -403,7 +294,7 @@ static int hypervisor_request(unsigned long id, req->id = id; req->operation = operation; req->sector_number = sector_number; - req->device = phys_device; + req->device = device; req->nr_segments = 1; req->buffer_and_sects[0] = buffer_ma | nr_sectors; req_prod = BLK_RING_INC(req_prod); @@ -542,9 +433,11 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) case XEN_BLOCK_VBD_CREATE: case XEN_BLOCK_VBD_DELETE: - case XEN_BLOCK_PROBE: case XEN_BLOCK_PHYSDEV_GRANT: case XEN_BLOCK_PHYSDEV_PROBE: + printk(KERN_ALERT "response for bogus operation %d\n", + bret->operation); + case XEN_BLOCK_PROBE: xlblk_control_msg_pending = bret->status; break; @@ -634,24 +527,7 @@ int __init xlblk_init(void) goto fail; } - { - int i; - printk(KERN_ALERT "xlblk_init: xen returned info for %d disks\n", - xlblk_disk_info.count); - for(i=0; i < xlblk_disk_info.count; i++) { - printk("%d -- device no=%x, type=%d, capacity=%ldMB\n", - i, xlblk_disk_info.disks[i].device, - xlblk_disk_info.disks[i].type, - xlblk_disk_info.disks[i].capacity >> 11); - - } - - } - /* Pass the information to our fake IDE and SCSI susbystems. */ - xlide_init(&xlblk_disk_info); - xlscsi_init(&xlblk_disk_info); - - /* And do the same for the 'virtual block device' world */ + /* Pass the information to our virtual block device susbystem. */ xlvbd_init(&xlblk_disk_info); return 0; @@ -663,8 +539,6 @@ int __init xlblk_init(void) static void __exit xlblk_cleanup(void) { xlvbd_cleanup(); - xlscsi_cleanup(); - xlide_cleanup(); free_irq(XLBLK_RESPONSE_IRQ, NULL); } diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h index a0cf5b8591..8fcaa59383 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h @@ -39,37 +39,9 @@ #define DPRINTK_IOCTL(_f, _a...) ((void)0) #endif -/* XL IDE and SCSI use same major/minor numbers as normal Linux devices. */ -#define XLIDE_MAJOR_0 IDE0_MAJOR -#define XLIDE_MAJOR_1 IDE1_MAJOR -#define XLSCSI_MAJOR SCSI_DISK0_MAJOR - -#define XLIDE_PARTN_SHIFT 6 -#define XLSCSI_PARTN_SHIFT 4 -#define XLVIRT_PARTN_SHIFT 4 - -static inline int PARTN_SHIFT(kdev_t dev) -{ - switch ( MAJOR(dev) ) - { - case XLIDE_MAJOR_0: - case XLIDE_MAJOR_1: - return XLIDE_PARTN_SHIFT; - case XLSCSI_MAJOR: - return XLSCSI_PARTN_SHIFT; - case XLVIRT_MAJOR: - return XLVIRT_PARTN_SHIFT; - default: - BUG(); - } -} - -#define XLIDE_DEVS_PER_MAJOR 2 -#define XLSCSI_DEVS_PER_MAJOR 16 -#define XLVIRT_DEVS_PER_MAJOR 16 /* - * We have one of these per XL-IDE, XL-SCSI, and XL-VIRT device. + * We have one of these per vbd, whether ide, scsi or 'other'. * They hang in an array off the gendisk structure. We may end up putting * all kinds of interesting stuff here :-) */ @@ -88,25 +60,10 @@ extern int xenolinux_block_check(kdev_t dev); extern int xenolinux_block_revalidate(kdev_t dev); extern void do_xlblk_request (request_queue_t *rq); -/* Fake IDE subsystem. */ -extern int xlide_init(xen_disk_info_t *xdi); -extern int xlide_hwsect(int minor); -extern void xlide_cleanup(void); -extern struct gendisk *xlide_gendisk[]; - -/* Fake SCSI subsystem. */ -extern int xlscsi_init(xen_disk_info_t *xdi); -extern int xlscsi_hwsect(int minor); -extern void xlscsi_cleanup(void); -extern struct gendisk *xlscsi_gendisk; /* Virtual block-device subsystem. */ extern int xlvbd_init(xen_disk_info_t *xdi); -extern int xlvbd_hwsect(int minor); extern void xlvbd_cleanup(void); -extern struct gendisk *xlvbd_gendisk; - -extern unsigned short xldev_to_physdev(kdev_t xldev); -extern kdev_t physdev_to_xldev(unsigned short physdev); +extern struct gendisk *xldev_to_gendisk(kdev_t xldev); #endif /* __XL_BLOCK_H__ */ diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_ide.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_ide.c deleted file mode 100644 index e49c25ba05..0000000000 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_ide.c +++ /dev/null @@ -1,204 +0,0 @@ -/****************************************************************************** - * xl_ide.c - * - * Xenolinux virtual IDE block-device driver. - */ - -#include "xl_block.h" -#include <linux/blk.h> - -#define XLIDE_MAX 256 -#define XLIDE_MAJOR_NAME "hd" -static int xlide_blksize_size[XLIDE_MAX]; -static int xlide_hardsect_size[XLIDE_MAX]; -static int xlide_max_sectors[XLIDE_MAX]; - -#define XLIDE_NR_MAJORS 2 - -struct gendisk *xlide_gendisk[XLIDE_NR_MAJORS] = { NULL }; - -static struct block_device_operations xlide_block_fops = -{ - open: xenolinux_block_open, - release: xenolinux_block_release, - ioctl: xenolinux_block_ioctl, - check_media_change: xenolinux_block_check, - revalidate: xenolinux_block_revalidate, -}; - -int xlide_hwsect(int minor) -{ - return xlide_hardsect_size[minor]; -} - -static int get_major(int major) -{ - int r = register_blkdev(major, XLIDE_MAJOR_NAME, &xlide_block_fops); - if ( r < 0 ) - printk (KERN_ALERT "XL IDE: can't get major %d\n", XLIDE_MAJOR_0); - return r; -} - -static void setup_major(struct gendisk **pgd, - xen_disk_info_t *xdi, int base, int major) -{ - int i, minors, disk, units = XLIDE_DEVS_PER_MAJOR; - unsigned short minor; - unsigned char buf[64]; - struct gendisk *gd; - - blk_size[major] = NULL; - blksize_size[major] = xlide_blksize_size + base*(1<<XLIDE_PARTN_SHIFT); - hardsect_size[major] = xlide_hardsect_size + base*(1<<XLIDE_PARTN_SHIFT); - max_sectors[major] = xlide_max_sectors + base*(1<<XLIDE_PARTN_SHIFT); - read_ahead[major] = 8; - - blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request); - - /* - * Turn off barking 'headactive' mode. We dequeue buffer heads as soon as - * we pass them down to Xen. - */ - blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); - - /* Construct an appropriate gendisk structure. */ - minors = units * (1<<XLIDE_PARTN_SHIFT); - 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); - gd->major = major; - gd->major_name = XLIDE_MAJOR_NAME; - gd->minor_shift = XLIDE_PARTN_SHIFT; - gd->max_p = 1<<XLIDE_PARTN_SHIFT; - gd->nr_real = units; - gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL); - gd->next = NULL; - gd->fops = &xlide_block_fops; - gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL); - gd->flags = kmalloc(sizeof(*gd->flags) * units, GFP_KERNEL); - memset(gd->sizes, 0, minors * sizeof(int)); - memset(gd->part, 0, minors * sizeof(struct hd_struct)); - memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units); - memset(gd->flags, 0, sizeof(*gd->flags) * units); - memset(gd->real_devices, 0, sizeof(xl_disk_t) * units); - *pgd = gd; - add_gendisk(gd); - - /* Now register each disk in turn. */ - for ( i = 0; i < xdi->count; i++ ) - { - disk = xdi->disks[i].device & XENDEV_IDX_MASK; - minor = (disk-base) << XLIDE_PARTN_SHIFT; - - if ( !IS_IDE_XENDEV(xdi->disks[i].device) || - (disk < base) || (disk >= (base + XLIDE_DEVS_PER_MAJOR)) ) - continue; - - ((xl_disk_t *)gd->real_devices)[disk-base].capacity = - xdi->disks[i].capacity; - - switch (xdi->disks[i].type) - { - case XD_TYPE_CDROM: - set_device_ro(MKDEV(major, minor), 1); - - case XD_TYPE_FLOPPY: - case XD_TYPE_TAPE: - gd->flags[disk] = GENHD_FL_REMOVABLE; - printk(KERN_ALERT "Skipping partition check on %s /dev/%s\n", - xdi->disks[i].type==XD_TYPE_CDROM ? "cdrom" : - (xdi->disks[i].type==XD_TYPE_TAPE ? "tape" : "floppy"), - disk_name(gd, minor, buf)); - break; - - case XD_TYPE_DISK: - register_disk(gd, - MKDEV(major, minor), - 1<<XLIDE_PARTN_SHIFT, - &xlide_block_fops, xdi->disks[i].capacity); - break; - - default: - printk(KERN_ALERT "XenoLinux: unknown ide device type %d\n", - xdi->disks[i].type); - break; - } - } - - return; -} - - -int xlide_init(xen_disk_info_t *xdi) -{ - int i, units; - - /* If we don't have any usable IDE devices we may as well bail now. */ - units = 0; - for ( i = 0; i < xdi->count; i++ ) - if ( IS_IDE_XENDEV(xdi->disks[i].device) && - ((xdi->disks[i].device & XENDEV_IDX_MASK) < - (XLIDE_NR_MAJORS*XLIDE_DEVS_PER_MAJOR)) ) - units++; - if ( units == 0 ) return 0; - - SET_MODULE_OWNER(&xlide_block_fops); - - if ( get_major(XLIDE_MAJOR_0) < 0 ) - return 0; - if ( get_major(XLIDE_MAJOR_1) < 0 ) - { - (void)unregister_blkdev(XLIDE_MAJOR_0, XLIDE_MAJOR_NAME); - return 0; - } - - /* Initialize global arrays. */ - for ( i = 0; i < XLIDE_MAX; i++ ) - { - xlide_blksize_size[i] = 512; - xlide_hardsect_size[i] = 512; - xlide_max_sectors[i] = 128; - } - - setup_major(&xlide_gendisk[0], xdi, 0*XLIDE_DEVS_PER_MAJOR, XLIDE_MAJOR_0); - setup_major(&xlide_gendisk[1], xdi, 1*XLIDE_DEVS_PER_MAJOR, XLIDE_MAJOR_1); - - return 0; -} - - -static void cleanup_major(int major) -{ - blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); - - read_ahead[major] = 0; - - if ( blksize_size[major] != NULL ) - { - kfree(blksize_size[major]); - blksize_size[major] = NULL; - } - - if ( hardsect_size[major] != NULL ) - { - kfree(hardsect_size[major]); - hardsect_size[major] = NULL; - } - - if ( max_sectors[major] != NULL ) - { - kfree(max_sectors[major]); - max_sectors[major] = NULL; - } - - (void)unregister_blkdev(major, XLIDE_MAJOR_NAME); -} - -void xlide_cleanup(void) -{ - if ( xlide_gendisk[0] == NULL ) return; - xlide_gendisk[0] = NULL; - cleanup_major(XLIDE_MAJOR_0); - cleanup_major(XLIDE_MAJOR_1); -} - diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_scsi.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_scsi.c deleted file mode 100644 index c0f389f181..0000000000 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_scsi.c +++ /dev/null @@ -1,168 +0,0 @@ -/****************************************************************************** - * xl_scsi.c - * - * Xenolinux virtual SCSI block-device driver. - */ - -#include "xl_block.h" - -#define MAJOR_NR XLSCSI_MAJOR -#include <linux/blk.h> - -#define XLSCSI_MAX 256 -#define XLSCSI_MAJOR_NAME "sd" -static int xlscsi_blksize_size[XLSCSI_MAX]; -static int xlscsi_hardsect_size[XLSCSI_MAX]; -static int xlscsi_max_sectors[XLSCSI_MAX]; - -struct gendisk *xlscsi_gendisk = NULL; - -static struct block_device_operations xlscsi_block_fops = -{ - open: xenolinux_block_open, - release: xenolinux_block_release, - ioctl: xenolinux_block_ioctl, - check_media_change: xenolinux_block_check, - revalidate: xenolinux_block_revalidate, -}; - - -/* tiny inteface fn */ -int xlscsi_hwsect(int minor) -{ - return xlscsi_hardsect_size[minor]; -} - - -int xlscsi_init(xen_disk_info_t *xdi) -{ - int i, result, units, minors, disk; - struct gendisk *gd; - - /* If we don't have any usable SCSI devices we may as well bail now. */ - units = 0; - for ( i = 0; i < xdi->count; i++ ) - if ( IS_SCSI_XENDEV(xdi->disks[i].device) && - ((xdi->disks[i].device & XENDEV_IDX_MASK) < - XLSCSI_DEVS_PER_MAJOR) ) - units++; - if ( units == 0 ) return 0; - - SET_MODULE_OWNER(&xlscsi_block_fops); - - result = register_blkdev(XLSCSI_MAJOR, XLSCSI_MAJOR_NAME, - &xlscsi_block_fops); - if ( result < 0 ) - { - printk (KERN_ALERT "XL SCSI: can't get major %d\n", XLSCSI_MAJOR); - return result; - } - - /* Initialize global arrays. */ - for ( i = 0; i < XLSCSI_MAX; i++ ) - { - xlscsi_blksize_size[i] = 1024; //XXX 512; - xlscsi_hardsect_size[i] = 512; - xlscsi_max_sectors[i] = 128*8; //XXX 128 - } - - blk_size[XLSCSI_MAJOR] = NULL; - blksize_size[XLSCSI_MAJOR] = xlscsi_blksize_size; - hardsect_size[XLSCSI_MAJOR] = xlscsi_hardsect_size; - max_sectors[XLSCSI_MAJOR] = xlscsi_max_sectors; - read_ahead[XLSCSI_MAJOR] = 0; //XXX8; - - blk_init_queue(BLK_DEFAULT_QUEUE(XLSCSI_MAJOR), do_xlblk_request); - - /* - * Turn off barking 'headactive' mode. We dequeue buffer heads as - * soon as we pass them down to Xen. - */ - blk_queue_headactive(BLK_DEFAULT_QUEUE(XLSCSI_MAJOR), 0); - - units = XLSCSI_MAX >> XLSCSI_PARTN_SHIFT; - - /* Construct an appropriate gendisk structure. */ - minors = units * (1<<XLSCSI_PARTN_SHIFT); - 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); - gd->major = XLSCSI_MAJOR; - gd->major_name = XLSCSI_MAJOR_NAME; - gd->minor_shift = XLSCSI_PARTN_SHIFT; - gd->max_p = 1<<XLSCSI_PARTN_SHIFT; - gd->nr_real = units; - gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL); - gd->next = NULL; - gd->fops = &xlscsi_block_fops; - gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL); - gd->flags = kmalloc(sizeof(*gd->flags) * units, GFP_KERNEL); - memset(gd->sizes, 0, minors * sizeof(int)); - memset(gd->part, 0, minors * sizeof(struct hd_struct)); - memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units); - memset(gd->flags, 0, sizeof(*gd->flags) * units); - memset(gd->real_devices, 0, sizeof(xl_disk_t) * units); - xlscsi_gendisk = gd; - add_gendisk(gd); - - /* Now register each disk in turn. */ - for ( i = 0; i < xdi->count; i++ ) - { - disk = xdi->disks[i].device & XENDEV_IDX_MASK; - - if ( !IS_SCSI_XENDEV(xdi->disks[i].device) || - (disk >= XLSCSI_DEVS_PER_MAJOR) ) - continue; - - ((xl_disk_t *)gd->real_devices)[disk].capacity = - xdi->disks[i].capacity; - register_disk(gd, - MKDEV(XLSCSI_MAJOR, disk<<XLSCSI_PARTN_SHIFT), - 1<<XLSCSI_PARTN_SHIFT, - &xlscsi_block_fops, - xdi->disks[i].capacity); - } - - printk(KERN_ALERT - "XenoLinux Virtual SCSI Device Driver installed [device: %d]\n", - XLSCSI_MAJOR); - - return 0; -} - - -void xlscsi_cleanup(void) -{ - if ( xlscsi_gendisk == NULL ) return; - - blk_cleanup_queue(BLK_DEFAULT_QUEUE(XLSCSI_MAJOR)); - - xlscsi_gendisk = NULL; - - read_ahead[XLSCSI_MAJOR] = 0; - - if ( blksize_size[XLSCSI_MAJOR] != NULL ) - { - kfree(blksize_size[XLSCSI_MAJOR]); - blksize_size[XLSCSI_MAJOR] = NULL; - } - - if ( hardsect_size[XLSCSI_MAJOR] != NULL ) - { - kfree(hardsect_size[XLSCSI_MAJOR]); - hardsect_size[XLSCSI_MAJOR] = NULL; - } - - if ( max_sectors[XLSCSI_MAJOR] != NULL ) - { - kfree(max_sectors[XLSCSI_MAJOR]); - max_sectors[XLSCSI_MAJOR] = NULL; - } - - if ( unregister_blkdev(XLSCSI_MAJOR, XLSCSI_MAJOR_NAME) != 0 ) - { - printk(KERN_ALERT - "XenoLinux Virtual SCSI Device Driver uninstalled w/ errs\n"); - } -} - diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c index e8ea5b85e7..9656452c43 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c @@ -7,19 +7,52 @@ #include "xl_block.h" -#define MAJOR_NR XLVIRT_MAJOR +// #define MAJOR_NR XLVIRT_MAJOR #include <linux/blk.h> /* Copied from linux/ide.h */ typedef unsigned char byte; -#define XLVIRT_MAX 256 -#define XLVIRT_MAJOR_NAME "xvd" -static int xlvbd_blksize_size[XLVIRT_MAX]; -static int xlvbd_hardsect_size[XLVIRT_MAX]; -static int xlvbd_max_sectors[XLVIRT_MAX]; +#define XLVBD_MAX_MAJORS 64 /* total number of vbds we support */ + +struct gendisk *xlvbd_gendisk[XLVBD_MAX_MAJORS] = { NULL }; + +/* For convenience we distinguish between ide, scsi and 'other' (i.e. +** potentially combinations of the two) in the naming scheme and in a +** few other places (like default readahead, etc). +*/ +#define XLIDE_MAJOR_NAME "hd" +#define XLSCSI_MAJOR_NAME "sd" +#define XLVBD_MAJOR_NAME "xvd" + +#define XLIDE_DEVS_PER_MAJOR 2 +#define XLSCSI_DEVS_PER_MAJOR 16 +#define XLVBD_DEVS_PER_MAJOR 16 + + +#define XLIDE_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ +#define XLIDE_MAX_MINORS (1 << XLIDE_PARTN_SHIFT) /* minors per ide vbd */ + +#define XLSCSI_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ +#define XLSCSI_MAX_MINORS (1 << XLSCSI_PARTN_SHIFT) /* minors per scsi vbd */ + +#define XLVBD_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ +#define XLVBD_MAX_MINORS (1 << XLVBD_PARTN_SHIFT) /* minors per 'other' vbd */ + + +/* the below are for the use of the generic drivers/block/ll_rw_block.c code */ +static int xlide_blksize_size[XLIDE_MAX_MINORS]; +static int xlide_hardsect_size[XLIDE_MAX_MINORS]; +static int xlide_max_sectors[XLIDE_MAX_MINORS]; + +static int xlscsi_blksize_size[XLSCSI_MAX_MINORS]; +static int xlscsi_hardsect_size[XLSCSI_MAX_MINORS]; +static int xlscsi_max_sectors[XLSCSI_MAX_MINORS]; + +static int xlvbd_blksize_size[XLVBD_MAX_MINORS]; +static int xlvbd_hardsect_size[XLVBD_MAX_MINORS]; +static int xlvbd_max_sectors[XLVBD_MAX_MINORS]; -struct gendisk *xlvbd_gendisk = NULL; static struct block_device_operations xlvbd_block_fops = { @@ -31,104 +64,249 @@ static struct block_device_operations xlvbd_block_fops = }; -int xlvbd_hwsect(int minor) -{ - return xlvbd_hardsect_size[minor]; -} - +typedef unsigned char bool; +/* +** Set up all the linux device goop for the virtual block devices (vbd's) +** that xen tells us about. Note that although from xen's pov VBDs are +** addressed simply an opaque 16-bit device number, the domain creation +** tools conventionally allocate these numbers to correspond to those +** used by 'real' linux -- this is just for convenience as it means e.g. +** that the same /etc/fstab can be used when booting with or without xen. +*/ int __init xlvbd_init(xen_disk_info_t *xdi) { - int i, result, units, minors, disk; + int i, result, nminors; struct gendisk *gd; + kdev_t device; + unsigned short major, minor, real_minor; + bool is_ide, is_scsi; + char *major_name; + unsigned char buf[64]; + int majors[256]; SET_MODULE_OWNER(&xlvbd_block_fops); - result = register_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME, - &xlvbd_block_fops); - if ( result < 0 ) + /* Initialize the global arrays. */ + for (i = 0; i < XLIDE_MAX_MINORS; i++) { - printk(KERN_ALERT "XL VBD: can't get major %d\n", XLVIRT_MAJOR); - return result; + /* from the generic ide code (drivers/ide/ide-probe.c, etc) */ + xlide_blksize_size[i] = 1024; + xlide_hardsect_size[i] = 512; + xlide_max_sectors[i] = 128; /* 'hwif->rqsize' if we knew it */ } - - /* Initialize global arrays. */ - for (i = 0; i < XLVIRT_MAX; i++) + + for (i = 0; i < XLSCSI_MAX_MINORS; i++) { - xlvbd_blksize_size[i] = 512; - xlvbd_hardsect_size[i] = 512; - xlvbd_max_sectors[i] = 128; + /* from the generic scsi disk code (drivers/scsi/sd.c) */ + xlscsi_blksize_size[i] = 1024; //XXX 512; + xlscsi_hardsect_size[i] = 512; + xlscsi_max_sectors[i] = 128*8; //XXX 128; } - - blk_size[XLVIRT_MAJOR] = NULL; - blksize_size[XLVIRT_MAJOR] = xlvbd_blksize_size; - hardsect_size[XLVIRT_MAJOR] = xlvbd_hardsect_size; - max_sectors[XLVIRT_MAJOR] = xlvbd_max_sectors; - read_ahead[XLVIRT_MAJOR] = 8; - - blk_init_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), do_xlblk_request); - - /* - * Turn off barking 'headactive' mode. We dequeue buffer heads as - * soon as we pass them down to Xen. - */ - blk_queue_headactive(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), 0); - - units = XLVIRT_MAX >> XLVIRT_PARTN_SHIFT; - - /* Construct an appropriate gendisk structure. */ - minors = units * (1<<XLVIRT_PARTN_SHIFT); - 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); - gd->major = XLVIRT_MAJOR; - gd->major_name = XLVIRT_MAJOR_NAME; - gd->minor_shift = XLVIRT_PARTN_SHIFT; - gd->max_p = 1<<XLVIRT_PARTN_SHIFT; - gd->nr_real = units; - gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL); - gd->next = NULL; - gd->fops = &xlvbd_block_fops; - gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL); - gd->flags = kmalloc(sizeof(*gd->flags) * units, GFP_KERNEL); - memset(gd->sizes, 0, minors * sizeof(int)); - memset(gd->part, 0, minors * sizeof(struct hd_struct)); - memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units); - memset(gd->flags, 0, sizeof(*gd->flags) * units); - memset(gd->real_devices, 0, sizeof(xl_disk_t) * units); - xlvbd_gendisk = gd; - add_gendisk(gd); - - /* Now register each disk in turn. */ - for ( i = 0; i < xdi->count; i++ ) + + for (i = 0; i < XLVBD_MAX_MINORS; i++) { - disk = xdi->disks[i].device & XENDEV_IDX_MASK; - - if ( !IS_VIRTUAL_XENDEV(xdi->disks[i].device) || - (disk >= XLVIRT_DEVS_PER_MAJOR) ) - continue; - - ((xl_disk_t *)gd->real_devices)[disk].capacity = - xdi->disks[i].capacity; - register_disk(gd, - MKDEV(XLVIRT_MAJOR, disk<<XLVIRT_PARTN_SHIFT), - 1<<XLVIRT_PARTN_SHIFT, - &xlvbd_block_fops, - xdi->disks[i].capacity); + /* we don't really know what to set these too since it depends */ + xlvbd_blksize_size[i] = 512; + xlvbd_hardsect_size[i] = 512; + xlvbd_max_sectors[i] = 128; } - printk(KERN_ALERT - "XenoLinux Virtual Block Device Driver installed [device: %d]\n", - XLVIRT_MAJOR); + /* keep track of which majors we've seen so far */ + for (i = 0; i < 256; i++) + majors[i] = 0; + + /* + ** We need to loop through each major device we've been told about and: + ** a) register the appropriate blkdev + ** b) setup the indexed-by-major global arrays (blk_size[], + ** blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) + ** c) setup the block queue + make it sensible + ** d) create an appropriate gendisk structure, and + ** e) register the gendisk + */ + for (i = 0; i < xdi->count; i++) + { + device = xdi->disks[i].device; + major = MAJOR(device); + minor = MINOR(device); + is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ + is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ + + if(is_ide) { + major_name = XLIDE_MAJOR_NAME; + nminors = XLIDE_MAX_MINORS; + } else if(is_scsi) { + major_name = XLSCSI_MAJOR_NAME; + nminors = XLSCSI_MAX_MINORS; + } else { + major_name = XLVBD_MAJOR_NAME; + nminors = XLVBD_MAX_MINORS; + } + + /* + ** XXX SMH: conventionally we assume a minor device if the + ** corresponding linux device number would be a minor device; + ** minor devices require slightly different handling than + ** 'full' devices (e.g. in terms of partition table handling). + */ + real_minor = minor & (nminors - 1); + + if(!majors[major]) { + + result = register_blkdev(major, major_name, &xlvbd_block_fops); + if (result < 0) { + printk(KERN_ALERT "XL VBD: can't get major %d\n", major); + continue; + } + + blk_size[major] = NULL; + if(is_ide) { + blksize_size[major] = xlide_blksize_size; + hardsect_size[major] = xlide_hardsect_size; + max_sectors[major] = xlide_max_sectors; + read_ahead[major] = 8; // from drivers/ide/ide-probe.c + } else if(is_scsi) { + blksize_size[major] = xlscsi_blksize_size; + hardsect_size[major] = xlscsi_hardsect_size; + max_sectors[major] = xlscsi_max_sectors; + read_ahead[major] = 0; // XXX 8; -- guessing + } else { + blksize_size[major] = xlvbd_blksize_size; + hardsect_size[major] = xlvbd_hardsect_size; + max_sectors[major] = xlvbd_max_sectors; + read_ahead[major] = 8; + } + + blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request); + + /* + * Turn off barking 'headactive' mode. We dequeue buffer heads as + * soon as we pass them down to Xen. + */ + blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); + + /* Construct an appropriate gendisk structure. */ + gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); + gd->sizes = kmalloc(nminors*sizeof(int), GFP_KERNEL); + gd->part = kmalloc(nminors*sizeof(struct hd_struct), + GFP_KERNEL); + gd->major = major; + gd->major_name = major_name; + + gd->max_p = nminors; + if(is_ide) { + gd->minor_shift = XLIDE_PARTN_SHIFT; + gd->nr_real = XLIDE_DEVS_PER_MAJOR; + } else if(is_scsi) { + gd->minor_shift = XLSCSI_PARTN_SHIFT; + gd->nr_real = XLSCSI_DEVS_PER_MAJOR; + } else { + gd->minor_shift = XLVBD_PARTN_SHIFT; + gd->nr_real = XLVBD_DEVS_PER_MAJOR; + } + gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), + GFP_KERNEL); + gd->next = NULL; + gd->fops = &xlvbd_block_fops; + gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), + GFP_KERNEL); + gd->flags = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL); + + memset(gd->sizes, 0, nminors * sizeof(int)); + memset(gd->part, 0, nminors * sizeof(struct hd_struct)); + memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr)); + memset(gd->flags, 0, gd->nr_real * sizeof(*gd->flags)); + memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t)); + + /* + ** Keep track of gendisk both locally and in the global array. + ** XXX SMH: can probably do without local copy -- FIXME later + */ + xlvbd_gendisk[i] = gd; + add_gendisk(gd); + + /* XXX SMH: not clear on what 'real_devices' is indexed by; + hence using unit number for now but in old code was 'disk' aka + sequence number assigned by xen during probe = barfle? */ + ((xl_disk_t *)gd->real_devices)[minor>>gd->minor_shift].capacity = + xdi->disks[i].capacity; + + + /* remember that we've done this major */ + majors[major] = 1; + } + + if(real_minor) { + + /* Need to skankily setup 'partition' information */ + gd->part[real_minor].start_sect = 0; + gd->part[real_minor].nr_sects = xdi->disks[i].capacity; + gd->sizes[real_minor] = xdi->disks[i].capacity; + + } else { + + /* Some final fix-ups depending on the device type */ + switch (xdi->disks[i].type) + { + case XD_TYPE_CDROM: + set_device_ro(device, 1); + + case XD_TYPE_FLOPPY: + case XD_TYPE_TAPE: + gd->flags[0] = GENHD_FL_REMOVABLE; + printk(KERN_ALERT + "Skipping partition check on %s /dev/%s\n", + xdi->disks[i].type==XD_TYPE_CDROM ? "cdrom" : + (xdi->disks[i].type==XD_TYPE_TAPE ? "tape" : + "floppy"), disk_name(gd, MINOR(device), buf)); + break; + + case XD_TYPE_DISK: + register_disk(gd, device, gd->nr_real, &xlvbd_block_fops, + xdi->disks[i].capacity); + break; + + default: + printk(KERN_ALERT "XenoLinux: unknown ide device type %d\n", + xdi->disks[i].type); + break; + } + + } + + printk(KERN_ALERT "XenoLinux Virtual Block Device Driver " + "installed [device: %04x]\n", device); + } return 0; } +/* +** XXX SMH: crappy linear scan routine to map from a device number bac k +** to the relevant gendisk; could be made better if and when it becomes +** an issue but for now we expect success within a few loop iterations. +*/ +struct gendisk *xldev_to_gendisk(kdev_t xldev) +{ + int i; + short major = MAJOR(xldev); + + for(i = 0; i < XLVBD_MAX_MAJORS; i++) { + if(xlvbd_gendisk[i]->major == major) + return xlvbd_gendisk[i]; + } + + /* didn't find it -- death */ + BUG(); + return NULL; +} void xlvbd_cleanup(void) { +#if 0 if ( xlvbd_gendisk == NULL ) return; - + blk_cleanup_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR)); xlvbd_gendisk = NULL; @@ -159,6 +337,8 @@ void xlvbd_cleanup(void) "XenoLinux Virtual Block Device Driver" " uninstalled w/ errs\n"); } +#endif + printk(KERN_ALERT "xlvbd_cleanup: not implemented XXX FIXME SMH\n"); } diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c index 3f0bbd6102..ff394a0cdd 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c @@ -61,6 +61,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, TRAP_INSTR "; " "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" : "=a" (ret) : "0" (&hypercall) : "memory" ); + } break; @@ -99,25 +100,10 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, } break; - case IOCTL_PRIVCMD_LINDEV_TO_XENDEV: - { - ret = (int)xldev_to_physdev((kdev_t)data); - } - break; - - case IOCTL_PRIVCMD_XENDEV_TO_LINDEV: - { - ret = (int)physdev_to_xldev((unsigned short)data); - } - break; - default: - { ret = -EINVAL; - } - break; - } - + break; + } return ret; } diff --git a/xenolinux-2.4.22-sparse/fs/partitions/Config.in b/xenolinux-2.4.22-sparse/fs/partitions/Config.in deleted file mode 100644 index b9650de5c3..0000000000 --- a/xenolinux-2.4.22-sparse/fs/partitions/Config.in +++ /dev/null @@ -1,72 +0,0 @@ -# -# Partition configuration -# -bool 'Advanced partition selection' CONFIG_PARTITION_ADVANCED -if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then - bool ' Acorn partition support' CONFIG_ACORN_PARTITION - if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then -# bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA - bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS - bool ' Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS - bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC - bool ' RISCiX partition support' CONFIG_ACORN_PARTITION_RISCIX - fi - bool ' Alpha OSF partition support' CONFIG_OSF_PARTITION - bool ' Amiga partition table support' CONFIG_AMIGA_PARTITION - bool ' Atari partition table support' CONFIG_ATARI_PARTITION - if [ "$CONFIG_ARCH_S390" = "y" ]; then - bool ' IBM disk label and partition support' CONFIG_IBM_PARTITION - fi - bool ' Macintosh partition map support' CONFIG_MAC_PARTITION - bool ' Xeno partition support' CONFIG_XENO_PARTITION - bool ' PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION - if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then - bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL - bool ' Minix subpartition support' CONFIG_MINIX_SUBPARTITION - bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION - bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL - fi - dep_bool ' Windows Logical Disk Manager (Dynamic Disk) support (EXPERIMENTAL)' CONFIG_LDM_PARTITION $CONFIG_EXPERIMENTAL - if [ "$CONFIG_LDM_PARTITION" = "y" ]; then - bool ' Windows LDM extra logging' CONFIG_LDM_DEBUG - fi - bool ' SGI partition support' CONFIG_SGI_PARTITION - bool ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION - bool ' Sun partition tables support' CONFIG_SUN_PARTITION - bool ' EFI GUID Partition support' CONFIG_EFI_PARTITION -else - if [ "$CONFIG_ALPHA" = "y" ]; then - define_bool CONFIG_OSF_PARTITION y - fi - if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \ - "$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \ - "$CONFIG_SGI_IP27" != "y" ]; then - define_bool CONFIG_MSDOS_PARTITION y - fi - if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_AFFS_FS" = "y" ]; then - define_bool CONFIG_AMIGA_PARTITION y - fi - if [ "$CONFIG_MAC" = "y" ]; then - define_bool CONFIG_MAC_PARTITION y - fi - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - define_bool CONFIG_ACORN_PARTITION y - define_bool CONFIG_ACORN_PARTITION_ADFS y -# define_bool CONFIG_ACORN_PARTITION_CUMANA y - define_bool CONFIG_ACORN_PARTITION_ICS y - define_bool CONFIG_ACORN_PARTITION_POWERTEC y - define_bool CONFIG_ACORN_PARTITION_RISCIX y - fi - if [ "$CONFIG_ATARI" = "y" ]; then - define_bool CONFIG_ATARI_PARTITION y - fi - if [ "$CONFIG_SGI_IP22" = "y" -o "$CONFIG_SGI_IP27" = "y" ]; then - define_bool CONFIG_SGI_PARTITION y - fi - if [ "$CONFIG_DECSTATION" = "y" ]; then - define_bool CONFIG_ULTRIX_PARTITION y - fi - if [ "$CONFIG_SPARC32" = "y" -o "$CONFIG_SPARC64" = "y" ]; then - define_bool CONFIG_SUN_PARTITION y - fi -fi diff --git a/xenolinux-2.4.22-sparse/fs/partitions/Makefile b/xenolinux-2.4.22-sparse/fs/partitions/Makefile deleted file mode 100644 index 097e5ca17a..0000000000 --- a/xenolinux-2.4.22-sparse/fs/partitions/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# Makefile for the linux kernel. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... - -O_TARGET := partitions.o - -export-objs := check.o msdos.o - -obj-y := check.o - -obj-$(CONFIG_ACORN_PARTITION) += acorn.o -obj-$(CONFIG_XENO_PARTITION) += xeno.o -obj-$(CONFIG_AMIGA_PARTITION) += amiga.o -obj-$(CONFIG_ATARI_PARTITION) += atari.o -obj-$(CONFIG_MAC_PARTITION) += mac.o -obj-$(CONFIG_LDM_PARTITION) += ldm.o -obj-$(CONFIG_MSDOS_PARTITION) += msdos.o -obj-$(CONFIG_OSF_PARTITION) += osf.o -obj-$(CONFIG_SGI_PARTITION) += sgi.o -obj-$(CONFIG_SUN_PARTITION) += sun.o -obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o -obj-$(CONFIG_IBM_PARTITION) += ibm.o -obj-$(CONFIG_EFI_PARTITION) += efi.o - -include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.22-sparse/fs/partitions/check.c b/xenolinux-2.4.22-sparse/fs/partitions/check.c deleted file mode 100644 index e279aa8b93..0000000000 --- a/xenolinux-2.4.22-sparse/fs/partitions/check.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Code extracted from drivers/block/genhd.c - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - * - * We now have independent partition support from the - * block drivers, which allows all the partition code to - * be grouped in one location, and it to be mostly self - * contained. - * - * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl} - */ - -#include <linux/config.h> -#include <linux/fs.h> -#include <linux/genhd.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/blk.h> -#include <linux/init.h> -#include <linux/raid/md.h> - -#include "check.h" - -#include "acorn.h" -#include "amiga.h" -#include "atari.h" -#include "ldm.h" -#include "mac.h" -#include "msdos.h" -#include "osf.h" -#include "sgi.h" -#include "sun.h" -#include "ibm.h" -#include "ultrix.h" -#include "efi.h" -#include "xeno.h" - -extern int *blk_size[]; - -int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ - -static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = { -#ifdef CONFIG_XENO_PARTITION - xeno_partition, /* this must come first */ -#endif -#ifdef CONFIG_ACORN_PARTITION - acorn_partition, -#endif -#ifdef CONFIG_EFI_PARTITION - efi_partition, /* this must come before msdos */ -#endif -#ifdef CONFIG_LDM_PARTITION - ldm_partition, /* this must come before msdos */ -#endif -#ifdef CONFIG_MSDOS_PARTITION - msdos_partition, -#endif -#ifdef CONFIG_OSF_PARTITION - osf_partition, -#endif -#ifdef CONFIG_SUN_PARTITION - sun_partition, -#endif -#ifdef CONFIG_AMIGA_PARTITION - amiga_partition, -#endif -#ifdef CONFIG_ATARI_PARTITION - atari_partition, -#endif -#ifdef CONFIG_MAC_PARTITION - mac_partition, -#endif -#ifdef CONFIG_SGI_PARTITION - sgi_partition, -#endif -#ifdef CONFIG_ULTRIX_PARTITION - ultrix_partition, -#endif -#ifdef CONFIG_IBM_PARTITION - ibm_partition, -#endif - NULL -}; - -/* - * This is ucking fugly but its probably the best thing for 2.4.x - * Take it as a clear reminder that: 1) we should put the device name - * generation in the object kdev_t points to in 2.5. - * and 2) ioctls better work on half-opened devices. - */ - -#ifdef CONFIG_ARCH_S390 -int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL; -int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp, - unsigned int no, unsigned long data); -EXPORT_SYMBOL(genhd_dasd_name); -EXPORT_SYMBOL(genhd_dasd_ioctl); -#endif - -/* - * disk_name() is used by partition check code and the md driver. - * It formats the devicename of the indicated disk into - * the supplied buffer (of size at least 32), and returns - * a pointer to that same buffer (for convenience). - */ - -char *disk_name (struct gendisk *hd, int minor, char *buf) -{ - const char *maj = hd->major_name; - unsigned int unit = (minor >> hd->minor_shift); - unsigned int part = (minor & ((1 << hd->minor_shift) -1 )); - - if ((unit < hd->nr_real) && hd->part[minor].de) { - int pos; - - pos = devfs_generate_path (hd->part[minor].de, buf, 64); - if (pos >= 0) - return buf + pos; - } - -#ifdef CONFIG_ARCH_S390 - if (genhd_dasd_name - && genhd_dasd_name (buf, unit, part, hd) == 0) - return buf; -#endif - /* - * IDE devices use multiple major numbers, but the drives - * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}.. - * This requires special handling here. - */ - switch (hd->major) { - case IDE9_MAJOR: - unit += 2; - case IDE8_MAJOR: - unit += 2; - case IDE7_MAJOR: - unit += 2; - case IDE6_MAJOR: - unit += 2; - case IDE5_MAJOR: - unit += 2; - case IDE4_MAJOR: - unit += 2; - case IDE3_MAJOR: - unit += 2; - case IDE2_MAJOR: - unit += 2; - case IDE1_MAJOR: - unit += 2; - case IDE0_MAJOR: - maj = "hd"; - break; - case MD_MAJOR: - sprintf(buf, "%s%d", maj, unit); - return buf; - } - if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) { - unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16; - if (unit+'a' > 'z') { - unit -= 26; - sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26); - if (part) - sprintf(buf + 4, "%d", part); - return buf; - } - } - if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) { - int ctlr = hd->major - COMPAQ_SMART2_MAJOR; - if (part == 0) - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit); - else - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part); - return buf; - } - if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) { - int ctlr = hd->major - COMPAQ_CISS_MAJOR; - if (part == 0) - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit); - else - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part); - return buf; - } - if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) { - int ctlr = hd->major - DAC960_MAJOR; - if (part == 0) - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit); - else - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part); - return buf; - } - if (hd->major == ATARAID_MAJOR) { - int disk = minor >> hd->minor_shift; - int part = minor & (( 1 << hd->minor_shift) - 1); - if (part == 0) - sprintf(buf, "%s/d%d", maj, disk); - else - sprintf(buf, "%s/d%dp%d", maj, disk, part); - return buf; - } - if (part) - sprintf(buf, "%s%c%d", maj, unit+'a', part); - else - sprintf(buf, "%s%c", maj, unit+'a'); - return buf; -} - -/* - * Add a partitions details to the devices partition description. - */ -void add_gd_partition(struct gendisk *hd, int minor, int start, int size) -{ -#ifndef CONFIG_DEVFS_FS - char buf[40]; -#endif - - hd->part[minor].start_sect = start; - hd->part[minor].nr_sects = size; -#ifdef CONFIG_DEVFS_FS - printk(" p%d", (minor & ((1 << hd->minor_shift) - 1))); -#else - if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) || - (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7)) - printk(" p%d", (minor & ((1 << hd->minor_shift) - 1))); - else - printk(" %s", disk_name(hd, minor, buf)); -#endif -} - -static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor) -{ - devfs_handle_t de = NULL; - static int first_time = 1; - unsigned long first_sector; - struct block_device *bdev; - char buf[64]; - int i; - - if (first_time) - printk(KERN_INFO "Partition check:\n"); - first_time = 0; - first_sector = hd->part[MINOR(dev)].start_sect; - - /* - * This is a kludge to allow the partition check to be - * skipped for specific drives (e.g. IDE CD-ROM drives) - */ - if ((int)first_sector == -1) { - hd->part[MINOR(dev)].start_sect = 0; - return; - } - - if (hd->de_arr) - de = hd->de_arr[MINOR(dev) >> hd->minor_shift]; - i = devfs_generate_path (de, buf, sizeof buf); - if (i >= 0) - printk(KERN_INFO " /dev/%s:", buf + i); - else - printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf)); - bdev = bdget(kdev_t_to_nr(dev)); - bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9; - bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev)); - for (i = 0; check_part[i]; i++) { - int res; - res = check_part[i](hd, bdev, first_sector, first_part_minor); - if (res) { - if (res < 0 && warn_no_part) - printk(" unable to read partition table\n"); - goto setup_devfs; - } - } - - printk(" unknown partition table\n"); -setup_devfs: - invalidate_bdev(bdev, 1); - truncate_inode_pages(bdev->bd_inode->i_mapping, 0); - bdput(bdev); - i = first_part_minor - 1; - devfs_register_partitions (hd, i, hd->sizes ? 0 : 1); -} - -#ifdef CONFIG_DEVFS_FS -static void devfs_register_partition (struct gendisk *dev, int minor, int part) -{ - int devnum = minor >> dev->minor_shift; - devfs_handle_t dir; - unsigned int devfs_flags = DEVFS_FL_DEFAULT; - char devname[16]; - - if (dev->part[minor + part].de) return; - dir = devfs_get_parent (dev->part[minor].de); - if (!dir) return; - if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) - devfs_flags |= DEVFS_FL_REMOVABLE; - sprintf (devname, "part%d", part); - dev->part[minor + part].de = - devfs_register (dir, devname, devfs_flags, - dev->major, minor + part, - S_IFBLK | S_IRUSR | S_IWUSR, - dev->fops, NULL); -} - -static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; - -static void devfs_register_disc (struct gendisk *dev, int minor) -{ - int pos = 0; - int devnum = minor >> dev->minor_shift; - devfs_handle_t dir, slave; - unsigned int devfs_flags = DEVFS_FL_DEFAULT; - char dirname[64], symlink[16]; - static devfs_handle_t devfs_handle; - - if (dev->part[minor].de) return; - if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) - devfs_flags |= DEVFS_FL_REMOVABLE; - if (dev->de_arr) { - dir = dev->de_arr[devnum]; - if (!dir) /* Aware driver wants to block disc management */ - return; - pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3); - if (pos < 0) return; - strncpy (dirname + pos, "../", 3); - } - else { - /* Unaware driver: construct "real" directory */ - sprintf (dirname, "../%s/disc%d", dev->major_name, devnum); - dir = devfs_mk_dir (NULL, dirname + 3, NULL); - } - if (!devfs_handle) - devfs_handle = devfs_mk_dir (NULL, "discs", NULL); - dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace); - sprintf (symlink, "disc%d", dev->part[minor].number); - devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT, - dirname + pos, &slave, NULL); - dev->part[minor].de = - devfs_register (dir, "disc", devfs_flags, dev->major, minor, - S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); - devfs_auto_unregister (dev->part[minor].de, slave); - if (!dev->de_arr) - devfs_auto_unregister (slave, dir); -} -#endif /* CONFIG_DEVFS_FS */ - -void devfs_register_partitions (struct gendisk *dev, int minor, int unregister) -{ -#ifdef CONFIG_DEVFS_FS - int part; - - if (!unregister) - devfs_register_disc (dev, minor); - for (part = 1; part < dev->max_p; part++) { - if ( unregister || (dev->part[minor].nr_sects < 1) || - (dev->part[part + minor].nr_sects < 1) ) { - devfs_unregister (dev->part[part + minor].de); - dev->part[part + minor].de = NULL; - continue; - } - devfs_register_partition (dev, minor, part); - } - if (unregister) { - devfs_unregister (dev->part[minor].de); - dev->part[minor].de = NULL; - devfs_dealloc_unique_number (&disc_numspace, - dev->part[minor].number); - } -#endif /* CONFIG_DEVFS_FS */ -} - -/* - * This function will re-read the partition tables for a given device, - * and set things back up again. There are some important caveats, - * however. You must ensure that no one is using the device, and no one - * can start using the device while this function is being executed. - * - * Much of the cleanup from the old partition tables should have already been - * done - */ - -void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors, - struct block_device_operations *ops, long size) -{ - if (!gdev) - return; - grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size); -} - -void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size) -{ - int i; - int first_minor = drive << dev->minor_shift; - int end_minor = first_minor + dev->max_p; - - if(!dev->sizes) - blk_size[dev->major] = NULL; - - dev->part[first_minor].nr_sects = size; - /* No such device or no minors to use for partitions */ - if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) ) - devfs_register_partitions (dev, first_minor, 0); - if (!size || minors == 1) - return; - - if (dev->sizes) { - dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9); - for (i = first_minor + 1; i < end_minor; i++) - dev->sizes[i] = 0; - } - blk_size[dev->major] = dev->sizes; - check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor); - - /* - * We need to set the sizes array before we will be able to access - * any of the partitions on this device. - */ - if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ - for (i = first_minor; i < end_minor; i++) - dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); - } -} - -unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p) -{ - struct address_space *mapping = bdev->bd_inode->i_mapping; - int sect = PAGE_CACHE_SIZE / 512; - struct page *page; - - page = read_cache_page(mapping, n/sect, - (filler_t *)mapping->a_ops->readpage, NULL); - if (!IS_ERR(page)) { - wait_on_page(page); - if (!Page_Uptodate(page)) - goto fail; - if (PageError(page)) - goto fail; - p->v = page; - return (unsigned char *)page_address(page) + 512 * (n % sect); -fail: - page_cache_release(page); - } - p->v = NULL; - return NULL; -} diff --git a/xenolinux-2.4.22-sparse/fs/partitions/xeno.c b/xenolinux-2.4.22-sparse/fs/partitions/xeno.c deleted file mode 100644 index a3b236b8cb..0000000000 --- a/xenolinux-2.4.22-sparse/fs/partitions/xeno.c +++ /dev/null @@ -1,94 +0,0 @@ - -#include <linux/kernel.h> -#include <asm/hypervisor.h> -#include <linux/fs.h> -#include <linux/blk.h> -#include <linux/slab.h> -#include <linux/genhd.h> -#include <asm/hypervisor-ifs/vbd.h> -#include <linux/pagemap.h> - -#include "check.h" -#include "xeno.h" - -extern int xenolinux_control_msg(int operration, char *buffer, int size); -extern unsigned short xldev_to_physdev(kdev_t xldev); - -/* Grab the physdisk partitions list from the hypervisor. */ -int xeno_partition(struct gendisk *hd, - struct block_device *bdev, - unsigned long first_sec, - int first_part_minor) -{ - physdisk_probebuf_t *buf; - int i, minor; - - /* Privileged domains can read partition info themselves. */ - if ( start_info.flags & SIF_PRIVILEGED ) - return 0; - - /* This only deals with raw/direct devices (IDE & SCSI). */ - switch ( xldev_to_physdev(bdev->bd_dev) & XENDEV_TYPE_MASK ) - { - case XENDEV_IDE: - case XENDEV_SCSI: - break; - default: - return 0; - } - - if ( (buf = kmalloc(sizeof(*buf), GFP_KERNEL)) == NULL ) - return -ENOMEM; - - buf->domain = start_info.dom_id; - buf->start_ind = 0; - buf->n_aces = PHYSDISK_MAX_ACES_PER_REQUEST; - - xenolinux_control_msg(XEN_BLOCK_PHYSDEV_PROBE, (char *)buf, - sizeof(*buf)); - - if ( buf->n_aces == PHYSDISK_MAX_ACES_PER_REQUEST ) - printk(KERN_ALERT "Too many returns for xeno partition parser\n"); - - /* Check for access to whole disk, allowing direct p.t. access. */ - for ( i = 0; i < buf->n_aces; i++ ) - { - if ( (buf->entries[i].device == xldev_to_physdev(bdev->bd_dev)) && - (buf->entries[i].partition == 0) ) - { - if ( !(buf->entries[i].mode & PHYSDISK_MODE_W) ) - { - if ( !(buf->entries[i].mode & PHYSDISK_MODE_R) ) - continue; - for ( i = 0; i < hd->max_p; i++ ) - set_device_ro(bdev->bd_dev + i, 1); - } - kfree(buf); - return 0; - } - } - - /* No direct access so trawl through the access lists instead. */ - for ( i = 0; i < buf->n_aces; i++ ) - { - if (buf->entries[i].device != xldev_to_physdev(bdev->bd_dev)) - continue; - if ( !(buf->entries[i].mode & PHYSDISK_MODE_W) ) - { - if ( !(buf->entries[i].mode & PHYSDISK_MODE_R) ) - continue; - set_device_ro(bdev->bd_dev + buf->entries[i].partition, 1); - } - minor = buf->entries[i].partition + first_part_minor - 1; - add_gd_partition(hd, - minor, - buf->entries[i].start_sect, - buf->entries[i].n_sectors); - } - - kfree(buf); - - printk("\n"); - - return 1; -} diff --git a/xenolinux-2.4.22-sparse/fs/partitions/xeno.h b/xenolinux-2.4.22-sparse/fs/partitions/xeno.h deleted file mode 100644 index 52cecb30cf..0000000000 --- a/xenolinux-2.4.22-sparse/fs/partitions/xeno.h +++ /dev/null @@ -1,2 +0,0 @@ -int xeno_partition(struct gendisk *hd, struct block_device *bdev, - unsigned long fsec, int first_part_minor); diff --git a/xenolinux-2.4.22-sparse/include/asm-xeno/proc_cmd.h b/xenolinux-2.4.22-sparse/include/asm-xeno/proc_cmd.h index 66308397eb..2fddd2c243 100644 --- a/xenolinux-2.4.22-sparse/include/asm-xeno/proc_cmd.h +++ b/xenolinux-2.4.22-sparse/include/asm-xeno/proc_cmd.h @@ -24,9 +24,5 @@ typedef struct privcmd_blkmsg _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t)) #define IOCTL_PRIVCMD_BLKMSG \ _IOC(_IOC_NONE, 'P', 1, sizeof(privcmd_blkmsg_t)) -#define IOCTL_PRIVCMD_LINDEV_TO_XENDEV \ - _IOC(_IOC_NONE, 'P', 2, sizeof(unsigned short)) -#define IOCTL_PRIVCMD_XENDEV_TO_LINDEV \ - _IOC(_IOC_NONE, 'P', 3, sizeof(unsigned short)) #endif /* __PROC_CMD_H__ */ |