Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/xen/xenbus Sort vif and vbd device IDs numerically ...



details:   https://anonhg.NetBSD.org/src/rev/f5712b4fbc2e
branches:  trunk
changeset: 779610:f5712b4fbc2e
user:      sborrill <sborrill%NetBSD.org@localhost>
date:      Tue Jun 05 10:58:56 2012 +0000

description:
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@

diffstat:

 sys/arch/xen/xenbus/xenbus_probe.c |  62 +++++++++++++++++++++++++++++++++++--
 1 files changed, 58 insertions(+), 4 deletions(-)

diffs (98 lines):

diff -r a606476c5d41 -r f5712b4fbc2e sys/arch/xen/xenbus/xenbus_probe.c
--- a/sys/arch/xen/xenbus/xenbus_probe.c        Tue Jun 05 08:49:16 2012 +0000
+++ b/sys/arch/xen/xenbus/xenbus_probe.c        Tue Jun 05 10:58:56 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xenbus_probe.c,v 1.35 2011/09/22 23:02:35 jym Exp $ */
+/* $NetBSD: xenbus_probe.c,v 1.36 2012/06/05 10:58:56 sborrill 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.35 2011/09/22 23:02:35 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.36 2012/06/05 10:58:56 sborrill Exp $");
 
 #if 0
 #define DPRINTK(fmt, args...) \
@@ -321,7 +321,8 @@
 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;
@@ -335,8 +336,58 @@
        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++) {
+                       id[i] = strtoul(dir[i], &ep, 10);
+                       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.
@@ -413,6 +464,9 @@
                watch_otherend(xbusd);
        }
        free(dir, M_DEVBUF);
+       if (lookup)
+               free(lookup, M_DEVBUF);
+       
        return err;
 }
 



Home | Main Index | Thread Index | Old Index