Module Name:    src
Committed By:   riz
Date:           Tue Jun 12 20:48:58 UTC 2012

Modified Files:
        src/sys/arch/xen/xenbus [netbsd-5]: xenbus_probe.c

Log Message:
Pull up following revision(s) (requested by sborrill in ticket #1768):
        sys/arch/xen/xenbus/xenbus_probe.c: revision 1.36
        sys/arch/xen/xenbus/xenbus_probe.c: revision 1.37
Sort vif and vbd device IDs numerically so that attach order does not depend
on the order they are passed in through xenstore. While this works for
hand-crafted Xen configuration files, it does not work for XenServer, XCP or
EC2 instances. This means that adding an extra virtual disk can make the
domU unbootable.
ID is actually based on the Linux device major/minor so this approach isn't
entirely correct (for instance, you can specify devices to be non-contiguous
which doesn't fit too well with our autoconf approach), but it works as a
first approximation.
Tested by me on XenServer and riz@ on EC2. OK bouyer@
Fix problem where devices with ID 0 were skipped as invalid as it didn't
distinguish between numerical zero and invalid numeric string.


To generate a diff of this commit:
cvs rdiff -u -r1.26.2.4 -r1.26.2.5 src/sys/arch/xen/xenbus/xenbus_probe.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xenbus/xenbus_probe.c
diff -u src/sys/arch/xen/xenbus/xenbus_probe.c:1.26.2.4 src/sys/arch/xen/xenbus/xenbus_probe.c:1.26.2.5
--- src/sys/arch/xen/xenbus/xenbus_probe.c:1.26.2.4	Fri Sep 23 12:44:52 2011
+++ src/sys/arch/xen/xenbus/xenbus_probe.c	Tue Jun 12 20:48:58 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: xenbus_probe.c,v 1.26.2.4 2011/09/23 12:44:52 sborrill Exp $ */
+/* $NetBSD: xenbus_probe.c,v 1.26.2.5 2012/06/12 20:48:58 riz Exp $ */
 /******************************************************************************
  * Talks to Xen Store to figure out what devices we have.
  *
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.26.2.4 2011/09/23 12:44:52 sborrill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.26.2.5 2012/06/12 20:48:58 riz Exp $");
 
 #if 0
 #define DPRINTK(fmt, args...) \
@@ -269,7 +269,8 @@ static int
 xenbus_probe_device_type(const char *path, const char *type,
     int (*create)(struct xenbus_device *))
 {
-	int err, i, msize;
+	int err, i, pos, msize;
+	int *lookup = NULL;
 	unsigned long state;
 	char **dir;
 	unsigned int dir_n = 0;
@@ -283,8 +284,62 @@ xenbus_probe_device_type(const char *pat
 	if (err)
 		return err;
 
-	for (i = 0; i < dir_n; i++) {
+	/* Only sort frontend devices i.e. create == NULL*/
+	if (dir_n > 1 && create == NULL) {
+		int minp;
+		unsigned long minv;
+		unsigned long *id;
+
+		lookup = malloc(sizeof(int) * dir_n, M_DEVBUF,
+		    M_WAITOK | M_ZERO);
+		if (lookup == NULL)
+			panic("can't malloc lookup");
+
+		id = malloc(sizeof(unsigned long) * dir_n, M_DEVBUF,
+		    M_WAITOK | M_ZERO);
+		if (id == NULL)
+			panic("can't malloc id");
+
+		/* Convert string values to numeric; skip invalid */
+		for (i = 0; i < dir_n; i++) {
+			/*
+			 * Add one to differentiate numerical zero from invalid
+			 * string. Has no effect on sort order.
+			 */
+			id[i] = strtoul(dir[i], &ep, 10) + 1;
+			if (dir[i][0] == '\0' || *ep != '\0')
+				id[i] = 0;
+		}
+		
+		/* Build lookup table in ascending order */
+		for (pos = 0; pos < dir_n; ) {
+			minv = UINT32_MAX;
+			minp = -1;
+			for (i = 0; i < dir_n; i++) {
+				if (id[i] < minv && id[i] > 0) {
+					minv = id[i];
+					minp = i;
+				}
+			}
+			if (minp >= 0) {
+				lookup[pos++] = minp;
+				id[minp] = 0;
+			}
+			else
+				break;
+		}
+		
+		free(id, M_DEVBUF);
+		/* Adjust in case we had to skip non-numeric entries */
+		dir_n = pos;
+	}
+
+	for (pos = 0; pos < dir_n; pos++) {
 		err = 0;
+		if (lookup)
+			i = lookup[pos];
+		else
+			i = pos;
 		/*
 		 * add size of path to size of xenbus_device. xenbus_device
 		 * already has room for one char in xbusd_path.
@@ -361,6 +416,9 @@ xenbus_probe_device_type(const char *pat
 		talk_to_otherend(xbusd);
 	}
 	free(dir, M_DEVBUF);
+	if (lookup)
+		free(lookup, M_DEVBUF);
+	
 	return err;
 }
 

Reply via email to