ia64/xen-unstable
changeset 1002:b27a29e3c9ce
bitkeeper revision 1.649 (3fdf2aeaeVXAAcKlXMdFTCQuwOYD_g)
xl_vbd.c, xl_block.h, xl_block.c:
Fixes to Xenolinux blkdev code.
xl_vbd.c, xl_block.h, xl_block.c:
Fixes to Xenolinux blkdev code.
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Tue Dec 16 15:55:22 2003 +0000 (2003-12-16) |
parents | 70a2962f5aeb |
children | ebd0aaef31e3 8e10a7fe0e35 |
files | xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c |
line diff
1.1 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c Fri Dec 12 16:43:28 2003 +0000 1.2 +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c Tue Dec 16 15:55:22 2003 +0000 1.3 @@ -58,7 +58,7 @@ static inline void signal_requests_to_xe 1.4 1.5 static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev) 1.6 { 1.7 - struct gendisk *gd = xldev_to_gendisk(xldev); 1.8 + struct gendisk *gd = get_gendisk(xldev); 1.9 return (xl_disk_t *)gd->real_devices + 1.10 (MINOR(xldev) >> gd->minor_shift); 1.11 } 1.12 @@ -67,26 +67,37 @@ static inline xl_disk_t *xldev_to_xldisk 1.13 int xenolinux_block_open(struct inode *inode, struct file *filep) 1.14 { 1.15 short xldev = inode->i_rdev; 1.16 - struct gendisk *gd = xldev_to_gendisk(xldev); 1.17 + struct gendisk *gd = get_gendisk(xldev); 1.18 xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); 1.19 short minor = MINOR(xldev); 1.20 1.21 - if(!gd->part[minor].nr_sects) { 1.22 - /* Device either doesn't exist, or has zero capacity; we use 1.23 - a few cheesy heuristics to return the relevant error code */ 1.24 - if(disk->capacity || (minor & (gd->max_p - 1))) { 1.25 - // we have a real device, but no such partition, or we just 1.26 - // have a partition number so guess this is the problem 1.27 - return -ENXIO; // no such device or address 1.28 - } else if (gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) { 1.29 - // this is a removable device => assume that media is missing 1.30 - return -ENOMEDIUM; // media not present (this is a guess) 1.31 - } else 1.32 - // just go for the general 'no such device' error 1.33 - return -ENODEV; // no such device 1.34 + if ( gd->part[minor].nr_sects == 0 ) 1.35 + { 1.36 + /* 1.37 + * Device either doesn't exist, or has zero capacity; we use a few 1.38 + * cheesy heuristics to return the relevant error code 1.39 + */ 1.40 + if ( (gd->sizes[minor >> gd->minor_shift] != 0) || 1.41 + ((minor & (gd->max_p - 1)) != 0) ) 1.42 + { 1.43 + /* 1.44 + * We have a real device, but no such partition, or we just have a 1.45 + * partition number so guess this is the problem. 1.46 + */ 1.47 + return -ENXIO; /* no such device or address */ 1.48 + } 1.49 + else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE ) 1.50 + { 1.51 + /* This is a removable device => assume that media is missing. */ 1.52 + return -ENOMEDIUM; /* media not present (this is a guess) */ 1.53 + } 1.54 + else 1.55 + { 1.56 + /* Just go for the general 'no such device' error. */ 1.57 + return -ENODEV; /* no such device */ 1.58 + } 1.59 } 1.60 1.61 - 1.62 disk->usage++; 1.63 DPRINTK("xenolinux_block_open\n"); 1.64 return 0; 1.65 @@ -103,7 +114,7 @@ int xenolinux_block_release(struct inode 1.66 1.67 1.68 int xenolinux_block_ioctl(struct inode *inode, struct file *filep, 1.69 - unsigned command, unsigned long argument) 1.70 + unsigned command, unsigned long argument) 1.71 { 1.72 kdev_t dev = inode->i_rdev; 1.73 struct hd_geometry *geo = (struct hd_geometry *)argument; 1.74 @@ -115,21 +126,21 @@ int xenolinux_block_ioctl(struct inode * 1.75 DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", 1.76 command, (long) argument, dev); 1.77 1.78 - gd = xldev_to_gendisk(dev); 1.79 + gd = get_gendisk(dev); 1.80 part = &gd->part[MINOR(dev)]; 1.81 1.82 switch ( command ) 1.83 { 1.84 case BLKGETSIZE: 1.85 DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); 1.86 - return put_user(part->nr_sects, (unsigned long *) argument); 1.87 + return put_user(part->nr_sects, (unsigned long *) argument); 1.88 1.89 case BLKRRPART: /* re-read partition table */ 1.90 DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART); 1.91 return xenolinux_block_revalidate(dev); 1.92 1.93 case BLKSSZGET: 1.94 - return hardsect_size[MAJOR(dev)][MINOR(dev)]; 1.95 + return hardsect_size[MAJOR(dev)][MINOR(dev)]; 1.96 1.97 case BLKBSZGET: /* get block size */ 1.98 DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET); 1.99 @@ -137,35 +148,35 @@ int xenolinux_block_ioctl(struct inode * 1.100 1.101 case BLKBSZSET: /* set block size */ 1.102 DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET); 1.103 - break; 1.104 + break; 1.105 1.106 case BLKRASET: /* set read-ahead */ 1.107 DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET); 1.108 - break; 1.109 + break; 1.110 1.111 case BLKRAGET: /* get read-ahead */ 1.112 DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET); 1.113 - break; 1.114 + break; 1.115 1.116 case HDIO_GETGEO: 1.117 /* note: these values are complete garbage */ 1.118 DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO); 1.119 - if (!argument) return -EINVAL; 1.120 - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; 1.121 - if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; 1.122 - if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; 1.123 - if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT; 1.124 - return 0; 1.125 + if (!argument) return -EINVAL; 1.126 + if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; 1.127 + if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; 1.128 + if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; 1.129 + if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT; 1.130 + return 0; 1.131 1.132 case HDIO_GETGEO_BIG: 1.133 /* note: these values are complete garbage */ 1.134 DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG); 1.135 - if (!argument) return -EINVAL; 1.136 - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; 1.137 - if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; 1.138 - if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; 1.139 - if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT; 1.140 - return 0; 1.141 + if (!argument) return -EINVAL; 1.142 + if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; 1.143 + if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; 1.144 + if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; 1.145 + if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT; 1.146 + return 0; 1.147 1.148 case CDROMMULTISESSION: 1.149 DPRINTK("FIXME: support multisession CDs later\n"); 1.150 @@ -175,7 +186,7 @@ int xenolinux_block_ioctl(struct inode * 1.151 1.152 default: 1.153 printk("ioctl %08x not supported by xl_block\n", command); 1.154 - return -ENOSYS; 1.155 + return -ENOSYS; 1.156 } 1.157 1.158 return 0; 1.159 @@ -190,13 +201,20 @@ int xenolinux_block_check(kdev_t dev) 1.160 1.161 int xenolinux_block_revalidate(kdev_t dev) 1.162 { 1.163 - struct gendisk *gd = xldev_to_gendisk(dev); 1.164 + struct gendisk *gd = get_gendisk(dev); 1.165 xl_disk_t *disk = xldev_to_xldisk(dev); 1.166 - unsigned long flags; 1.167 + unsigned long flags, capacity = gd->part[MINOR(dev)].nr_sects; 1.168 int i, disk_nr = MINOR(dev) >> gd->minor_shift; 1.169 1.170 DPRINTK("xenolinux_block_revalidate: %d\n", dev); 1.171 1.172 + /* 1.173 + * We didn't construct this VBD by reading a partition table. This 1.174 + * function can only do bad things to us. 1.175 + */ 1.176 + if ( capacity == 0 ) 1.177 + return -EINVAL; 1.178 + 1.179 spin_lock_irqsave(&io_request_lock, flags); 1.180 if ( disk->usage > 1 ) 1.181 { 1.182 @@ -212,27 +230,9 @@ int xenolinux_block_revalidate(kdev_t de 1.183 gd->part[MINOR(dev+i)].nr_sects = 0; 1.184 } 1.185 1.186 -#if 0 1.187 - /* VBDs can change under our feet. Check if that has happened. */ 1.188 - if ( MAJOR(dev) == XLVIRT_MAJOR ) 1.189 - { 1.190 - xen_disk_info_t *xdi = kmalloc(sizeof(*xdi), GFP_KERNEL); 1.191 - if ( xdi != NULL ) 1.192 - { 1.193 - memset(xdi, 0, sizeof(*xdi)); 1.194 - xenolinux_control_msg(XEN_BLOCK_PROBE, 1.195 - (char *)xdi, sizeof(*xdi)); 1.196 - for ( i = 0; i < xdi->count; i++ ) 1.197 - if ( IS_VIRTUAL_XENDEV(xdi->disks[i].device) && 1.198 - ((xdi->disks[i].device & XENDEV_IDX_MASK) == disk_nr) ) 1.199 - ((xl_disk_t *)gd->real_devices)[disk_nr].capacity = 1.200 - xdi->disks[i].capacity; 1.201 - kfree(xdi); 1.202 - } 1.203 - } 1.204 -#endif 1.205 + /* XXX Should perhaps revalidate VBDs here */ 1.206 1.207 - grok_partitions(gd, disk_nr, gd->nr_real, disk->capacity); 1.208 + grok_partitions(gd, disk_nr, gd->nr_real, capacity); 1.209 1.210 return 0; 1.211 } 1.212 @@ -271,14 +271,12 @@ static int hypervisor_request(unsigned l 1.213 1.214 case XEN_BLOCK_READ: 1.215 case XEN_BLOCK_WRITE: 1.216 - 1.217 - /* Get the appropriate gendisk */ 1.218 - gd = xldev_to_gendisk(device); 1.219 + gd = get_gendisk(device); 1.220 1.221 - /* Update the sector_number we'll pass down as appropriate; note 1.222 - that we could sanity check that resulting sector will be in 1.223 - this partition, but this will happen in xen anyhow */ 1.224 - sector_number += gd->part[MINOR(device)].start_sect; 1.225 + /* Update the sector_number we'll pass down as appropriate; note 1.226 + that we could sanity check that resulting sector will be in 1.227 + this partition, but this will happen in xen anyhow */ 1.228 + sector_number += gd->part[MINOR(device)].start_sect; 1.229 1.230 if ( (sg_operation == operation) && 1.231 (sg_dev == device) && 1.232 @@ -339,9 +337,9 @@ void do_xlblk_request(request_queue_t *r 1.233 1.234 while ( !rq->plugged && !list_empty(&rq->queue_head)) 1.235 { 1.236 - if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) 1.237 - goto out; 1.238 - 1.239 + if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) 1.240 + goto out; 1.241 + 1.242 DPRINTK("do_xlblk_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n", 1.243 req, req->cmd, req->sector, 1.244 req->current_nr_sectors, req->nr_sectors, req->bh); 1.245 @@ -351,11 +349,11 @@ void do_xlblk_request(request_queue_t *r 1.246 if ((rw != READ) && (rw != WRITE)) 1.247 panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw); 1.248 1.249 - req->errors = 0; 1.250 + req->errors = 0; 1.251 1.252 bh = req->bh; 1.253 while ( bh != NULL ) 1.254 - { 1.255 + { 1.256 next_bh = bh->b_reqnext; 1.257 bh->b_reqnext = NULL; 1.258 1.259 @@ -364,12 +362,12 @@ void do_xlblk_request(request_queue_t *r 1.260 (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 1.261 bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev); 1.262 1.263 - if(full) { 1.264 + if(full) { 1.265 1.266 - bh->b_reqnext = next_bh; 1.267 - pending_queues[nr_pending++] = rq; 1.268 - if ( nr_pending >= MAX_PENDING ) BUG(); 1.269 - goto out; 1.270 + bh->b_reqnext = next_bh; 1.271 + pending_queues[nr_pending++] = rq; 1.272 + if ( nr_pending >= MAX_PENDING ) BUG(); 1.273 + goto out; 1.274 1.275 } 1.276 1.277 @@ -430,15 +428,15 @@ static void xlblk_response_int(int irq, 1.278 if ( state == STATE_CLOSED ) 1.279 return; 1.280 1.281 - spin_lock_irqsave(&io_request_lock, flags); 1.282 + spin_lock_irqsave(&io_request_lock, flags); 1.283 1.284 for ( i = resp_cons; 1.285 - i != blk_ring->resp_prod; 1.286 - i = BLK_RING_INC(i) ) 1.287 + i != blk_ring->resp_prod; 1.288 + i = BLK_RING_INC(i) ) 1.289 { 1.290 - blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp; 1.291 - switch (bret->operation) 1.292 - { 1.293 + blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp; 1.294 + switch (bret->operation) 1.295 + { 1.296 case XEN_BLOCK_READ: 1.297 case XEN_BLOCK_WRITE: 1.298 if ( bret->status ) 1.299 @@ -452,11 +450,11 @@ static void xlblk_response_int(int irq, 1.300 bh->b_reqnext = NULL; 1.301 bh->b_end_io(bh, !bret->status); 1.302 } 1.303 - break; 1.304 - 1.305 + break; 1.306 + 1.307 default: 1.308 BUG(); 1.309 - } 1.310 + } 1.311 } 1.312 1.313 resp_cons = i; 1.314 @@ -501,8 +499,8 @@ int __init xlblk_init(void) 1.315 SA_SAMPLE_RANDOM, "blkdev", NULL); 1.316 if ( error ) 1.317 { 1.318 - printk(KERN_ALERT "Could not allocate receive interrupt\n"); 1.319 - goto fail; 1.320 + printk(KERN_ALERT "Could not allocate receive interrupt\n"); 1.321 + goto fail; 1.322 } 1.323 1.324 /* Setup our [empty] disk information structure */
2.1 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h Fri Dec 12 16:43:28 2003 +0000 2.2 +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h Tue Dec 16 15:55:22 2003 +0000 2.3 @@ -47,7 +47,6 @@ 2.4 */ 2.5 typedef struct xl_disk { 2.6 int usage; 2.7 - unsigned long capacity; 2.8 } xl_disk_t; 2.9 2.10 /* Generic layer. */ 2.11 @@ -55,7 +54,7 @@ extern int xenolinux_control_msg(int ope 2.12 extern int xenolinux_block_open(struct inode *inode, struct file *filep); 2.13 extern int xenolinux_block_release(struct inode *inode, struct file *filep); 2.14 extern int xenolinux_block_ioctl(struct inode *inode, struct file *filep, 2.15 - unsigned command, unsigned long argument); 2.16 + unsigned command, unsigned long argument); 2.17 extern int xenolinux_block_check(kdev_t dev); 2.18 extern int xenolinux_block_revalidate(kdev_t dev); 2.19 extern void do_xlblk_request (request_queue_t *rq); 2.20 @@ -64,6 +63,5 @@ extern void do_xlblk_request (request_qu 2.21 /* Virtual block-device subsystem. */ 2.22 extern int xlvbd_init(xen_disk_info_t *xdi); 2.23 extern void xlvbd_cleanup(void); 2.24 -extern struct gendisk *xldev_to_gendisk(kdev_t xldev); 2.25 2.26 #endif /* __XL_BLOCK_H__ */
3.1 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c Fri Dec 12 16:43:28 2003 +0000 3.2 +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c Tue Dec 16 15:55:22 2003 +0000 3.3 @@ -6,16 +6,9 @@ 3.4 */ 3.5 3.6 #include "xl_block.h" 3.7 - 3.8 -// #define MAJOR_NR XLVIRT_MAJOR 3.9 #include <linux/blk.h> 3.10 3.11 -/* Copied from linux/ide.h */ 3.12 -typedef unsigned char byte; 3.13 - 3.14 -#define XLVBD_MAX_MAJORS 64 /* total number of vbds we support */ 3.15 - 3.16 -struct gendisk *xlvbd_gendisk[XLVBD_MAX_MAJORS] = { NULL }; 3.17 +#define GENHD_FL_XENO 2 3.18 3.19 /* For convenience we distinguish between ide, scsi and 'other' (i.e. 3.20 ** potentially combinations of the two) in the naming scheme and in a 3.21 @@ -29,7 +22,6 @@ struct gendisk *xlvbd_gendisk[XLVBD_MAX_ 3.22 #define XLSCSI_DEVS_PER_MAJOR 16 3.23 #define XLVBD_DEVS_PER_MAJOR 16 3.24 3.25 - 3.26 #define XLIDE_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ 3.27 #define XLIDE_MAX_PART (1 << XLIDE_PARTN_SHIFT) /* minors per ide vbd */ 3.28 3.29 @@ -39,7 +31,6 @@ struct gendisk *xlvbd_gendisk[XLVBD_MAX_ 3.30 #define XLVBD_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ 3.31 #define XLVBD_MAX_PART (1 << XLVBD_PARTN_SHIFT) /* minors per 'other' vbd */ 3.32 3.33 - 3.34 /* the below are for the use of the generic drivers/block/ll_rw_block.c code */ 3.35 static int xlide_blksize_size[256]; 3.36 static int xlide_hardsect_size[256]; 3.37 @@ -51,7 +42,6 @@ static int xlvbd_blksize_size[256]; 3.38 static int xlvbd_hardsect_size[256]; 3.39 static int xlvbd_max_sectors[256]; 3.40 3.41 - 3.42 static struct block_device_operations xlvbd_block_fops = 3.43 { 3.44 open: xenolinux_block_open, 3.45 @@ -61,290 +51,262 @@ static struct block_device_operations xl 3.46 revalidate: xenolinux_block_revalidate, 3.47 }; 3.48 3.49 - 3.50 -typedef unsigned char bool; 3.51 - 3.52 -/* 3.53 -** Set up all the linux device goop for the virtual block devices (vbd's) 3.54 -** that xen tells us about. Note that although from xen's pov VBDs are 3.55 -** addressed simply an opaque 16-bit device number, the domain creation 3.56 -** tools conventionally allocate these numbers to correspond to those 3.57 -** used by 'real' linux -- this is just for convenience as it means e.g. 3.58 -** that the same /etc/fstab can be used when booting with or without xen. 3.59 -*/ 3.60 +/* 3.61 + * Set up all the linux device goop for the virtual block devices (vbd's) that 3.62 + * xen tells us about. Note that although from xen's pov VBDs are addressed 3.63 + * simply an opaque 16-bit device number, the domain creation tools 3.64 + * conventionally allocate these numbers to correspond to those used by 'real' 3.65 + * linux -- this is just for convenience as it means e.g. that the same 3.66 + * /etc/fstab can be used when booting with or without xen. 3.67 + */ 3.68 int __init xlvbd_init(xen_disk_info_t *xdi) 3.69 { 3.70 int i, result, max_part; 3.71 struct gendisk *gd = NULL; 3.72 kdev_t device; 3.73 unsigned short major, minor, partno; 3.74 - bool is_ide, is_scsi; 3.75 + int is_ide, is_scsi; 3.76 char *major_name; 3.77 unsigned char buf[64]; 3.78 - int majors[256]; 3.79 3.80 SET_MODULE_OWNER(&xlvbd_block_fops); 3.81 3.82 /* Initialize the global arrays. */ 3.83 - for (i = 0; i < 256; i++) 3.84 + for ( i = 0; i < 256; i++ ) 3.85 + { 3.86 + /* from the generic ide code (drivers/ide/ide-probe.c, etc) */ 3.87 + xlide_blksize_size[i] = 1024; 3.88 + xlide_hardsect_size[i] = 512; 3.89 + xlide_max_sectors[i] = 128; /* 'hwif->rqsize' if we knew it */ 3.90 + 3.91 + /* from the generic scsi disk code (drivers/scsi/sd.c) */ 3.92 + xlscsi_blksize_size[i] = 1024; /* XXX 512; */ 3.93 + xlscsi_hardsect_size[i] = 512; 3.94 + xlscsi_max_sectors[i] = 128*8; /* XXX 128; */ 3.95 + 3.96 + /* we don't really know what to set these too since it depends */ 3.97 + xlvbd_blksize_size[i] = 512; 3.98 + xlvbd_hardsect_size[i] = 512; 3.99 + xlvbd_max_sectors[i] = 128; 3.100 + } 3.101 + 3.102 + /* 3.103 + * We need to loop through each major device we've been told about and: 3.104 + * a) register the appropriate blkdev 3.105 + * b) setup the indexed-by-major global arrays (blk_size[], 3.106 + * blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) 3.107 + * c) setup the block queue + make it sensible 3.108 + * d) create an appropriate gendisk structure, and 3.109 + * e) register the gendisk 3.110 + */ 3.111 + for ( i = 0; i < xdi->count; i++ ) 3.112 { 3.113 - /* from the generic ide code (drivers/ide/ide-probe.c, etc) */ 3.114 - xlide_blksize_size[i] = 1024; 3.115 - xlide_hardsect_size[i] = 512; 3.116 - xlide_max_sectors[i] = 128; /* 'hwif->rqsize' if we knew it */ 3.117 + device = xdi->disks[i].device; 3.118 + major = MAJOR(device); 3.119 + minor = MINOR(device); 3.120 + is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ 3.121 + is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ 3.122 + 3.123 + if ( is_ide ) 3.124 + { 3.125 + major_name = XLIDE_MAJOR_NAME; 3.126 + max_part = XLIDE_MAX_PART; 3.127 + } 3.128 + else if ( is_scsi ) 3.129 + { 3.130 + major_name = XLSCSI_MAJOR_NAME; 3.131 + max_part = XLSCSI_MAX_PART; 3.132 + } 3.133 + else 3.134 + { 3.135 + major_name = XLVBD_MAJOR_NAME; 3.136 + max_part = XLVBD_MAX_PART; 3.137 + } 3.138 + 3.139 + partno = minor & (max_part - 1); 3.140 + 3.141 + if ( (gd = get_gendisk(device)) == NULL ) 3.142 + { 3.143 + result = register_blkdev(major, major_name, &xlvbd_block_fops); 3.144 + if ( result < 0 ) 3.145 + { 3.146 + printk(KERN_ALERT "XL VBD: can't get major %d\n", major); 3.147 + continue; 3.148 + } 3.149 3.150 - /* from the generic scsi disk code (drivers/scsi/sd.c) */ 3.151 - xlscsi_blksize_size[i] = 1024; //XXX 512; 3.152 - xlscsi_hardsect_size[i] = 512; 3.153 - xlscsi_max_sectors[i] = 128*8; //XXX 128; 3.154 + if( is_ide ) 3.155 + { 3.156 + blksize_size[major] = xlide_blksize_size; 3.157 + hardsect_size[major] = xlide_hardsect_size; 3.158 + max_sectors[major] = xlide_max_sectors; 3.159 + read_ahead[major] = 8; /* from drivers/ide/ide-probe.c */ 3.160 + } 3.161 + else if ( is_scsi ) 3.162 + { 3.163 + blksize_size[major] = xlscsi_blksize_size; 3.164 + hardsect_size[major] = xlscsi_hardsect_size; 3.165 + max_sectors[major] = xlscsi_max_sectors; 3.166 + read_ahead[major] = 0; /* XXX 8; -- guessing */ 3.167 + } 3.168 + else 3.169 + { 3.170 + blksize_size[major] = xlvbd_blksize_size; 3.171 + hardsect_size[major] = xlvbd_hardsect_size; 3.172 + max_sectors[major] = xlvbd_max_sectors; 3.173 + read_ahead[major] = 8; 3.174 + } 3.175 + 3.176 + blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request); 3.177 + 3.178 + /* 3.179 + * Turn off barking 'headactive' mode. We dequeue buffer heads as 3.180 + * soon as we pass them down to Xen. 3.181 + */ 3.182 + blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); 3.183 3.184 - /* we don't really know what to set these too since it depends */ 3.185 - xlvbd_blksize_size[i] = 512; 3.186 - xlvbd_hardsect_size[i] = 512; 3.187 - xlvbd_max_sectors[i] = 128; 3.188 - } 3.189 + /* Construct an appropriate gendisk structure. */ 3.190 + gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); 3.191 + gd->major = major; 3.192 + gd->major_name = major_name; 3.193 + 3.194 + gd->max_p = max_part; 3.195 + if ( is_ide ) 3.196 + { 3.197 + gd->minor_shift = XLIDE_PARTN_SHIFT; 3.198 + gd->nr_real = XLIDE_DEVS_PER_MAJOR; 3.199 + } 3.200 + else if ( is_scsi ) 3.201 + { 3.202 + gd->minor_shift = XLSCSI_PARTN_SHIFT; 3.203 + gd->nr_real = XLSCSI_DEVS_PER_MAJOR; 3.204 + } 3.205 + else 3.206 + { 3.207 + gd->minor_shift = XLVBD_PARTN_SHIFT; 3.208 + gd->nr_real = XLVBD_DEVS_PER_MAJOR; 3.209 + } 3.210 + 3.211 + /* 3.212 + ** The sizes[] and part[] arrays hold the sizes and other 3.213 + ** information about every partition with this 'major' (i.e. 3.214 + ** every disk sharing the 8 bit prefix * max partns per disk) 3.215 + */ 3.216 + gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL); 3.217 + gd->part = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct), 3.218 + GFP_KERNEL); 3.219 + memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int)); 3.220 + memset(gd->part, 0, max_part * gd->nr_real 3.221 + * sizeof(struct hd_struct)); 3.222 3.223 3.224 - /* keep track of which majors we've seen so far */ 3.225 - for (i = 0; i < 256; i++) 3.226 - majors[i] = 0; 3.227 + gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), 3.228 + GFP_KERNEL); 3.229 + memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t)); 3.230 3.231 - /* 3.232 - ** We need to loop through each major device we've been told about and: 3.233 - ** a) register the appropriate blkdev 3.234 - ** b) setup the indexed-by-major global arrays (blk_size[], 3.235 - ** blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) 3.236 - ** c) setup the block queue + make it sensible 3.237 - ** d) create an appropriate gendisk structure, and 3.238 - ** e) register the gendisk 3.239 - */ 3.240 - for (i = 0; i < xdi->count; i++) 3.241 - { 3.242 - device = xdi->disks[i].device; 3.243 - major = MAJOR(device); 3.244 - minor = MINOR(device); 3.245 - is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ 3.246 - is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ 3.247 - 3.248 - if(is_ide) { 3.249 - major_name = XLIDE_MAJOR_NAME; 3.250 - max_part = XLIDE_MAX_PART; 3.251 - } else if(is_scsi) { 3.252 - major_name = XLSCSI_MAJOR_NAME; 3.253 - max_part = XLSCSI_MAX_PART; 3.254 - } else { 3.255 - major_name = XLVBD_MAJOR_NAME; 3.256 - max_part = XLVBD_MAX_PART; 3.257 - } 3.258 + gd->next = NULL; 3.259 + gd->fops = &xlvbd_block_fops; 3.260 3.261 - /* 3.262 - ** XXX SMH: conventionally we assume a minor device if the 3.263 - ** corresponding linux device number would be a minor device; 3.264 - ** minor devices require slightly different handling than 3.265 - ** 'full' devices (e.g. in terms of partition table handling). 3.266 - */ 3.267 - partno = minor & (max_part - 1); 3.268 - 3.269 - if(!majors[major]) { 3.270 - 3.271 - result = register_blkdev(major, major_name, &xlvbd_block_fops); 3.272 - if (result < 0) { 3.273 - printk(KERN_ALERT "XL VBD: can't get major %d\n", major); 3.274 - continue; 3.275 - } 3.276 + gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), 3.277 + GFP_KERNEL); 3.278 + gd->flags = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL); 3.279 + 3.280 + memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr)); 3.281 + memset(gd->flags, 0, gd->nr_real * sizeof(*gd->flags)); 3.282 3.283 - blk_size[major] = NULL; 3.284 - if(is_ide) { 3.285 - blksize_size[major] = xlide_blksize_size; 3.286 - hardsect_size[major] = xlide_hardsect_size; 3.287 - max_sectors[major] = xlide_max_sectors; 3.288 - read_ahead[major] = 8; // from drivers/ide/ide-probe.c 3.289 - } else if(is_scsi) { 3.290 - blksize_size[major] = xlscsi_blksize_size; 3.291 - hardsect_size[major] = xlscsi_hardsect_size; 3.292 - max_sectors[major] = xlscsi_max_sectors; 3.293 - read_ahead[major] = 0; // XXX 8; -- guessing 3.294 - } else { 3.295 - blksize_size[major] = xlvbd_blksize_size; 3.296 - hardsect_size[major] = xlvbd_hardsect_size; 3.297 - max_sectors[major] = xlvbd_max_sectors; 3.298 - read_ahead[major] = 8; 3.299 - } 3.300 - 3.301 - blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request); 3.302 - 3.303 - /* 3.304 - * Turn off barking 'headactive' mode. We dequeue buffer heads as 3.305 - * soon as we pass them down to Xen. 3.306 - */ 3.307 - blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); 3.308 + add_gendisk(gd); 3.309 + 3.310 + blk_size[major] = gd->sizes; 3.311 + } 3.312 + 3.313 + if ( XD_READONLY(xdi->disks[i].info) ) 3.314 + set_device_ro(device, 1); 3.315 3.316 - /* Construct an appropriate gendisk structure. */ 3.317 - gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); 3.318 - gd->major = major; 3.319 - gd->major_name = major_name; 3.320 - 3.321 - gd->max_p = max_part; 3.322 - if(is_ide) { 3.323 - gd->minor_shift = XLIDE_PARTN_SHIFT; 3.324 - gd->nr_real = XLIDE_DEVS_PER_MAJOR; 3.325 - } else if(is_scsi) { 3.326 - gd->minor_shift = XLSCSI_PARTN_SHIFT; 3.327 - gd->nr_real = XLSCSI_DEVS_PER_MAJOR; 3.328 - } else { 3.329 - gd->minor_shift = XLVBD_PARTN_SHIFT; 3.330 - gd->nr_real = XLVBD_DEVS_PER_MAJOR; 3.331 - } 3.332 - 3.333 - /* 3.334 - ** The sizes[] and part[] arrays hold the sizes and other 3.335 - ** information about every partition with this 'major' (i.e. 3.336 - ** every disk sharing the 8 bit prefix * max partns per disk) 3.337 - */ 3.338 - gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL); 3.339 - gd->part = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct), 3.340 - GFP_KERNEL); 3.341 - memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int)); 3.342 - memset(gd->part, 0, max_part * gd->nr_real 3.343 - * sizeof(struct hd_struct)); 3.344 - 3.345 - 3.346 - gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), 3.347 - GFP_KERNEL); 3.348 - memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t)); 3.349 - 3.350 - gd->next = NULL; 3.351 - gd->fops = &xlvbd_block_fops; 3.352 - 3.353 - gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), 3.354 - GFP_KERNEL); 3.355 - gd->flags = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL); 3.356 - 3.357 - memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr)); 3.358 - memset(gd->flags, 0, gd->nr_real * sizeof(*gd->flags)); 3.359 - 3.360 - /* 3.361 - ** Keep track of gendisk both locally and in the global array. 3.362 - ** XXX SMH: can probably do without local copy -- FIXME later 3.363 - */ 3.364 - xlvbd_gendisk[i] = gd; 3.365 - add_gendisk(gd); 3.366 + gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XENO; 3.367 + 3.368 + if ( partno != 0 ) 3.369 + { 3.370 + /* Need to skankily setup 'partition' information */ 3.371 + gd->part[partno].start_sect = 0; 3.372 + gd->part[partno].nr_sects = xdi->disks[i].capacity; 3.373 + gd->sizes[partno] = xdi->disks[i].capacity; 3.374 + } 3.375 + else 3.376 + { 3.377 + /* Some final fix-ups depending on the device type */ 3.378 + switch ( XD_TYPE(xdi->disks[i].info) ) 3.379 + { 3.380 + case XD_TYPE_CDROM: 3.381 + case XD_TYPE_FLOPPY: 3.382 + case XD_TYPE_TAPE: 3.383 + gd->part[minor].nr_sects = xdi->disks[i].capacity; 3.384 + gd->sizes[minor] = xdi->disks[i].capacity>>(BLOCK_SIZE_BITS-9); 3.385 + gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; 3.386 + printk(KERN_ALERT 3.387 + "Skipping partition check on %s /dev/%s\n", 3.388 + XD_TYPE(xdi->disks[i].info)==XD_TYPE_CDROM ? "cdrom" : 3.389 + (XD_TYPE(xdi->disks[i].info)==XD_TYPE_TAPE ? "tape" : 3.390 + "floppy"), disk_name(gd, MINOR(device), buf)); 3.391 + break; 3.392 3.393 - /* XXX SMH: not clear on what 'real_devices' is indexed by; 3.394 - hence using unit number for now but in old code was 'disk' aka 3.395 - sequence number assigned by xen during probe = barfle? */ 3.396 - ((xl_disk_t *)gd->real_devices)[minor>>gd->minor_shift].capacity = 3.397 - xdi->disks[i].capacity; 3.398 - 3.399 - 3.400 - /* remember that we've done this major */ 3.401 - majors[major] = 1; 3.402 - } else 3.403 - /* Continue the setup of this gendisk */ 3.404 - gd = get_gendisk(device); 3.405 - 3.406 - if(XD_READONLY(xdi->disks[i].info)) 3.407 - set_device_ro(device, 1); 3.408 - 3.409 - if(partno) { 3.410 - 3.411 - /* Need to skankily setup 'partition' information */ 3.412 - gd->part[partno].start_sect = 0; 3.413 - gd->part[partno].nr_sects = xdi->disks[i].capacity; 3.414 - gd->sizes[partno] = xdi->disks[i].capacity; 3.415 - 3.416 - } else { 3.417 + case XD_TYPE_DISK: 3.418 + register_disk(gd, device, gd->nr_real, &xlvbd_block_fops, 3.419 + xdi->disks[i].capacity); 3.420 + break; 3.421 3.422 - /* Some final fix-ups depending on the device type */ 3.423 - switch (XD_TYPE(xdi->disks[i].info)) 3.424 - { 3.425 - 3.426 - case XD_TYPE_CDROM: 3.427 - case XD_TYPE_FLOPPY: 3.428 - case XD_TYPE_TAPE: 3.429 - gd->flags[minor >> gd->minor_shift] = GENHD_FL_REMOVABLE; 3.430 - printk(KERN_ALERT 3.431 - "Skipping partition check on %s /dev/%s\n", 3.432 - XD_TYPE(xdi->disks[i].info)==XD_TYPE_CDROM ? "cdrom" : 3.433 - (XD_TYPE(xdi->disks[i].info)==XD_TYPE_TAPE ? "tape" : 3.434 - "floppy"), disk_name(gd, MINOR(device), buf)); 3.435 - break; 3.436 - 3.437 - case XD_TYPE_DISK: 3.438 - register_disk(gd, device, gd->nr_real, &xlvbd_block_fops, 3.439 - xdi->disks[i].capacity); 3.440 - break; 3.441 - 3.442 - default: 3.443 - printk(KERN_ALERT "XenoLinux: unknown device type %d\n", 3.444 - XD_TYPE(xdi->disks[i].info)); 3.445 - break; 3.446 - } 3.447 - 3.448 - } 3.449 - 3.450 - printk(KERN_ALERT "XenoLinux Virtual Block Device Driver " 3.451 - "installed [device: %04x]\n", device); 3.452 + default: 3.453 + printk(KERN_ALERT "XenoLinux: unknown device type %d\n", 3.454 + XD_TYPE(xdi->disks[i].info)); 3.455 + break; 3.456 + } 3.457 + } 3.458 + 3.459 + printk(KERN_ALERT "XenoLinux Virtual Block Device Driver " 3.460 + "installed [device: %04x]\n", device); 3.461 } 3.462 3.463 return 0; 3.464 } 3.465 3.466 -/* 3.467 -** XXX SMH: crappy linear scan routine to map from a device number bac k 3.468 -** to the relevant gendisk; could be made better if and when it becomes 3.469 -** an issue but for now we expect success within a few loop iterations. 3.470 -*/ 3.471 -struct gendisk *xldev_to_gendisk(kdev_t xldev) 3.472 -{ 3.473 - int i; 3.474 - short major = MAJOR(xldev); 3.475 - 3.476 - for(i = 0; i < XLVBD_MAX_MAJORS; i++) { 3.477 - if(xlvbd_gendisk[i]->major == major) 3.478 - return xlvbd_gendisk[i]; 3.479 - } 3.480 - 3.481 - /* didn't find it -- death */ 3.482 - BUG(); 3.483 - return NULL; 3.484 -} 3.485 - 3.486 void xlvbd_cleanup(void) 3.487 { 3.488 - bool is_ide, is_scsi; 3.489 + int is_ide, is_scsi, i; 3.490 struct gendisk *gd; 3.491 char *major_name; 3.492 int major; 3.493 3.494 - for(major = 0; major < XLVBD_MAX_MAJORS; major++) { 3.495 - 3.496 - if(!(gd = xlvbd_gendisk[major])) 3.497 - continue; 3.498 - 3.499 - is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ 3.500 - is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ 3.501 + for ( major = 0; major < MAX_BLKDEV; major++ ) 3.502 + { 3.503 + if ( (gd = get_gendisk(MKDEV(major, 0))) == NULL ) 3.504 + continue; 3.505 3.506 - blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); 3.507 - 3.508 - if(is_ide) { 3.509 - major_name = XLIDE_MAJOR_NAME; 3.510 - } else if(is_scsi) { 3.511 - major_name = XLSCSI_MAJOR_NAME; 3.512 - } else { 3.513 - major_name = XLVBD_MAJOR_NAME; 3.514 - } 3.515 + /* 3.516 + * If this is a 'Xeno' blkdev then at least one unit will have the Xeno 3.517 + * flag set. 3.518 + */ 3.519 + for ( i = 0; i < gd->nr_real; i++ ) 3.520 + if ( gd->flags[i] & GENHD_FL_XENO ) 3.521 + break; 3.522 + if ( i == gd->nr_real ) 3.523 + continue; 3.524 + 3.525 + is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ 3.526 + is_scsi = SCSI_BLK_MAJOR(major); /* is this a scsi device? */ 3.527 3.528 - if (unregister_blkdev(major, major_name) != 0) 3.529 - printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:" 3.530 - "major device %04x uninstalled w/ errors\n", major); 3.531 + blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); 3.532 3.533 + if ( is_ide ) 3.534 + major_name = XLIDE_MAJOR_NAME; 3.535 + else if ( is_scsi ) 3.536 + major_name = XLSCSI_MAJOR_NAME; 3.537 + else 3.538 + major_name = XLVBD_MAJOR_NAME; 3.539 + 3.540 + if ( unregister_blkdev(major, major_name) != 0 ) 3.541 + printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:" 3.542 + "major device %04x uninstalled w/ errors\n", major); 3.543 } 3.544 - 3.545 - return; 3.546 } 3.547 3.548 - 3.549 #ifdef MODULE 3.550 module_init(xlvbd_init); 3.551 module_exit(xlvbd_cleanup);