|
@@ -105,15 +105,17 @@ static DEFINE_SPINLOCK(blkif_io_lock);
|
|
#define GRANT_INVALID_REF 0
|
|
#define GRANT_INVALID_REF 0
|
|
|
|
|
|
#define PARTS_PER_DISK 16
|
|
#define PARTS_PER_DISK 16
|
|
|
|
+#define PARTS_PER_EXT_DISK 256
|
|
|
|
|
|
#define BLKIF_MAJOR(dev) ((dev)>>8)
|
|
#define BLKIF_MAJOR(dev) ((dev)>>8)
|
|
#define BLKIF_MINOR(dev) ((dev) & 0xff)
|
|
#define BLKIF_MINOR(dev) ((dev) & 0xff)
|
|
|
|
|
|
-#define DEV_NAME "xvd" /* name in /dev */
|
|
|
|
|
|
+#define EXT_SHIFT 28
|
|
|
|
+#define EXTENDED (1<<EXT_SHIFT)
|
|
|
|
+#define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
|
|
|
|
+#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
|
|
|
|
|
|
-/* Information about our VBDs. */
|
|
|
|
-#define MAX_VBDS 64
|
|
|
|
-static LIST_HEAD(vbds_list);
|
|
|
|
|
|
+#define DEV_NAME "xvd" /* name in /dev */
|
|
|
|
|
|
static int get_id_from_freelist(struct blkfront_info *info)
|
|
static int get_id_from_freelist(struct blkfront_info *info)
|
|
{
|
|
{
|
|
@@ -386,31 +388,60 @@ static int xlvbd_barrier(struct blkfront_info *info)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity,
|
|
|
|
- int vdevice, u16 vdisk_info, u16 sector_size,
|
|
|
|
- struct blkfront_info *info)
|
|
|
|
|
|
+static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
|
|
|
|
+ struct blkfront_info *info,
|
|
|
|
+ u16 vdisk_info, u16 sector_size)
|
|
{
|
|
{
|
|
struct gendisk *gd;
|
|
struct gendisk *gd;
|
|
int nr_minors = 1;
|
|
int nr_minors = 1;
|
|
int err = -ENODEV;
|
|
int err = -ENODEV;
|
|
|
|
+ unsigned int offset;
|
|
|
|
+ int minor;
|
|
|
|
+ int nr_parts;
|
|
|
|
|
|
BUG_ON(info->gd != NULL);
|
|
BUG_ON(info->gd != NULL);
|
|
BUG_ON(info->rq != NULL);
|
|
BUG_ON(info->rq != NULL);
|
|
|
|
|
|
- if ((minor % PARTS_PER_DISK) == 0)
|
|
|
|
- nr_minors = PARTS_PER_DISK;
|
|
|
|
|
|
+ if ((info->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", info->vdevice);
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!VDEV_IS_EXTENDED(info->vdevice)) {
|
|
|
|
+ minor = BLKIF_MINOR(info->vdevice);
|
|
|
|
+ nr_parts = PARTS_PER_DISK;
|
|
|
|
+ } else {
|
|
|
|
+ minor = BLKIF_MINOR_EXT(info->vdevice);
|
|
|
|
+ nr_parts = PARTS_PER_EXT_DISK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((minor % nr_parts) == 0)
|
|
|
|
+ nr_minors = nr_parts;
|
|
|
|
|
|
gd = alloc_disk(nr_minors);
|
|
gd = alloc_disk(nr_minors);
|
|
if (gd == NULL)
|
|
if (gd == NULL)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
- if (nr_minors > 1)
|
|
|
|
- sprintf(gd->disk_name, "%s%c", DEV_NAME,
|
|
|
|
- 'a' + minor / PARTS_PER_DISK);
|
|
|
|
- else
|
|
|
|
- sprintf(gd->disk_name, "%s%c%d", DEV_NAME,
|
|
|
|
- 'a' + minor / PARTS_PER_DISK,
|
|
|
|
- minor % PARTS_PER_DISK);
|
|
|
|
|
|
+ offset = minor / nr_parts;
|
|
|
|
+
|
|
|
|
+ if (nr_minors > 1) {
|
|
|
|
+ if (offset < 26)
|
|
|
|
+ sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset);
|
|
|
|
+ else
|
|
|
|
+ sprintf(gd->disk_name, "%s%c%c", DEV_NAME,
|
|
|
|
+ 'a' + ((offset / 26)-1), 'a' + (offset % 26));
|
|
|
|
+ } else {
|
|
|
|
+ if (offset < 26)
|
|
|
|
+ sprintf(gd->disk_name, "%s%c%d", DEV_NAME,
|
|
|
|
+ 'a' + offset,
|
|
|
|
+ minor & (nr_parts - 1));
|
|
|
|
+ else
|
|
|
|
+ sprintf(gd->disk_name, "%s%c%c%d", DEV_NAME,
|
|
|
|
+ 'a' + ((offset / 26) - 1),
|
|
|
|
+ 'a' + (offset % 26),
|
|
|
|
+ minor & (nr_parts - 1));
|
|
|
|
+ }
|
|
|
|
|
|
gd->major = XENVBD_MAJOR;
|
|
gd->major = XENVBD_MAJOR;
|
|
gd->first_minor = minor;
|
|
gd->first_minor = minor;
|
|
@@ -699,8 +730,13 @@ static int blkfront_probe(struct xenbus_device *dev,
|
|
err = xenbus_scanf(XBT_NIL, dev->nodename,
|
|
err = xenbus_scanf(XBT_NIL, dev->nodename,
|
|
"virtual-device", "%i", &vdevice);
|
|
"virtual-device", "%i", &vdevice);
|
|
if (err != 1) {
|
|
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);
|
|
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
|
@@ -861,9 +897,7 @@ static void blkfront_connect(struct blkfront_info *info)
|
|
if (err)
|
|
if (err)
|
|
info->feature_barrier = 0;
|
|
info->feature_barrier = 0;
|
|
|
|
|
|
- err = xlvbd_alloc_gendisk(BLKIF_MINOR(info->vdevice),
|
|
|
|
- sectors, info->vdevice,
|
|
|
|
- binfo, sector_size, info);
|
|
|
|
|
|
+ err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
|
|
if (err) {
|
|
if (err) {
|
|
xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
|
|
xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
|
|
info->xbdev->otherend);
|
|
info->xbdev->otherend);
|