Jan Beulich
2012-Mar-06  09:04 UTC
[PATCH] linux-2.6.18/blkfront: properly name all devices
- devices beyond xvdzz didn''t get proper names assigned at all
- devices using SCSI_CDROM_MAJOR got named sdXX rather than srNN
- devices with unknown majors got mistakenly converted to use major 202
- extended devices with minors not representable within the kernel''s
  major/minor bit split spilled into foreign majors
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/drivers/xen/blkfront/block.h
+++ b/drivers/xen/blkfront/block.h
@@ -64,20 +64,12 @@
 #define DPRINTK_IOCTL(_f, _a...) ((void)0)
 #endif
 
-struct xlbd_type_info
-{
-	int partn_shift;
-	int disks_per_major;
-	char *devname;
-	char *diskname;
-};
-
 struct xlbd_major_info
 {
 	int major;
 	int index;
 	int usage;
-	struct xlbd_type_info *type;
+	const struct xlbd_type_info *type;
 	struct xlbd_minor_state *minors;
 };
 
--- a/drivers/xen/blkfront/vbd.c
+++ b/drivers/xen/blkfront/vbd.c
@@ -65,46 +65,63 @@ struct xlbd_minor_state {
  */
 
 #define NUM_IDE_MAJORS 10
-#define NUM_SCSI_MAJORS 17
+#define NUM_SD_MAJORS 16
 #define NUM_VBD_MAJORS 2
 
-static struct xlbd_type_info xlbd_ide_type = {
+struct xlbd_type_info
+{
+	int partn_shift;
+	int disks_per_major;
+	char *devname;
+	char *diskname;
+};
+
+static const struct xlbd_type_info xlbd_ide_type = {
 	.partn_shift = 6,
 	.disks_per_major = 2,
 	.devname = "ide",
 	.diskname = "hd",
 };
 
-static struct xlbd_type_info xlbd_scsi_type = {
+static const struct xlbd_type_info xlbd_sd_type = {
 	.partn_shift = 4,
 	.disks_per_major = 16,
 	.devname = "sd",
 	.diskname = "sd",
 };
 
-static struct xlbd_type_info xlbd_vbd_type = {
+static const struct xlbd_type_info xlbd_sr_type = {
+	.partn_shift = 0,
+	.disks_per_major = 256,
+	.devname = "sr",
+	.diskname = "sr",
+};
+
+static const struct xlbd_type_info xlbd_vbd_type = {
 	.partn_shift = 4,
 	.disks_per_major = 16,
 	.devname = "xvd",
 	.diskname = "xvd",
 };
 
-static struct xlbd_type_info xlbd_vbd_type_ext = {
+static const 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 +
+static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SD_MAJORS + 1 +
 					 NUM_VBD_MAJORS];
 
 #define XLBD_MAJOR_IDE_START	0
-#define XLBD_MAJOR_SCSI_START	(NUM_IDE_MAJORS)
-#define XLBD_MAJOR_VBD_START	(NUM_IDE_MAJORS + NUM_SCSI_MAJORS)
-
-#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_SD_START	(NUM_IDE_MAJORS)
+#define XLBD_MAJOR_SR_START	(NUM_IDE_MAJORS + NUM_SD_MAJORS)
+#define XLBD_MAJOR_VBD_START	(NUM_IDE_MAJORS + NUM_SD_MAJORS + 1)
+
+#define XLBD_MAJOR_IDE_RANGE	XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SD_START - 1
+#define XLBD_MAJOR_SD_RANGE	XLBD_MAJOR_SD_START ... XLBD_MAJOR_SR_START - 1
+#define XLBD_MAJOR_SR_RANGE	XLBD_MAJOR_SR_START
 #define XLBD_MAJOR_VBD_RANGE	XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START +
NUM_VBD_MAJORS - 1
 
 #define XLBD_MAJOR_VBD_ALT(idx) ((idx) ^ XLBD_MAJOR_VBD_START ^
(XLBD_MAJOR_VBD_START + 1))
@@ -155,9 +172,13 @@ xlbd_alloc_major_info(int major, int min
 		ptr->type = &xlbd_ide_type;
 		ptr->index = index - XLBD_MAJOR_IDE_START;
 		break;
-	case XLBD_MAJOR_SCSI_RANGE:
-		ptr->type = &xlbd_scsi_type;
-		ptr->index = index - XLBD_MAJOR_SCSI_START;
+	case XLBD_MAJOR_SD_RANGE:
+		ptr->type = &xlbd_sd_type;
+		ptr->index = index - XLBD_MAJOR_SD_START;
+		break;
+	case XLBD_MAJOR_SR_RANGE:
+		ptr->type = &xlbd_sr_type;
+		ptr->index = index - XLBD_MAJOR_SR_START;
 		break;
 	case XLBD_MAJOR_VBD_RANGE:
 		ptr->index = 0;
@@ -213,20 +234,21 @@ xlbd_get_major_info(int major, int minor
 	case IDE7_MAJOR: index = 7; break;
 	case IDE8_MAJOR: index = 8; break;
 	case IDE9_MAJOR: index = 9; break;
-	case SCSI_DISK0_MAJOR: index = 10; break;
+	case SCSI_DISK0_MAJOR: index = XLBD_MAJOR_SD_START; break;
 	case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
-		index = 11 + major - SCSI_DISK1_MAJOR;
+		index = XLBD_MAJOR_SD_START + 1 + major - SCSI_DISK1_MAJOR;
 		break;
-        case SCSI_DISK8_MAJOR ... SCSI_DISK15_MAJOR:
-                index = 18 + major - SCSI_DISK8_MAJOR;
-                break;
-        case SCSI_CDROM_MAJOR: index = 26; break;
-        default:
-		if (!VDEV_IS_EXTENDED(vdevice))
-			index = 27;
-		else
-			index = 28;
+	case SCSI_DISK8_MAJOR ... SCSI_DISK15_MAJOR:
+		index = XLBD_MAJOR_SD_START + 8 + major - SCSI_DISK8_MAJOR;
+		break;
+	case SCSI_CDROM_MAJOR:
+		index = XLBD_MAJOR_SR_START;
 		break;
+	case XENVBD_MAJOR:
+		index = XLBD_MAJOR_VBD_START + !!VDEV_IS_EXTENDED(vdevice);
+		break;
+	default:
+		return NULL;
 	}
 
 	mi = ((major_info[index] != NULL) ? major_info[index] :
@@ -324,6 +346,14 @@ xlbd_release_minors(struct xlbd_major_in
 	spin_unlock(&ms->lock);
 }
 
+static char *encode_disk_name(char *ptr, unsigned int n)
+{
+	if (n >= 26)
+		ptr = encode_disk_name(ptr, n / 26 - 1);
+	*ptr = ''a'' + n % 26;
+	return ptr + 1;
+}
+
 static int
 xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
 		     struct blkfront_info *info)
@@ -369,6 +399,7 @@ xlvbd_alloc_gendisk(int major, int minor
 	struct xlbd_major_info *mi;
 	int nr_minors = 1;
 	int err = -ENODEV;
+	char *ptr;
 	unsigned int offset;
 
 	BUG_ON(info->gd != NULL);
@@ -392,33 +423,21 @@ xlvbd_alloc_gendisk(int major, int minor
 	if (gd == NULL)
 		goto release;
 
-	offset =  mi->index * mi->type->disks_per_major +
-			(minor >> mi->type->partn_shift);
-	if (nr_minors > 1) {
-		if (offset < 26) {
-			sprintf(gd->disk_name, "%s%c",
-				 mi->type->diskname, ''a'' + offset );
-		}
-		else {
-			sprintf(gd->disk_name, "%s%c%c",
-				mi->type->diskname,
-				''a'' + ((offset/26)-1), ''a'' +
(offset%26) );
-		}
-	}
-	else {
-		if (offset < 26) {
-			sprintf(gd->disk_name, "%s%c%d",
-				mi->type->diskname,
-				''a'' + offset,
-				minor & ((1 << mi->type->partn_shift) - 1));
-		}
-		else {
-			sprintf(gd->disk_name, "%s%c%c%d",
-				mi->type->diskname,
-				''a'' + ((offset/26)-1), ''a'' +
(offset%26),
-				minor & ((1 << mi->type->partn_shift) - 1));
-		}
-	}
+	strcpy(gd->disk_name, mi->type->diskname);
+	ptr = gd->disk_name + strlen(mi->type->diskname);
+	offset = mi->index * mi->type->disks_per_major +
+		 (minor >> mi->type->partn_shift);
+	if (mi->type->partn_shift) {
+		ptr = encode_disk_name(ptr, offset);
+		offset = minor & ((1 << mi->type->partn_shift) - 1);
+	} else
+		gd->flags |= GENHD_FL_CD;
+	BUG_ON(ptr >= gd->disk_name + ARRAY_SIZE(gd->disk_name));
+	if (nr_minors > 1)
+		*ptr = 0;
+	else
+		snprintf(ptr, gd->disk_name + ARRAY_SIZE(gd->disk_name) - ptr,
+			 "%u", offset);
 
 	gd->major = mi->major;
 	gd->first_minor = minor;
@@ -478,6 +497,11 @@ xlvbd_add(blkif_sector_t capacity, int v
 	else {
 		major = XENVBD_MAJOR;
 		minor = BLKIF_MINOR_EXT(vdevice);
+		if (minor >> MINORBITS) {
+			printk(KERN_WARNING "blkfront: %#x''s minor (%#x)"
+			       " out of range; ignoring\n", vdevice, minor);
+			return -ENODEV;
+		}
 	}
 
 	info->dev = MKDEV(major, minor);
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel