ia64/linux-2.6.18-xen.hg

changeset 581:65faf5fc61a1

blkfront: Fix blkfront to accept expanded devices (v2)

This patch implements the new extended allocation scheme on the
blkfront end. Note that there is a new xenbus node for the extended
stuff, called "virtual-device-ext". On a blkfront_probe(), if nothing
is found in "virtual-device", then it will go looking in
"virtual-device-ext". This prevents old guest kernels from potentially
mis-interpreting data in "virtual-device" (and then subsequently
crashing).

Changes since v1:
- Restructure the changes to remove duplicate code
- Add some error checks on the xlvbd_add() path. Note that I did not
do full error checking on the existing numbering scheme (i.e. the
202<<8 for xvd, 3<<8 for IDE, 8<<8 for SCSI, etc). The reason I
didn't do full checking is that it is perfectly legal to do something
like: "xm block-attach pv tap:aio:/disk 0xCB10 w" (which is major
203), which then maps onto the 202 xvd device. It's not particularly
nice behavior, in my opinion, but changing it now would change this
behavior. So the only check I added was to make sure we weren't above
the extended device range (1<<28).

Signed-off-by: Chris Lalancette <clalance@redhat.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 27 16:06:41 2008 +0100 (2008-06-27)
parents e7b48c70c727
children b29a06ba7a5f
files drivers/xen/blkfront/blkfront.c drivers/xen/blkfront/vbd.c
line diff
     1.1 --- a/drivers/xen/blkfront/blkfront.c	Fri Jun 27 14:46:41 2008 +0100
     1.2 +++ b/drivers/xen/blkfront/blkfront.c	Fri Jun 27 16:06:41 2008 +0100
     1.3 @@ -92,8 +92,13 @@ static int blkfront_probe(struct xenbus_
     1.4  	err = xenbus_scanf(XBT_NIL, dev->nodename,
     1.5  			   "virtual-device", "%i", &vdevice);
     1.6  	if (err != 1) {
     1.7 -		xenbus_dev_fatal(dev, err, "reading virtual-device");
     1.8 -		return err;
     1.9 +		/* go looking in the extended area instead */
    1.10 +		err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device-ext",
    1.11 +			"%i", &vdevice);
    1.12 +		if (err != 1) {
    1.13 +			xenbus_dev_fatal(dev, err, "reading virtual-device");
    1.14 +			return err;
    1.15 +		}
    1.16  	}
    1.17  
    1.18  	info = kzalloc(sizeof(*info), GFP_KERNEL);
     2.1 --- a/drivers/xen/blkfront/vbd.c	Fri Jun 27 14:46:41 2008 +0100
     2.2 +++ b/drivers/xen/blkfront/vbd.c	Fri Jun 27 16:06:41 2008 +0100
     2.3 @@ -43,6 +43,11 @@
     2.4  #define BLKIF_MAJOR(dev) ((dev)>>8)
     2.5  #define BLKIF_MINOR(dev) ((dev) & 0xff)
     2.6  
     2.7 +#define EXT_SHIFT 28
     2.8 +#define EXTENDED (1<<EXT_SHIFT)
     2.9 +#define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
    2.10 +#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
    2.11 +
    2.12  /*
    2.13   * For convenience we distinguish between ide, scsi and 'other' (i.e.,
    2.14   * potentially combinations of the two) in the naming scheme and in a few other
    2.15 @@ -74,6 +79,13 @@ static struct xlbd_type_info xlbd_vbd_ty
    2.16  	.diskname = "xvd",
    2.17  };
    2.18  
    2.19 +static struct xlbd_type_info xlbd_vbd_type_ext = {
    2.20 +	.partn_shift = 8,
    2.21 +	.disks_per_major = 256,
    2.22 +	.devname = "xvd",
    2.23 +	.diskname = "xvd",
    2.24 +};
    2.25 +
    2.26  static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
    2.27  					 NUM_VBD_MAJORS];
    2.28  
    2.29 @@ -85,10 +97,6 @@ static struct xlbd_major_info *major_inf
    2.30  #define XLBD_MAJOR_SCSI_RANGE	XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1
    2.31  #define XLBD_MAJOR_VBD_RANGE	XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1
    2.32  
    2.33 -/* Information about our VBDs. */
    2.34 -#define MAX_VBDS 64
    2.35 -static LIST_HEAD(vbds_list);
    2.36 -
    2.37  static struct block_device_operations xlvbd_block_fops =
    2.38  {
    2.39  	.owner = THIS_MODULE,
    2.40 @@ -139,13 +147,10 @@ xlbd_alloc_major_info(int major, int min
    2.41  }
    2.42  
    2.43  static struct xlbd_major_info *
    2.44 -xlbd_get_major_info(int vdevice)
    2.45 +xlbd_get_major_info(int major, int minor)
    2.46  {
    2.47  	struct xlbd_major_info *mi;
    2.48 -	int major, minor, index;
    2.49 -
    2.50 -	major = BLKIF_MAJOR(vdevice);
    2.51 -	minor = BLKIF_MINOR(vdevice);
    2.52 +	int index;
    2.53  
    2.54  	switch (major) {
    2.55  	case IDE0_MAJOR: index = 0; break;
    2.56 @@ -222,7 +227,7 @@ xlvbd_init_blk_queue(struct gendisk *gd,
    2.57  }
    2.58  
    2.59  static int
    2.60 -xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity, int vdevice,
    2.61 +xlvbd_alloc_gendisk(int major, int minor, blkif_sector_t capacity, int vdevice,
    2.62  		    u16 vdisk_info, u16 sector_size,
    2.63  		    struct blkfront_info *info)
    2.64  {
    2.65 @@ -236,9 +241,11 @@ xlvbd_alloc_gendisk(int minor, blkif_sec
    2.66  	BUG_ON(info->mi != NULL);
    2.67  	BUG_ON(info->rq != NULL);
    2.68  
    2.69 -	mi = xlbd_get_major_info(vdevice);
    2.70 +	mi = xlbd_get_major_info(major, minor);
    2.71  	if (mi == NULL)
    2.72  		goto out;
    2.73 +	if (VDEV_IS_EXTENDED(vdevice))
    2.74 +		mi->type = &xlbd_vbd_type_ext;
    2.75  	info->mi = mi;
    2.76  
    2.77  	if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
    2.78 @@ -318,15 +325,30 @@ xlvbd_add(blkif_sector_t capacity, int v
    2.79  {
    2.80  	struct block_device *bd;
    2.81  	int err = 0;
    2.82 +	int major, minor;
    2.83  
    2.84 -	info->dev = MKDEV(BLKIF_MAJOR(vdevice), BLKIF_MINOR(vdevice));
    2.85 +	if ((vdevice>>EXT_SHIFT) > 1) {
    2.86 +		/* this is above the extended range; something is wrong */
    2.87 +		printk(KERN_WARNING "blkfront: vdevice 0x%x is above the extended range; ignoring\n", vdevice);
    2.88 +		return -ENODEV;
    2.89 +	}
    2.90  
    2.91 +	if (!VDEV_IS_EXTENDED(vdevice)) {
    2.92 +		major = BLKIF_MAJOR(vdevice);
    2.93 +		minor = BLKIF_MINOR(vdevice);
    2.94 +	}
    2.95 +	else {
    2.96 +		major = 202;
    2.97 +		minor = BLKIF_MINOR_EXT(vdevice);
    2.98 +	}
    2.99 +
   2.100 +	info->dev = MKDEV(major, minor);
   2.101  	bd = bdget(info->dev);
   2.102  	if (bd == NULL)
   2.103  		return -ENODEV;
   2.104  
   2.105 -	err = xlvbd_alloc_gendisk(BLKIF_MINOR(vdevice), capacity, vdevice,
   2.106 -				  vdisk_info, sector_size, info);
   2.107 +	err = xlvbd_alloc_gendisk(major, minor, capacity, vdevice, vdisk_info,
   2.108 +				  sector_size, info);
   2.109  
   2.110  	bdput(bd);
   2.111  	return err;