[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] blkfront: Fix blkfront to accept expanded devices (v2)



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1214579201 -3600
# Node ID 65faf5fc61a1cadb20885dc2e926efe1722956fd
# Parent  e7b48c70c7270d46ba645fc643b63bb49860ea44
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@xxxxxxxxxx>
---
 drivers/xen/blkfront/blkfront.c |    9 +++++-
 drivers/xen/blkfront/vbd.c      |   54 ++++++++++++++++++++++++++++------------
 2 files changed, 45 insertions(+), 18 deletions(-)

diff -r e7b48c70c727 -r 65faf5fc61a1 drivers/xen/blkfront/blkfront.c
--- a/drivers/xen/blkfront/blkfront.c   Fri Jun 27 14:46:41 2008 +0100
+++ b/drivers/xen/blkfront/blkfront.c   Fri Jun 27 16:06:41 2008 +0100
@@ -92,8 +92,13 @@ static int blkfront_probe(struct xenbus_
        err = xenbus_scanf(XBT_NIL, dev->nodename,
                           "virtual-device", "%i", &vdevice);
        if (err != 1) {
-               xenbus_dev_fatal(dev, err, "reading virtual-device");
-               return err;
+               /* go looking in the extended area instead */
+               err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device-ext",
+                       "%i", &vdevice);
+               if (err != 1) {
+                       xenbus_dev_fatal(dev, err, "reading virtual-device");
+                       return err;
+               }
        }
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
diff -r e7b48c70c727 -r 65faf5fc61a1 drivers/xen/blkfront/vbd.c
--- a/drivers/xen/blkfront/vbd.c        Fri Jun 27 14:46:41 2008 +0100
+++ b/drivers/xen/blkfront/vbd.c        Fri Jun 27 16:06:41 2008 +0100
@@ -43,6 +43,11 @@
 #define BLKIF_MAJOR(dev) ((dev)>>8)
 #define BLKIF_MINOR(dev) ((dev) & 0xff)
 
+#define EXT_SHIFT 28
+#define EXTENDED (1<<EXT_SHIFT)
+#define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
+#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
+
 /*
  * 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
@@ -74,6 +79,13 @@ static struct xlbd_type_info xlbd_vbd_ty
        .diskname = "xvd",
 };
 
+static struct xlbd_type_info xlbd_vbd_type_ext = {
+       .partn_shift = 8,
+       .disks_per_major = 256,
+       .devname = "xvd",
+       .diskname = "xvd",
+};
+
 static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
                                         NUM_VBD_MAJORS];
 
@@ -84,10 +96,6 @@ static struct xlbd_major_info *major_inf
 #define XLBD_MAJOR_IDE_RANGE   XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START 
- 1
 #define XLBD_MAJOR_SCSI_RANGE  XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START 
- 1
 #define XLBD_MAJOR_VBD_RANGE   XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + 
NUM_VBD_MAJORS - 1
-
-/* Information about our VBDs. */
-#define MAX_VBDS 64
-static LIST_HEAD(vbds_list);
 
 static struct block_device_operations xlvbd_block_fops =
 {
@@ -139,13 +147,10 @@ xlbd_alloc_major_info(int major, int min
 }
 
 static struct xlbd_major_info *
-xlbd_get_major_info(int vdevice)
+xlbd_get_major_info(int major, int minor)
 {
        struct xlbd_major_info *mi;
-       int major, minor, index;
-
-       major = BLKIF_MAJOR(vdevice);
-       minor = BLKIF_MINOR(vdevice);
+       int index;
 
        switch (major) {
        case IDE0_MAJOR: index = 0; break;
@@ -222,7 +227,7 @@ xlvbd_init_blk_queue(struct gendisk *gd,
 }
 
 static int
-xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity, int vdevice,
+xlvbd_alloc_gendisk(int major, int minor, blkif_sector_t capacity, int vdevice,
                    u16 vdisk_info, u16 sector_size,
                    struct blkfront_info *info)
 {
@@ -236,9 +241,11 @@ xlvbd_alloc_gendisk(int minor, blkif_sec
        BUG_ON(info->mi != NULL);
        BUG_ON(info->rq != NULL);
 
-       mi = xlbd_get_major_info(vdevice);
+       mi = xlbd_get_major_info(major, minor);
        if (mi == NULL)
                goto out;
+       if (VDEV_IS_EXTENDED(vdevice))
+               mi->type = &xlbd_vbd_type_ext;
        info->mi = mi;
 
        if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
@@ -318,15 +325,30 @@ xlvbd_add(blkif_sector_t capacity, int v
 {
        struct block_device *bd;
        int err = 0;
-
-       info->dev = MKDEV(BLKIF_MAJOR(vdevice), BLKIF_MINOR(vdevice));
-
+       int major, minor;
+
+       if ((vdevice>>EXT_SHIFT) > 1) {
+               /* this is above the extended range; something is wrong */
+               printk(KERN_WARNING "blkfront: vdevice 0x%x is above the 
extended range; ignoring\n", vdevice);
+               return -ENODEV;
+       }
+
+       if (!VDEV_IS_EXTENDED(vdevice)) {
+               major = BLKIF_MAJOR(vdevice);
+               minor = BLKIF_MINOR(vdevice);
+       }
+       else {
+               major = 202;
+               minor = BLKIF_MINOR_EXT(vdevice);
+       }
+
+       info->dev = MKDEV(major, minor);
        bd = bdget(info->dev);
        if (bd == NULL)
                return -ENODEV;
 
-       err = xlvbd_alloc_gendisk(BLKIF_MINOR(vdevice), capacity, vdevice,
-                                 vdisk_info, sector_size, info);
+       err = xlvbd_alloc_gendisk(major, minor, capacity, vdevice, vdisk_info,
+                                 sector_size, info);
 
        bdput(bd);
        return err;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.