From 07486ec49f025987359499eb2f06f0b794994d42 Mon Sep 17 00:00:00 2001 From: "kaf24@labyrinth.cl.cam.ac.uk" Date: Fri, 7 Mar 2003 11:29:57 +0000 Subject: bitkeeper revision 1.111 (3e6882b5ERWU6qPXXUlLkYvavej4FQ) xl_segment.c, xl_scsi.c, xl_ide.c, xl_block.h, xl_block.c: Partition tables are now revalidated on demand for all XL blkdevs (IDE, SCSI, and virtual). --- .../arch/xeno/drivers/block/xl_block.c | 72 ++++++++++++++++------ .../arch/xeno/drivers/block/xl_block.h | 10 +++ .../arch/xeno/drivers/block/xl_ide.c | 11 +++- .../arch/xeno/drivers/block/xl_scsi.c | 7 ++- .../arch/xeno/drivers/block/xl_segment.c | 7 ++- 5 files changed, 84 insertions(+), 23 deletions(-) (limited to 'xenolinux-2.4.21-pre4-sparse') diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c index 985fda050f..567af806b5 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c @@ -34,7 +34,7 @@ static int nr_pending; /* Convert from a XenoLinux major device to the Xen-level 'physical' device */ static inline unsigned short xldev_to_physdev(kdev_t xldev) { - unsigned short physdev; + unsigned short physdev = 0; switch ( MAJOR(xldev) ) { @@ -49,11 +49,10 @@ static inline unsigned short xldev_to_physdev(kdev_t xldev) case XLVIRT_MAJOR: physdev = XENDEV_VIRTUAL; break; - - default: - BUG(); } + if ( physdev == 0 ) BUG(); + physdev += (MINOR(xldev) >> PARTN_SHIFT); return physdev; @@ -84,23 +83,36 @@ static inline struct gendisk *xldev_to_gendisk(kdev_t xldev) 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); +} + + int xenolinux_block_open(struct inode *inode, struct file *filep) { - DPRINTK("xenolinux_block_open\n"); + xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); + disk->usage++; + DPRINTK("xenolinux_block_open\n"); return 0; } + int xenolinux_block_release(struct inode *inode, struct file *filep) { + xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); + disk->usage--; DPRINTK("xenolinux_block_release\n"); return 0; } - int xenolinux_block_ioctl(struct inode *inode, struct file *filep, unsigned command, unsigned long argument) { + kdev_t dev = inode->i_rdev; struct hd_geometry *geo = (struct hd_geometry *)argument; struct gendisk *gd; struct hd_struct *part; @@ -112,10 +124,10 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep, if (!inode) return -EINVAL; DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", - command, (long) argument, inode->i_rdev); + command, (long) argument, dev); - gd = xldev_to_gendisk(inode->i_rdev); - part = &gd->part[MINOR(inode->i_rdev)]; + gd = xldev_to_gendisk(dev); + part = &gd->part[MINOR(dev)]; switch ( command ) { @@ -125,25 +137,26 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep, case BLKRRPART: /* re-read partition table */ DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART); - break; + if ( !capable(CAP_SYS_ADMIN) ) return -EACCES; + return xenolinux_block_revalidate(dev); case BLKSSZGET: - switch ( MAJOR(inode->i_rdev) ) + switch ( MAJOR(dev) ) { case XLIDE_MAJOR: DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlide_hwsect(MINOR(inode->i_rdev))); - return xlide_hwsect(MINOR(inode->i_rdev)); + xlide_hwsect(MINOR(dev))); + return xlide_hwsect(MINOR(dev)); case XLSCSI_MAJOR: DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlscsi_hwsect(MINOR(inode->i_rdev))); - return xlscsi_hwsect(MINOR(inode->i_rdev)); + xlscsi_hwsect(MINOR(dev))); + return xlscsi_hwsect(MINOR(dev)); case XLVIRT_MAJOR: DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlsegment_hwsect(MINOR(inode->i_rdev))); - return xlsegment_hwsect(MINOR(inode->i_rdev)); + xlsegment_hwsect(MINOR(dev))); + return xlsegment_hwsect(MINOR(dev)); default: printk(KERN_ALERT "BLKSSZGET ioctl() on bogus disk!\n"); @@ -202,10 +215,33 @@ int xenolinux_block_check(kdev_t dev) int xenolinux_block_revalidate(kdev_t dev) { - DPRINTK("xenolinux_block_revalidate\n"); + struct gendisk *gd = xldev_to_gendisk(dev); + xl_disk_t *disk = xldev_to_xldisk(dev); + unsigned long flags; + int i; + + spin_lock_irqsave(&io_request_lock, flags); + if ( disk->usage > 1 ) + { + spin_unlock_irqrestore(&io_request_lock, flags); + return -EBUSY; + } + spin_unlock_irqrestore(&io_request_lock, flags); + + for ( i = 0; i < (1 << PARTN_SHIFT); i++ ) + { + invalidate_device(dev + i, 1); + gd->part[dev + i].start_sect = 0; + gd->part[dev + i].nr_sects = 0; + } + + grok_partitions(gd, MINOR(dev) >> PARTN_SHIFT, + 1 << PARTN_SHIFT, disk->capacity); + return 0; } + /* * hypervisor_request * diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.h b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.h index 2140b30d7b..17ca09d9f2 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.h +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.h @@ -35,6 +35,16 @@ #define DPRINTK_IOCTL(_f, _a...) ((void)0) #endif +/* + * We have one of these per XL-IDE, XL-SCSI, and XL-VIRT device. + * They hang in an array off the gendisk structure. We may end up putting + * all kinds of interesting stuff here :-) + */ +typedef struct xl_disk { + int usage; + unsigned long capacity; +} xl_disk_t; + /* Generic layer. */ extern int xenolinux_control_msg(int operration, char *buffer); extern int xenolinux_block_open(struct inode *inode, struct file *filep); diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c index f07c54dcb4..9d6ef64c75 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c @@ -78,6 +78,8 @@ int xlide_init(xen_disk_info_t *xdi) for ( i = 0; i < xdi->count; i++ ) if ( xdi->disks[i].type == XEN_DISK_IDE ) units++; + if ( units == 0 ) return 0; + /* Construct an appropriate gendisk structure. */ minors = units * (1<minor_shift = IDE_PARTN_BITS; gd->max_p = 1<nr_real = units; - gd->real_devices = NULL; + 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); @@ -97,14 +99,17 @@ int xlide_init(xen_disk_info_t *xdi) 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); xlide_gendisk = gd; add_gendisk(gd); - + /* Now register each disk in turn. */ disk = 0; for ( i = 0; i < xdi->count; i++ ) { if ( xdi->disks[i].type != XEN_DISK_IDE ) continue; + ((xl_disk_t *)gd->real_devices)[disk].capacity = + xdi->disks[i].capacity; register_disk(gd, MKDEV(XLIDE_MAJOR, disk<disks[i].capacity); disk++; } - + printk(KERN_ALERT "XenoLinux Virtual IDE Device Driver installed [device: %d]\n", XLIDE_MAJOR); diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c index ddbd22d5f1..68566799bd 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c @@ -79,6 +79,8 @@ int xlscsi_init(xen_disk_info_t *xdi) for ( i = 0; i < xdi->count; i++ ) if ( xdi->disks[i].type == XEN_DISK_SCSI ) units++; + if ( units == 0 ) return 0; + /* Construct an appropriate gendisk structure. */ minors = units * (1<minor_shift = SCSI_PARTN_BITS; gd->max_p = 1<nr_real = units; - gd->real_devices = NULL; + 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); @@ -98,6 +100,7 @@ int xlscsi_init(xen_disk_info_t *xdi) 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); @@ -106,6 +109,8 @@ int xlscsi_init(xen_disk_info_t *xdi) for ( i = 0; i < xdi->count; i++ ) { if ( xdi->disks[i].type != XEN_DISK_SCSI ) continue; + ((xl_disk_t *)gd->real_devices)[disk].capacity = + xdi->disks[i].capacity; register_disk(gd, MKDEV(XLSCSI_MAJOR, disk<count; i++ ) if ( xdi->disks[i].type == XEN_DISK_VIRTUAL ) units++; + if ( units == 0 ) return 0; + /* Construct an appropriate gendisk structure. */ minors = units * (1<minor_shift = VIRT_PARTN_BITS; gd->max_p = 1<nr_real = units; - gd->real_devices = NULL; + gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL); gd->next = NULL; gd->fops = &xlsegment_block_fops; gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL); @@ -115,6 +117,7 @@ int __init xlseg_init(void) 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); xlsegment_gendisk = gd; add_gendisk(gd); @@ -123,6 +126,8 @@ int __init xlseg_init(void) for ( i = 0; i < xdi->count; i++ ) { if ( xdi->disks[i].type != XEN_DISK_VIRTUAL ) continue; + ((xl_disk_t *)gd->real_devices)[disk].capacity = + xdi->disks[i].capacity; register_disk(gd, MKDEV(XLVIRT_MAJOR, disk<