changeset 13642:8107b374f945

1844 xen: "disk_link: invalid disk device number" Reviewed by: Dmitry.Yusupov@nexenta.com Reviewed by: Albert Lee <trisk@nexenta.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Approved by: Garrett D'Amore <garrett@damore.org>
author Vitaliy Gusev <gusev.vitaliy@nexenta.com>
date Tue, 20 Mar 2012 15:29:39 -0700
parents 9efb7f317b8a
children 837d1b6404bf
files usr/src/cmd/devfsadm/disk_link.c
diffstat 1 files changed, 82 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/devfsadm/disk_link.c	Sat Mar 17 14:03:50 2012 -0500
+++ b/usr/src/cmd/devfsadm/disk_link.c	Tue Mar 20 15:29:39 2012 -0700
@@ -19,6 +19,7 @@
  * CDDL HEADER END
  */
 /*
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -319,51 +320,102 @@
 /*
  * xVM virtual block device
  *
- * VBDs are enumerated into xenstore by xend and named using
- * the linux dev_t values for 'hd' and 'xvd' devices.  Linux
- * dev_t's are 16-bit values.  The upper 8 bits identify the major #
- * of the device (hd, xvd) and the lower 8 bits the instance and partition
+ * Xen passes device number in next format:
  *
- * For PV guests, VBDs are named by the virt-tools using
- * the form xvd[a-p][1-15].  The corresponding Solaris /dev/dsk name
- * created by this generator will be c0t[0-15]d[0-15]sN,
- * were the target (t) value represents [a-p] and the
- * disk (d) value is either 0 (e.g. xvda) or contains the partition
- * information if it has been specified [1-15] (e.g. xvda1)
+ *    1 << 28 | disk << 8 | partition      xvd, disks or partitions 16 onwards
+ *  202 <<  8 | disk << 4 | partition      xvd, disks and partitions up to 15
+ *    8 <<  8 | disk << 4 | partition      sd, disks and partitions up to 15
+ *    3 <<  8 | disk << 6 | partition      hd, disks 0..1, partitions 0..63
+ *   22 <<  8 | (disk-2) << 6 | partition  hd, disks 2..3, partitions 0..63
+ *    2 << 28 onwards                      reserved for future use
+ *   other values less than 1 << 28        deprecated / reserved
+ *
+ * The corresponding Solaris /dev/dsk name can be:
+ *
+ *          c0tYdXsN
+ *
+ * where Y,X >= 0.
  *
  * For PV guests using the legacy naming (0, 1, 2, ...)
  * the Solaris disk names created will be c0d[0..767]sN
- * The Solaris version of virt-install based on virtinst.101
- * named PV disks as sequential integers.  With virtinst.300_1 and
- * beyond, the virt-* tools will no longer create legacy disk
- * names.
+ */
+
+#define	HD_BASE		(3 << 8)
+#define	XEN_EXT_SHIFT	(28)
+
+/*
+ * Return: Number of parsed and written parameters
  */
 static int
+decode_xen_device(uint_t device, uint_t *disk, uint_t *plun)
+{
+	uint_t dsk, lun = 0;
+	int ret = 1;
+
+	if ((device >> XEN_EXT_SHIFT) > 1)
+		return (0);
+
+	if (device < HD_BASE) {
+		/* legacy device address */
+		dsk = device;
+		goto end;
+	}
+
+	ret = 2;
+	if (device & (1 << XEN_EXT_SHIFT)) {
+		/* extended */
+		dsk = device & (~0xff);
+		lun = device & 0xff;
+		goto end;
+	}
+
+	switch (device >> 8) {
+	case 202:				/* xvd */
+		dsk = (device >> 4) & 0xf;
+		lun =  device & 0xf;
+		break;
+	case 8:					/* sd */
+		dsk = device & (~0xf);
+		lun = device & 0xf;
+		break;
+	case 3:					/* hd, disk 0..1 */
+		dsk = device & (~0x3f);
+		lun = device & 0x3f;
+		break;
+	case 22:				/* hd, disk 2..3 */
+		dsk = device & (~0x3f);
+		lun = device & 0x3f;
+		break;
+	default:
+		return (0);
+	}
+end:
+	*disk = dsk;
+	*plun = lun;
+	return (ret);
+}
+
+static int
 disk_callback_xvmd(di_minor_t minor, di_node_t node)
 {
-#define	HD_BASE (3 << 8)
-#define	XVBDMAJ 202
-
 	char *addr;
 	char disk[16];
 	uint_t targ;
-	uint_t lun = 0;
-	uint_t fmaj;
+	uint_t dsk, lun;
+	int res;
 
 	addr = di_bus_addr(node);
 	targ = strtol(addr, (char **)NULL, 10);
-	fmaj = targ >> 8;
+
+	res = decode_xen_device(targ, &dsk, &lun);
+
+	/* HVM device names are generated using the standard generator */
 
-	/* legacy device address */
-	if (targ < HD_BASE)
-		(void) snprintf(disk, sizeof (disk),  "d%d", targ);
-	/* PV VBD */
-	else if (fmaj == XVBDMAJ) {
-		lun = targ & 0xf;
-		targ = (targ & 0xff) >> 4;
-		(void) snprintf(disk, sizeof (disk), "t%dd%d", targ, lun);
-	/* HVM device names are generated using the standard generator */
-	} else {
+	if (res == 1)
+		(void) snprintf(disk, sizeof (disk),  "d%d", dsk);
+	else if (res == 2)
+		(void) snprintf(disk, sizeof (disk), "t%dd%d", dsk, lun);
+	else {
 		devfsadm_errprint("%s: invalid disk device number (%s)\n",
 		    modname, addr);
 		return (DEVFSADM_CONTINUE);