[libvirt] PATCH: 5 of 5: Remove domain devices linked lists

Daniel P. Berrange berrange at redhat.com
Fri Oct 3 12:29:44 UTC 2008


This one isn't strictly needed yet, but while we're removing linked lists
we might as well kill off all of them. So this removes the linked lists
for devices associated with a domain.

 src/domain_conf.c                       |  244 +++++++++++++++-----------------
 src/domain_conf.h                       |   47 +++---
 src/lxc_container.c                     |   38 ++--
 src/lxc_controller.c                    |   11 -
 src/lxc_driver.c                        |   29 +--
 src/openvz_conf.c                       |   35 ++--
 src/openvz_driver.c                     |   36 ++--
 src/qemu_conf.c                         |   57 ++-----
 src/qemu_driver.c                       |   79 ++++------
 src/xend_internal.c                     |  214 +++++++++++++---------------
 src/xend_internal.h                     |    2 
 src/xm_internal.c                       |  228 ++++++++++++-----------------
 tests/sexpr2xmldata/sexpr2xml-fv-v2.xml |   10 -
 13 files changed, 480 insertions(+), 550 deletions(-)

Daniel

diff -r 44cb26ad18bc src/domain_conf.c
--- a/src/domain_conf.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/domain_conf.c	Fri Oct 03 12:44:51 2008 +0100
@@ -230,7 +230,6 @@
     if (!def)
         return;
 
-    virDomainInputDefFree(def->next);
     VIR_FREE(def);
 }
 
@@ -244,7 +243,6 @@
     VIR_FREE(def->driverName);
     VIR_FREE(def->driverType);
 
-    virDomainDiskDefFree(def->next);
     VIR_FREE(def);
 }
 
@@ -256,7 +254,6 @@
     VIR_FREE(def->src);
     VIR_FREE(def->dst);
 
-    virDomainFSDefFree(def->next);
     VIR_FREE(def);
 }
 
@@ -290,7 +287,6 @@
     }
 
     VIR_FREE(def->ifname);
-    virDomainNetDefFree(def->next);
     VIR_FREE(def);
 }
 
@@ -324,7 +320,6 @@
         break;
     }
 
-    virDomainChrDefFree(def->next);
     VIR_FREE(def);
 }
 
@@ -333,7 +328,6 @@
     if (!def)
         return;
 
-    virDomainSoundDefFree(def->next);
     VIR_FREE(def);
 }
 
@@ -343,7 +337,6 @@
         return;
 
     VIR_FREE(def->target);
-    virDomainHostdevDefFree(def->next);
     VIR_FREE(def);
 }
 
@@ -375,19 +368,45 @@
 
 void virDomainDefFree(virDomainDefPtr def)
 {
+    unsigned int i;
+
     if (!def)
         return;
 
     virDomainGraphicsDefFree(def->graphics);
-    virDomainInputDefFree(def->inputs);
-    virDomainDiskDefFree(def->disks);
-    virDomainFSDefFree(def->fss);
-    virDomainNetDefFree(def->nets);
-    virDomainChrDefFree(def->serials);
-    virDomainChrDefFree(def->parallels);
+
+    for (i = 0 ; i < def->ninputs ; i++)
+        virDomainInputDefFree(def->inputs[i]);
+    VIR_FREE(def->inputs);
+
+    for (i = 0 ; i < def->ndisks ; i++)
+        virDomainDiskDefFree(def->disks[i]);
+    VIR_FREE(def->disks);
+
+    for (i = 0 ; i < def->nfss ; i++)
+        virDomainFSDefFree(def->fss[i]);
+    VIR_FREE(def->fss);
+
+    for (i = 0 ; i < def->nnets ; i++)
+        virDomainNetDefFree(def->nets[i]);
+    VIR_FREE(def->nets);
+    for (i = 0 ; i < def->nserials ; i++)
+        virDomainChrDefFree(def->serials[i]);
+    VIR_FREE(def->serials);
+
+    for (i = 0 ; i < def->nparallels ; i++)
+        virDomainChrDefFree(def->parallels[i]);
+    VIR_FREE(def->parallels);
+
     virDomainChrDefFree(def->console);
-    virDomainSoundDefFree(def->sounds);
-    virDomainHostdevDefFree(def->hostdevs);
+
+    for (i = 0 ; i < def->nsounds ; i++)
+        virDomainSoundDefFree(def->sounds[i]);
+    VIR_FREE(def->sounds);
+
+    for (i = 0 ; i < def->nhostdevs ; i++)
+        virDomainHostdevDefFree(def->hostdevs[i]);
+    VIR_FREE(def->hostdevs);
 
     VIR_FREE(def->os.type);
     VIR_FREE(def->os.arch);
@@ -1695,6 +1714,14 @@
     return NULL;
 }
 
+int virDomainDiskQSort(const void *a, const void *b)
+{
+    const virDomainDiskDefPtr *da = a;
+    const virDomainDiskDefPtr *db = b;
+
+    return virDomainDiskCompare(*da, *db);
+}
+
 
 static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
                                             virCapsPtr caps,
@@ -1936,36 +1963,18 @@
                              "%s", _("cannot extract disk devices"));
         goto error;
     }
+    if (n && VIR_ALLOC_N(def->disks, n) < 0)
+        goto no_memory;
     for (i = 0 ; i < n ; i++) {
         virDomainDiskDefPtr disk = virDomainDiskDefParseXML(conn,
                                                             nodes[i]);
         if (!disk)
             goto error;
 
-        /* Maintain list in sorted order according to target device name */
-        virDomainDiskDefPtr ptr = def->disks;
-        virDomainDiskDefPtr *prev = &(def->disks);
-        while (ptr) {
-            if (STREQ(disk->dst, ptr->dst)) {
-                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                                     _("duplicate disk target '%s'"),
-                                     disk->dst);
-                goto error;
-            }
-            if (virDomainDiskCompare(disk, ptr) < 0) {
-                disk->next = ptr;
-                *prev = disk;
-                break;
-            }
-            prev = &(ptr->next);
-            ptr = ptr->next;
-        }
-
-        if (!ptr) {
-            disk->next = ptr;
-            *prev = disk;
-        }
+        def->disks[def->ndisks++] = disk;
     }
+    qsort(def->disks, def->ndisks, sizeof(*def->disks),
+          virDomainDiskQSort);
     VIR_FREE(nodes);
 
     /* analysis of the filesystems */
@@ -1974,14 +1983,15 @@
                              "%s", _("cannot extract filesystem devices"));
         goto error;
     }
-    for (i = n - 1 ; i >= 0 ; i--) {
+    if (n && VIR_ALLOC_N(def->fss, n) < 0)
+        goto no_memory;
+    for (i = 0 ; i < n ; i++) {
         virDomainFSDefPtr fs = virDomainFSDefParseXML(conn,
                                                       nodes[i]);
         if (!fs)
             goto error;
 
-        fs->next = def->fss;
-        def->fss = fs;
+        def->fss[def->nfss++] = fs;
     }
     VIR_FREE(nodes);
 
@@ -1991,14 +2001,15 @@
                              "%s", _("cannot extract network devices"));
         goto error;
     }
-    for (i = n - 1 ; i >= 0 ; i--) {
+    if (n && VIR_ALLOC_N(def->nets, n) < 0)
+        goto no_memory;
+    for (i = 0 ; i < n ; i++) {
         virDomainNetDefPtr net = virDomainNetDefParseXML(conn,
                                                          nodes[i]);
         if (!net)
             goto error;
 
-        net->next = def->nets;
-        def->nets = net;
+        def->nets[def->nnets++] = net;
     }
     VIR_FREE(nodes);
 
@@ -2009,15 +2020,17 @@
                              "%s", _("cannot extract parallel devices"));
         goto error;
     }
-    for (i = n - 1 ; i >= 0 ; i--) {
+    if (n && VIR_ALLOC_N(def->parallels, n) < 0)
+        goto no_memory;
+
+    for (i = 0 ; i < n ; i++) {
         virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
                                                          nodes[i]);
         if (!chr)
             goto error;
 
         chr->dstPort = i;
-        chr->next = def->parallels;
-        def->parallels = chr;
+        def->parallels[def->nparallels++] = chr;
     }
     VIR_FREE(nodes);
 
@@ -2026,15 +2039,17 @@
                              "%s", _("cannot extract serial devices"));
         goto error;
     }
-    for (i = n - 1 ; i >= 0 ; i--) {
+    if (n && VIR_ALLOC_N(def->serials, n) < 0)
+        goto no_memory;
+
+    for (i = 0 ; i < n ; i++) {
         virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
                                                          nodes[i]);
         if (!chr)
             goto error;
 
         chr->dstPort = i;
-        chr->next = def->serials;
-        def->serials = chr;
+        def->serials[def->nserials++] = chr;
     }
     VIR_FREE(nodes);
 
@@ -2042,7 +2057,7 @@
      * If no serial devices were listed, then look for console
      * devices which is the legacy syntax for the same thing
      */
-    if (def->serials == NULL) {
+    if (def->nserials == 0) {
         if ((node = virXPathNode(conn, "./devices/console[1]", ctxt)) != NULL) {
             virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
                                                              node);
@@ -2055,8 +2070,12 @@
              * while for non-HVM it was a parvirt console
              */
             if (STREQ(def->os.type, "hvm")) {
-                chr->next = def->serials;
-                def->serials = chr;
+                if (VIR_ALLOC_N(def->serials, 1) < 0) {
+                    virDomainChrDefFree(chr);
+                    goto no_memory;
+                }
+                def->nserials = 1;
+                def->serials[0] = chr;
             } else {
                 def->console = chr;
             }
@@ -2070,7 +2089,10 @@
                              "%s", _("cannot extract input devices"));
         goto error;
     }
-    for (i = n - 1 ; i >= 0 ; i--) {
+    if (n && VIR_ALLOC_N(def->inputs, n) < 0)
+        goto no_memory;
+
+    for (i = 0 ; i < n ; i++) {
         virDomainInputDefPtr input = virDomainInputDefParseXML(conn,
                                                                def->os.type,
                                                                nodes[i]);
@@ -2091,8 +2113,7 @@
             continue;
         }
 
-        input->next = def->inputs;
-        def->inputs = input;
+        def->inputs[def->ninputs++] = input;
     }
     VIR_FREE(nodes);
 
@@ -2127,8 +2148,13 @@
             input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
             input->bus = VIR_DOMAIN_INPUT_BUS_XEN;
         }
-        input->next = def->inputs;
-        def->inputs = input;
+
+        if (VIR_REALLOC_N(def->inputs, def->ninputs + 1) < 0) {
+            virDomainInputDefFree(input);
+            goto no_memory;
+        }
+        def->inputs[def->ninputs] = input;
+        def->ninputs++;
     }
 
 
@@ -2138,28 +2164,26 @@
                              "%s", _("cannot extract sound devices"));
         goto error;
     }
-    for (i = n - 1 ; i >= 0 ; i--) {
-        int collision = 0;
-        virDomainSoundDefPtr check;
+    if (n && VIR_ALLOC_N(def->sounds, n) < 0)
+        goto no_memory;
+    for (i = 0 ; i < n ; i++) {
+        int collision = 0, j;
         virDomainSoundDefPtr sound = virDomainSoundDefParseXML(conn,
                                                                nodes[i]);
         if (!sound)
             goto error;
 
         /* Verify there's no duplicated sound card */
-        check = def->sounds;
-        while (check) {
-            if (check->model == sound->model)
+        for (j = 0 ; j < def->nsounds ; j++) {
+            if (def->sounds[j]->model == sound->model)
                 collision = 1;
-            check = check->next;
         }
         if (collision) {
             virDomainSoundDefFree(sound);
             continue;
         }
 
-        sound->next = def->sounds;
-        def->sounds = sound;
+        def->sounds[def->nsounds++] = sound;
     }
     VIR_FREE(nodes);
 
@@ -2169,17 +2193,22 @@
                              "%s", _("cannot extract host devices"));
         goto error;
     }
+    if (n && VIR_ALLOC_N(def->hostdevs, n) < 0)
+        goto no_memory;
     for (i = 0 ; i < n ; i++) {
         virDomainHostdevDefPtr hostdev = virDomainHostdevDefParseXML(conn, nodes[i]);
         if (!hostdev)
             goto error;
 
-        hostdev->next = def->hostdevs;
-        def->hostdevs = hostdev;
+        def->hostdevs[def->nhostdevs++] = hostdev;
     }
     VIR_FREE(nodes);
 
     return def;
+
+no_memory:
+    virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL);
+    /* fallthrough */
 
  error:
     VIR_FREE(tmp);
@@ -2971,13 +3000,6 @@
     virBuffer buf = VIR_BUFFER_INITIALIZER;
     unsigned char *uuid;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
-    virDomainDiskDefPtr disk;
-    virDomainFSDefPtr fs;
-    virDomainNetDefPtr net;
-    virDomainSoundDefPtr sound;
-    virDomainInputDefPtr input;
-    virDomainChrDefPtr chr;
-    virDomainHostdevDefPtr hostdev;
     const char *type = NULL, *tmp;
     int n, allones = 1;
 
@@ -3114,67 +3136,49 @@
         virBufferEscapeString(&buf, "    <emulator>%s</emulator>\n",
                               def->emulator);
 
-    disk = def->disks;
-    while (disk) {
-        if (virDomainDiskDefFormat(conn, &buf, disk) < 0)
+    for (n = 0 ; n < def->ndisks ; n++)
+        if (virDomainDiskDefFormat(conn, &buf, def->disks[n]) < 0)
             goto cleanup;
-        disk = disk->next;
-    }
 
-    fs = def->fss;
-    while (fs) {
-        if (virDomainFSDefFormat(conn, &buf, fs) < 0)
+    for (n = 0 ; n < def->nfss ; n++)
+        if (virDomainFSDefFormat(conn, &buf, def->fss[n]) < 0)
             goto cleanup;
-        fs = fs->next;
-    }
 
-    net = def->nets;
-    while (net) {
-        if (virDomainNetDefFormat(conn, &buf, net) < 0)
+
+    for (n = 0 ; n < def->nnets ; n++)
+        if (virDomainNetDefFormat(conn, &buf, def->nets[n]) < 0)
             goto cleanup;
-        net = net->next;
-    }
 
+    for (n = 0 ; n < def->nserials ; n++)
+        if (virDomainChrDefFormat(conn, &buf, def->serials[n], "serial") < 0)
+            goto cleanup;
 
-    chr = def->serials;
-    while (chr) {
-        if (virDomainChrDefFormat(conn, &buf, chr, "serial") < 0)
+    for (n = 0 ; n < def->nparallels ; n++)
+        if (virDomainChrDefFormat(conn, &buf, def->parallels[n], "parallel") < 0)
             goto cleanup;
-        chr = chr->next;
-    }
-
-    chr = def->parallels;
-    while (chr) {
-        if (virDomainChrDefFormat(conn, &buf, chr, "parallel") < 0)
-            goto cleanup;
-        chr = chr->next;
-    }
 
     /* If there's a PV console that's preferred.. */
     if (def->console) {
         if (virDomainChrDefFormat(conn, &buf, def->console, "console") < 0)
             goto cleanup;
-    } else if (def->serials != NULL) {
+    } else if (def->nserials != 0) {
         /* ..else for legacy compat duplicate the serial device as a console */
-        if (virDomainChrDefFormat(conn, &buf, def->serials, "console") < 0)
+        if (virDomainChrDefFormat(conn, &buf, def->serials[n], "console") < 0)
             goto cleanup;
     }
 
-    input = def->inputs;
-    while (input) {
-        if (input->bus == VIR_DOMAIN_INPUT_BUS_USB &&
-            virDomainInputDefFormat(conn, &buf, input) < 0)
+    for (n = 0 ; n < def->ninputs ; n++)
+        if (def->inputs[n]->bus == VIR_DOMAIN_INPUT_BUS_USB &&
+            virDomainInputDefFormat(conn, &buf, def->inputs[n]) < 0)
             goto cleanup;
-        input = input->next;
-    }
 
     if (def->graphics) {
         /* If graphics is enabled, add the implicit mouse */
         virDomainInputDef autoInput = {
             VIR_DOMAIN_INPUT_TYPE_MOUSE,
             STREQ(def->os.type, "hvm") ?
-            VIR_DOMAIN_INPUT_BUS_PS2 : VIR_DOMAIN_INPUT_BUS_XEN,
-            NULL };
+            VIR_DOMAIN_INPUT_BUS_PS2 : VIR_DOMAIN_INPUT_BUS_XEN
+        };
 
         if (virDomainInputDefFormat(conn, &buf, &autoInput) < 0)
             goto cleanup;
@@ -3183,19 +3187,13 @@
             goto cleanup;
     }
 
-    sound = def->sounds;
-    while(sound) {
-        if (virDomainSoundDefFormat(conn, &buf, sound) < 0)
+    for (n = 0 ; n < def->nsounds ; n++)
+        if (virDomainSoundDefFormat(conn, &buf, def->sounds[n]) < 0)
             goto cleanup;
-        sound = sound->next;
-    }
 
-    hostdev = def->hostdevs;
-    while (hostdev) {
-        if (virDomainHostdevDefFormat(conn, &buf, hostdev) < 0)
+    for (n = 0 ; n < def->nhostdevs ; n++)
+        if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n]) < 0)
             goto cleanup;
-        hostdev = hostdev->next;
-    }
 
     virBufferAddLit(&buf, "  </devices>\n");
     virBufferAddLit(&buf, "</domain>\n");
diff -r 44cb26ad18bc src/domain_conf.h
--- a/src/domain_conf.h	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/domain_conf.h	Fri Oct 03 12:44:51 2008 +0100
@@ -90,8 +90,6 @@
     char *driverType;
     unsigned int readonly : 1;
     unsigned int shared : 1;
-
-    virDomainDiskDefPtr next;
 };
 
 
@@ -112,8 +110,6 @@
     char *src;
     char *dst;
     unsigned int readonly : 1;
-
-    virDomainFSDefPtr next;
 };
 
 
@@ -158,8 +154,6 @@
         } bridge;
     } data;
     char *ifname;
-
-    virDomainNetDefPtr next;
 };
 
 enum virDomainChrSrcType {
@@ -211,8 +205,6 @@
             int listen;
         } nix;
     } data;
-
-    virDomainChrDefPtr next;
 };
 
 enum virDomainInputType {
@@ -235,7 +227,6 @@
 struct _virDomainInputDef {
     int type;
     int bus;
-    virDomainInputDefPtr next;
 };
 
 enum virDomainSoundModel {
@@ -250,7 +241,6 @@
 typedef virDomainSoundDef *virDomainSoundDefPtr;
 struct _virDomainSoundDef {
     int model;
-    virDomainSoundDefPtr next;
 };
 
 /* 3 possible graphics console modes */
@@ -324,7 +314,6 @@
         } caps;
     } source;
     char* target;
-    virDomainHostdevDefPtr next;
 };
 
 /* Flags for the 'type' field in next struct */
@@ -428,15 +417,34 @@
 
     int localtime;
 
+    /* Only 1 */
     virDomainGraphicsDefPtr graphics;
-    virDomainDiskDefPtr disks;
-    virDomainFSDefPtr fss;
-    virDomainNetDefPtr nets;
-    virDomainInputDefPtr inputs;
-    virDomainSoundDefPtr sounds;
-    virDomainHostdevDefPtr hostdevs;
-    virDomainChrDefPtr serials;
-    virDomainChrDefPtr parallels;
+
+    int ndisks;
+    virDomainDiskDefPtr *disks;
+
+    int nfss;
+    virDomainFSDefPtr *fss;
+
+    int nnets;
+    virDomainNetDefPtr *nets;
+
+    int ninputs;
+    virDomainInputDefPtr *inputs;
+
+    int nsounds;
+    virDomainSoundDefPtr *sounds;
+
+    int nhostdevs;
+    virDomainHostdevDefPtr *hostdevs;
+
+    int nserials;
+    virDomainChrDefPtr *serials;
+
+    int nparallels;
+    virDomainChrDefPtr *parallels;
+
+    /* Only 1 */
     virDomainChrDefPtr console;
 };
 
@@ -531,6 +539,7 @@
                             char *cpuset,
                             int maxcpu);
 
+int virDomainDiskQSort(const void *a, const void *b);
 int virDomainDiskCompare(virDomainDiskDefPtr a,
                          virDomainDiskDefPtr b);
 
diff -r 44cb26ad18bc src/lxc_container.c
--- a/src/lxc_container.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/lxc_container.c	Fri Oct 03 12:44:51 2008 +0100
@@ -368,28 +368,28 @@
 
 static int lxcContainerMountNewFS(virDomainDefPtr vmDef)
 {
-    virDomainFSDefPtr tmp;
+    int i;
 
     /* Pull in rest of container's mounts */
-    for (tmp = vmDef->fss; tmp; tmp = tmp->next) {
+    for (i = 0 ; i < vmDef->nfss ; i++) {
         char *src;
-        if (STREQ(tmp->dst, "/"))
+        if (STREQ(vmDef->fss[i]->dst, "/"))
             continue;
         // XXX fix
-        if (tmp->type != VIR_DOMAIN_FS_TYPE_MOUNT)
+        if (vmDef->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
             continue;
 
-        if (asprintf(&src, "/.oldroot/%s", tmp->src) < 0) {
+        if (asprintf(&src, "/.oldroot/%s", vmDef->fss[i]->src) < 0) {
             lxcError(NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
             return -1;
         }
 
-        if (virFileMakePath(tmp->dst) < 0 ||
-            mount(src, tmp->dst, NULL, MS_BIND, NULL) < 0) {
+        if (virFileMakePath(vmDef->fss[i]->dst) < 0 ||
+            mount(src, vmDef->fss[i]->dst, NULL, MS_BIND, NULL) < 0) {
             VIR_FREE(src);
             lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                      _("failed to mount %s at %s for container: %s"),
-                     tmp->src, tmp->dst, strerror(errno));
+                     vmDef->fss[i]->src, vmDef->fss[i]->dst, strerror(errno));
             return -1;
         }
         VIR_FREE(src);
@@ -482,21 +482,21 @@
    but with extra stuff mapped in */
 static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef)
 {
-    virDomainFSDefPtr tmp;
+    int i;
 
-    for (tmp = vmDef->fss; tmp; tmp = tmp->next) {
+    for (i = 0 ; i < vmDef->nfss ; i++) {
         // XXX fix to support other mount types
-        if (tmp->type != VIR_DOMAIN_FS_TYPE_MOUNT)
+        if (vmDef->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
             continue;
 
-        if (mount(tmp->src,
-                  tmp->dst,
+        if (mount(vmDef->fss[i]->src,
+                  vmDef->fss[i]->dst,
                   NULL,
                   MS_BIND,
                   NULL) < 0) {
             lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                      _("failed to mount %s at %s for container: %s"),
-                     tmp->src, tmp->dst, strerror(errno));
+                     vmDef->fss[i]->src, vmDef->fss[i]->dst, strerror(errno));
             return -1;
         }
     }
@@ -514,14 +514,14 @@
 
 static int lxcContainerSetupMounts(virDomainDefPtr vmDef)
 {
-    virDomainFSDefPtr tmp;
+    int i;
     virDomainFSDefPtr root = NULL;
 
-    for (tmp = vmDef->fss; tmp && !root; tmp = tmp->next) {
-        if (tmp->type != VIR_DOMAIN_FS_TYPE_MOUNT)
+    for (i = 0 ; i < vmDef->nfss ; i++) {
+        if (vmDef->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
             continue;
-        if (STREQ(tmp->dst, "/"))
-            root = tmp;
+        if (STREQ(vmDef->fss[i]->dst, "/"))
+            root = vmDef->fss[i];
     }
 
     if (root)
diff -r 44cb26ad18bc src/lxc_controller.c
--- a/src/lxc_controller.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/lxc_controller.c	Fri Oct 03 12:44:51 2008 +0100
@@ -429,8 +429,6 @@
     int bg = 0;
     virCapsPtr caps = NULL;
     virDomainDefPtr def = NULL;
-    int nnets = 0;
-    virDomainNetDefPtr nets = NULL;
     char *configFile = NULL;
     char *sockpath = NULL;
     const struct option const options[] = {
@@ -525,14 +523,9 @@
     if ((def = virDomainDefParseFile(NULL, caps, configFile)) == NULL)
         goto cleanup;
 
-    nets = def->nets;
-    while (nets) {
-        nnets++;
-        nets = nets->next;
-    }
-    if (nnets != nveths) {
+    if (def->nnets != nveths) {
         fprintf(stderr, "%s: expecting %d veths, but got %d\n",
-                argv[0], nnets, nveths);
+                argv[0], def->nnets, nveths);
         goto cleanup;
     }
 
diff -r 44cb26ad18bc src/lxc_driver.c
--- a/src/lxc_driver.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/lxc_driver.c	Fri Oct 03 12:44:51 2008 +0100
@@ -370,7 +370,7 @@
     int rc = -1;
     int waitRc;
     int childStatus = -1;
-    virDomainNetDefPtr net;
+    int i;
 
     while (((waitRc = waitpid(vm->pid, &childStatus, 0)) == -1) &&
            errno == EINTR)
@@ -400,9 +400,9 @@
     vm->def->id = -1;
     vm->monitor = -1;
 
-    for (net = vm->def->nets; net; net = net->next) {
-        vethInterfaceUpOrDown(net->ifname, 0);
-        vethDelete(net->ifname);
+    for (i = 0 ; i < vm->def->nnets ; i++) {
+        vethInterfaceUpOrDown(vm->def->nets[i]->ifname, 0);
+        vethDelete(vm->def->nets[i]->ifname);
     }
 
     return rc;
@@ -423,8 +423,7 @@
                               unsigned int *nveths,
                               char ***veths)
 {
-    int rc = -1;
-    virDomainNetDefPtr net;
+    int rc = -1, i;
     char *bridge = NULL;
     char parentVeth[PATH_MAX] = "";
     char containerVeth[PATH_MAX] = "";
@@ -433,12 +432,12 @@
     if (brInit(&brctl) != 0)
         return -1;
 
-    for (net = def->nets; net; net = net->next) {
-        switch (net->type) {
+    for (i = 0 ; i < def->nnets ; i++) {
+        switch (def->nets[i]->type) {
         case VIR_DOMAIN_NET_TYPE_NETWORK:
         {
             virNetworkPtr network = virNetworkLookupByName(conn,
-                                                           net->data.network.name);
+                                                           def->nets[i]->data.network.name);
             if (!network) {
                 goto error_exit;
             }
@@ -449,7 +448,7 @@
             break;
         }
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
-            bridge = net->data.bridge.brname;
+            bridge = def->nets[i]->data.bridge.brname;
             break;
         }
 
@@ -461,8 +460,8 @@
         }
 
         DEBUG0("calling vethCreate()");
-        if (NULL != net->ifname) {
-            strcpy(parentVeth, net->ifname);
+        if (NULL != def->nets[i]->ifname) {
+            strcpy(parentVeth, def->nets[i]->ifname);
         }
         DEBUG("parentVeth: %s, containerVeth: %s", parentVeth, containerVeth);
         if (0 != (rc = vethCreate(parentVeth, PATH_MAX, containerVeth, PATH_MAX))) {
@@ -470,15 +469,15 @@
                      _("failed to create veth device pair: %d"), rc);
             goto error_exit;
         }
-        if (NULL == net->ifname) {
-            net->ifname = strdup(parentVeth);
+        if (NULL == def->nets[i]->ifname) {
+            def->nets[i]->ifname = strdup(parentVeth);
         }
         if (VIR_REALLOC_N(*veths, (*nveths)+1) < 0)
             goto error_exit;
         if (((*veths)[(*nveths)++] = strdup(containerVeth)) == NULL)
             goto error_exit;
 
-        if (NULL == net->ifname) {
+        if (NULL == def->nets[i]->ifname) {
             lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                      _("failed to allocate veth names"));
             goto error_exit;
diff -r 44cb26ad18bc src/openvz_conf.c
--- a/src/openvz_conf.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/openvz_conf.c	Fri Oct 03 12:44:51 2008 +0100
@@ -171,11 +171,12 @@
     return -1;
 }
 
-static virDomainNetDefPtr
-openvzReadNetworkConf(virConnectPtr conn, int veid) {
+static int
+openvzReadNetworkConf(virConnectPtr conn,
+                      virDomainDefPtr def,
+                      int veid) {
     int ret;
-    virDomainNetDefPtr net = NULL;
-    virDomainNetDefPtr new_net;
+    virDomainNetDefPtr net;
     char temp[4096];
     char *token, *saveptr = NULL;
 
@@ -193,17 +194,19 @@
     } else if (ret > 0) {
         token = strtok_r(temp, " ", &saveptr);
         while (token != NULL) {
-            new_net = NULL;
-            if (VIR_ALLOC(new_net) < 0)
+            if (VIR_ALLOC(net) < 0)
                 goto no_memory;
-            new_net->next = net;
-            net = new_net;
 
             net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
             net->data.ethernet.ipaddr = strdup(token);
 
             if (net->data.ethernet.ipaddr == NULL)
                 goto no_memory;
+
+            if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
+                goto no_memory;
+            def->nets[def->nnets++] = net;
+            net = NULL;
 
             token = strtok_r(NULL, " ", &saveptr);
         }
@@ -224,11 +227,8 @@
         token = strtok_r(temp, ";", &saveptr);
         while (token != NULL) {
             /*add new device to list*/
-            new_net = NULL;
-            if (VIR_ALLOC(new_net) < 0)
+            if (VIR_ALLOC(net) < 0)
                 goto no_memory;
-            new_net->next = net;
-            net = new_net;
 
             net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
 
@@ -278,16 +278,21 @@
                 p = ++next;
             } while (p < token + strlen(token));
 
+            if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
+                goto no_memory;
+            def->nets[def->nnets++] = net;
+            net = NULL;
+
             token = strtok_r(NULL, ";", &saveptr);
         }
     }
 
-    return net;
+    return 0;
 no_memory:
     openvzError(conn, VIR_ERR_NO_MEMORY, NULL);
 error:
     virDomainNetDefFree(net);
-    return NULL;
+    return -1;
 }
 
 
@@ -375,7 +380,7 @@
 
         /* XXX load rest of VM config data .... */
 
-        dom->def->nets = openvzReadNetworkConf(NULL, veid);
+        openvzReadNetworkConf(NULL, dom->def, veid);
 
         if (VIR_REALLOC_N(driver->domains.objs,
                           driver->domains.count + 1) < 0)
diff -r 44cb26ad18bc src/openvz_driver.c
--- a/src/openvz_driver.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/openvz_driver.c	Fri Oct 03 12:44:51 2008 +0100
@@ -117,21 +117,21 @@
     ADD_ARG_LIT("create");
     ADD_ARG_LIT(vmdef->name);
 
-    if (vmdef->fss) {
-        if (vmdef->fss->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) {
+    if (vmdef->nfss) {
+        if (vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) {
             openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("only filesystem templates are supported"));
             return -1;
         }
 
-        if (vmdef->fss->next) {
+        if (vmdef->nfss > 1) {
             openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("only one filesystem supported"));
             return -1;
         }
 
         ADD_ARG_LIT("--ostemplate");
-        ADD_ARG_LIT(vmdef->fss->src);
+        ADD_ARG_LIT(vmdef->fss[0]->src);
     }
 #if 0
     if ((vmdef->profile && *(vmdef->profile))) {
@@ -394,12 +394,6 @@
         }
     }
 
-    if (net->next != NULL)
-       if (openvzDomainSetNetwork(conn, vpsid, net->next) < 0) {
-          rc = -1;
-          goto exit;
-       }
-
  exit:
     cmdExecFree(prog);
     VIR_FREE(mac);
@@ -422,6 +416,7 @@
     virDomainDefPtr vmdef = NULL;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    int i;
     const char *prog[OPENVZ_MAX_ARG];
     prog[0] = NULL;
 
@@ -471,10 +466,12 @@
     if (dom)
         dom->id = -1;
 
-    if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
-        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-                  _("Could not configure network"));
-        goto exit;
+    for (i = 0 ; i < vmdef->nnets ; i++) {
+        if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets[i]) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        _("Could not configure network"));
+            goto exit;
+        }
     }
 
     if (vmdef->vcpus > 0) {
@@ -497,6 +494,7 @@
     virDomainDefPtr vmdef = NULL;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    int i;
     struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
     const char *progstart[] = {VZCTL, "--quiet", "start", NULL, NULL};
     const char *progcreate[OPENVZ_MAX_ARG];
@@ -542,10 +540,12 @@
         goto exit;
     }
 
-    if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
-       openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-                  _("Could not configure network"));
-        goto exit;
+    for (i = 0 ; i < vmdef->nnets ; i++) {
+        if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets[i]) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        _("Could not configure network"));
+            goto exit;
+        }
     }
 
     progstart[3] = vmdef->name;
diff -r 44cb26ad18bc src/qemu_conf.c
--- a/src/qemu_conf.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/qemu_conf.c	Fri Oct 03 12:44:51 2008 +0100
@@ -723,13 +723,6 @@
     char memory[50];
     char vcpus[50];
     char boot[VIR_DOMAIN_BOOT_LAST];
-    virDomainDiskDefPtr disk = vm->def->disks;
-    virDomainNetDefPtr net = vm->def->nets;
-    virDomainInputDefPtr input = vm->def->inputs;
-    virDomainSoundDefPtr sound = vm->def->sounds;
-    virDomainHostdevDefPtr hostdev = vm->def->hostdevs;
-    virDomainChrDefPtr serial = vm->def->serials;
-    virDomainChrDefPtr parallel = vm->def->parallels;
     struct utsname ut;
     int disableKQEMU = 0;
     int qargc = 0, qarga = 0;
@@ -923,10 +916,11 @@
             }
         }
 
-        while (disk) {
+        for (i = 0 ; i < vm->def->ndisks ; i++) {
             char opt[PATH_MAX];
             const char *media = NULL;
             int bootable = 0;
+            virDomainDiskDefPtr disk = vm->def->disks[i];
             int idx = virDiskNameToIndex(disk->dst);
             const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
 
@@ -938,7 +932,6 @@
                                      _("unsupported usb disk type for '%s'"), disk->src);
                     goto error;
                 }
-                disk = disk->next;
                 continue;
             }
 
@@ -974,12 +967,12 @@
 
             ADD_ARG_LIT("-drive");
             ADD_ARG_LIT(opt);
-            disk = disk->next;
         }
     } else {
-        while (disk) {
+        for (i = 0 ; i < vm->def->ndisks ; i++) {
             char dev[NAME_MAX];
             char file[PATH_MAX];
+            virDomainDiskDefPtr disk = vm->def->disks[i];
 
             if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
                 if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
@@ -989,7 +982,6 @@
                                      _("unsupported usb disk type for '%s'"), disk->src);
                     goto error;
                 }
-                disk = disk->next;
                 continue;
             }
 
@@ -998,7 +990,6 @@
                 if (disk->src) {
                     snprintf(dev, NAME_MAX, "-%s", "cdrom");
                 } else {
-                    disk = disk->next;
                     continue;
                 }
             } else {
@@ -1016,18 +1007,17 @@
 
             ADD_ARG_LIT(dev);
             ADD_ARG_LIT(file);
-
-            disk = disk->next;
         }
     }
 
-    if (!net) {
+    if (!vm->def->nnets) {
         ADD_ARG_LIT("-net");
         ADD_ARG_LIT("none");
     } else {
         int vlan = 0;
-        while (net) {
+        for (i = 0 ; i < vm->def->nnets ; i++) {
             char nic[100];
+            virDomainNetDefPtr net = vm->def->nets[i];
 
             if (snprintf(nic, sizeof(nic),
                          "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s%s",
@@ -1108,53 +1098,50 @@
                 }
             }
 
-            net = net->next;
             vlan++;
         }
     }
 
-    if (!serial) {
+    if (!vm->def->nserials) {
         ADD_ARG_LIT("-serial");
         ADD_ARG_LIT("none");
     } else {
-        while (serial) {
+        for (i = 0 ; i < vm->def->nserials ; i++) {
             char buf[4096];
+            virDomainChrDefPtr serial = vm->def->serials[i];
 
             if (qemudBuildCommandLineChrDevStr(serial, buf, sizeof(buf)) < 0)
                 goto error;
 
             ADD_ARG_LIT("-serial");
             ADD_ARG_LIT(buf);
-
-            serial = serial->next;
         }
     }
 
-    if (!parallel) {
+    if (!vm->def->nparallels) {
         ADD_ARG_LIT("-parallel");
         ADD_ARG_LIT("none");
     } else {
-        while (parallel) {
+        for (i = 0 ; i < vm->def->nparallels ; i++) {
             char buf[4096];
+            virDomainChrDefPtr parallel = vm->def->parallels[i];
 
             if (qemudBuildCommandLineChrDevStr(parallel, buf, sizeof(buf)) < 0)
                 goto error;
 
             ADD_ARG_LIT("-parallel");
             ADD_ARG_LIT(buf);
-
-            parallel = parallel->next;
         }
     }
 
     ADD_ARG_LIT("-usb");
-    while (input) {
+    for (i = 0 ; i < vm->def->ninputs ; i++) {
+        virDomainInputDefPtr input = vm->def->inputs[i];
+
         if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
             ADD_ARG_LIT("-usbdevice");
             ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
         }
-
-        input = input->next;
     }
 
     if (vm->def->graphics &&
@@ -1217,13 +1204,14 @@
     }
 
     /* Add sound hardware */
-    if (sound) {
+    if (vm->def->nsounds) {
         int size = 100;
         char *modstr;
         if (VIR_ALLOC_N(modstr, size+1) < 0)
             goto no_memory;
 
-        while(sound && size > 0) {
+        for (i = 0 ; i < vm->def->nsounds && size > 0 ; i++) {
+            virDomainSoundDefPtr sound = vm->def->sounds[i];
             const char *model = virDomainSoundModelTypeToString(sound->model);
             if (!model) {
                 VIR_FREE(modstr);
@@ -1233,8 +1221,7 @@
             }
             strncat(modstr, model, size);
             size -= strlen(model);
-            sound = sound->next;
-            if (sound)
+            if (i < (vm->def->nsounds - 1))
                strncat(modstr, ",", size--);
         }
         ADD_ARG_LIT("-soundhw");
@@ -1242,9 +1229,10 @@
     }
 
     /* Add host passthrough hardware */
-    while (hostdev) {
+    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
         int ret;
         char* usbdev;
+        virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
 
         if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
             hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
@@ -1266,7 +1254,6 @@
             ADD_ARG_LIT(usbdev);
             VIR_FREE(usbdev);
         }
-        hostdev = hostdev->next;
     }
 
     if (migrateFrom) {
diff -r 44cb26ad18bc src/qemu_driver.c
--- a/src/qemu_driver.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/qemu_driver.c	Fri Oct 03 12:44:51 2008 +0100
@@ -498,8 +498,7 @@
 {
     char *monitor = NULL;
     size_t offset = 0;
-    virDomainChrDefPtr chr;
-    int ret;
+    int ret, i;
 
     /* The order in which QEMU prints out the PTY paths is
        the order in which it procsses its monitor, serial
@@ -511,25 +510,23 @@
         goto cleanup;
 
     /* then the serial devices */
-    chr = vm->def->serials;
-    while (chr) {
+    for (i = 0 ; i < vm->def->nserials ; i++) {
+        virDomainChrDefPtr chr = vm->def->serials[i];
         if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
             if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                                &chr->data.file.path)) != 0)
                 goto cleanup;
         }
-        chr = chr->next;
     }
 
     /* and finally the parallel devices */
-    chr = vm->def->parallels;
-    while (chr) {
+    for (i = 0 ; i < vm->def->nparallels ; i++) {
+        virDomainChrDefPtr chr = vm->def->parallels[i];
         if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
             if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                                &chr->data.file.path)) != 0)
                 goto cleanup;
         }
-        chr = chr->next;
     }
 
     /* Got them all, so now open the monitor console */
@@ -2397,6 +2394,7 @@
     char *cmd, *reply, *safe_path;
     char *devname = NULL;
     unsigned int qemuCmdFlags;
+    int i;
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2405,12 +2403,12 @@
     }
 
     newdisk = dev->data.disk;
-    origdisk = vm->def->disks;
-    while (origdisk) {
-        if (origdisk->bus == newdisk->bus &&
-            STREQ(origdisk->dst, newdisk->dst))
+    for (i = 0 ; i < vm->def->ndisks ; i++) {
+        if (vm->def->disks[i]->bus == newdisk->bus &&
+            STREQ(vm->def->disks[i]->dst, newdisk->dst)) {
+            origdisk = vm->def->disks[i];
             break;
-        origdisk = origdisk->next;
+        }
     }
 
     if (!origdisk) {
@@ -2512,7 +2510,6 @@
     virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
     int ret;
     char *cmd, *reply;
-    virDomainDiskDefPtr *dest, *prev, ptr;
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2520,26 +2517,9 @@
         return -1;
     }
 
-    /* Find spot in domain definition where we will put the disk */
-    ptr = vm->def->disks;
-    prev = &(vm->def->disks);
-    while (ptr) {
-        if (STREQ(dev->data.disk->dst, ptr->dst)) {
-            qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("duplicate disk target '%s'"),
-                             dev->data.disk->dst);
-            return -1;
-        }
-        if (virDomainDiskCompare(dev->data.disk, ptr) < 0) {
-            dest = &(ptr);
-            break;
-        }
-        prev = &(ptr->next);
-        ptr = ptr->next;
-    }
-
-    if (!ptr) {
-        dest = prev;
+    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
+        qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
+        return -1;
     }
 
     ret = asprintf(&cmd, "usb_add disk:%s", dev->data.disk->src);
@@ -2567,9 +2547,9 @@
         return -1;
     }
 
-    /* Actually update the xml */
-    dev->data.disk->next = *dest;
-    *prev = dev->data.disk;
+    vm->def->disks[vm->def->ndisks++] = dev->data.disk;
+    qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
+          virDomainDiskQSort);
 
     VIR_FREE(reply);
     VIR_FREE(cmd);
@@ -2586,6 +2566,10 @@
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
+        return -1;
+    }
+    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
+        qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
         return -1;
     }
 
@@ -2622,9 +2606,7 @@
         return -1;
     }
 
-    /* Update xml */
-    dev->data.hostdev->next = vm->def->hostdevs;
-    vm->def->hostdevs = dev->data.hostdev;
+    vm->def->hostdevs[vm->def->nhostdevs++] = dev->data.hostdev;
 
     VIR_FREE(reply);
     VIR_FREE(cmd);
@@ -2907,7 +2889,7 @@
 #ifdef __linux__
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
     virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
-    virDomainNetDefPtr net;
+    int i;
 
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2928,8 +2910,9 @@
     }
 
     /* Check the path is one of the domain's network interfaces. */
-    for (net = vm->def->nets; net; net = net->next) {
-        if (net->ifname && STREQ (net->ifname, path))
+    for (i = 0 ; i < vm->def->nnets ; i++) {
+        if (vm->def->nets[i]->ifname &&
+            STREQ (vm->def->nets[i]->ifname, path))
             goto ok;
     }
 
@@ -2955,8 +2938,7 @@
 {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
     virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
-    virDomainDiskDefPtr disk;
-    int fd, ret = -1;
+    int fd, ret = -1, i;
 
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2971,9 +2953,10 @@
     }
 
     /* Check the path belongs to this domain. */
-    for (disk = vm->def->disks ; disk != NULL ; disk = disk->next) {
-        if (disk->src != NULL &&
-            STREQ (disk->src, path)) goto found;
+    for (i = 0 ; i < vm->def->ndisks ; i++) {
+        if (vm->def->disks[i]->src != NULL &&
+            STREQ (vm->def->disks[i]->src, path))
+            goto found;
     }
     qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                       _("invalid path"));
diff -r 44cb26ad18bc src/xend_internal.c
--- a/src/xend_internal.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/xend_internal.c	Fri Oct 03 12:44:51 2008 +0100
@@ -1647,7 +1647,7 @@
                         int xendConfigVersion)
 {
     const struct sexpr *cur, *node;
-    virDomainDiskDefPtr disk = NULL, prev = def->disks;
+    virDomainDiskDefPtr disk = NULL;
 
     for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
         node = cur->u.s.car;
@@ -1781,12 +1781,10 @@
                 strchr(mode, '!'))
                 disk->shared = 1;
 
-            if (prev)
-                prev->next = disk;
-            else
-                def->disks = disk;
-
-            prev = disk;
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+                goto no_memory;
+
+            def->disks[def->ndisks++] = disk;
             disk = NULL;
         }
     }
@@ -1807,7 +1805,7 @@
                        virDomainDefPtr def,
                        const struct sexpr *root)
 {
-    virDomainNetDefPtr net = NULL, prev = def->nets;
+    virDomainNetDefPtr net = NULL;
     const struct sexpr *cur, *node;
     const char *tmp;
     int vif_index = 0;
@@ -1880,10 +1878,10 @@
                 !(net->model = strdup(model)))
                 goto no_memory;
 
-            if (prev)
-                prev->next = net;
-            else
-                def->nets = net;
+            if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
+                goto no_memory;
+
+            def->nets[def->nnets++] = net;
             vif_index++;
         }
     }
@@ -1905,22 +1903,22 @@
 {
     if (STREQ(str, "all")) {
         int i;
-        virDomainSoundDefPtr prev = NULL;
+
+        if (VIR_ALLOC_N(def->sounds,
+                        VIR_DOMAIN_SOUND_MODEL_LAST) < 0)
+            goto no_memory;
+
         for (i = 0 ; i < VIR_DOMAIN_SOUND_MODEL_LAST ; i++) {
             virDomainSoundDefPtr sound;
             if (VIR_ALLOC(sound) < 0)
                 goto no_memory;
             sound->model = i;
-            if (prev)
-                prev->next = sound;
-            else
-                def->sounds = sound;
-            prev = sound;
+            def->sounds[def->nsounds++] = sound;
         }
     } else {
         char model[10];
         const char *offset = str, *offset2;
-        virDomainSoundDefPtr prev = NULL;
+
         do {
             int len;
             virDomainSoundDefPtr sound;
@@ -1945,11 +1943,12 @@
                 goto error;
             }
 
-            if (prev)
-                prev->next = sound;
-            else
-                def->sounds = sound;
-            prev = sound;
+            if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
+                virDomainSoundDefFree(sound);
+                goto no_memory;
+            }
+
+            def->sounds[def->nsounds++] = sound;
             offset = offset2 ? offset2 + 1 : NULL;
         } while (offset);
     }
@@ -1968,7 +1967,6 @@
                       virDomainDefPtr def,
                       const struct sexpr *root)
 {
-    virDomainInputDefPtr prev = def->inputs;
     struct sexpr *cur, *node;
     const char *tmp;
 
@@ -1988,11 +1986,11 @@
                     else
                         input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
 
-                    if (prev)
-                        prev->next = input;
-                    else
-                        def->inputs = input;
-                    prev = input;
+                    if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
+                        VIR_FREE(input);
+                        goto no_memory;
+                    }
+                    def->inputs[def->ninputs++] = input;
                 } else {
                     /* XXX Handle other non-input USB devices later */
                 }
@@ -2333,34 +2331,31 @@
         xendConfigVersion == 1) {
         tmp = sexpr_node(root, "domain/image/hvm/cdrom");
         if ((tmp != NULL) && (tmp[0] != 0)) {
-            virDomainDiskDefPtr disk, prev;
+            virDomainDiskDefPtr disk;
             if (VIR_ALLOC(disk) < 0)
                 goto no_memory;
             if (!(disk->src = strdup(tmp))) {
-                VIR_FREE(disk);
+                virDomainDiskDefFree(disk);
                 goto no_memory;
             }
             disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
             disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
             if (!(disk->dst = strdup("hdc"))) {
-                VIR_FREE(disk);
+                virDomainDiskDefFree(disk);
                 goto no_memory;
             }
             if (!(disk->driverName = strdup("file"))) {
-                VIR_FREE(disk);
+                virDomainDiskDefFree(disk);
                 goto no_memory;
             }
             disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
             disk->readonly = 1;
 
-            prev = def->disks;
-            while (prev && prev->next) {
-                prev = prev->next;
-            }
-            if (prev)
-                prev->next = disk;
-            else
-                def->disks = disk;
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            def->disks[def->ndisks++] = disk;
         }
     }
 
@@ -2372,7 +2367,7 @@
         for (i = 0 ; i < sizeof(fds)/sizeof(fds[0]) ; i++) {
             tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
             if ((tmp != NULL) && (tmp[0] != 0)) {
-                virDomainDiskDefPtr disk, prev;
+                virDomainDiskDefPtr disk;
                 if (VIR_ALLOC(disk) < 0)
                     goto no_memory;
                 if (!(disk->src = strdup(tmp))) {
@@ -2382,26 +2377,25 @@
                 disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
                 disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
                 if (!(disk->dst = strdup(fds[i]))) {
-                    VIR_FREE(disk);
+                    virDomainDiskDefFree(disk);
                     goto no_memory;
                 }
                 if (!(disk->driverName = strdup("file"))) {
-                    VIR_FREE(disk);
+                    virDomainDiskDefFree(disk);
                     goto no_memory;
                 }
                 disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
 
-                prev = def->disks;
-                while (prev && prev->next) {
-                    prev = prev->next;
-                }
-                if (prev)
-                    prev->next = disk;
-                else
-                    def->disks = disk;
-            }
-        }
-    }
+                if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+                    virDomainDiskDefFree(disk);
+                    goto no_memory;
+                }
+                def->disks[def->ndisks++] = disk;
+            }
+        }
+    }
+    qsort(def->disks, def->ndisks, sizeof(*def->disks),
+          virDomainDiskQSort);
 
     /* in case of HVM we have USB device emulation */
     if (hvm &&
@@ -2413,14 +2407,26 @@
     if (hvm) {
         tmp = sexpr_node(root, "domain/image/hvm/serial");
         if (tmp && STRNEQ(tmp, "none")) {
-            if ((def->serials = xenDaemonParseSxprChar(conn, tmp, tty)) == NULL)
-                goto error;
+            virDomainChrDefPtr chr;
+            if ((chr = xenDaemonParseSxprChar(conn, tmp, tty)) == NULL)
+                goto error;
+            if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->serials[def->nserials++] = chr;
         }
         tmp = sexpr_node(root, "domain/image/hvm/parallel");
         if (tmp && STRNEQ(tmp, "none")) {
+            virDomainChrDefPtr chr;
             /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
-            if ((def->parallels = xenDaemonParseSxprChar(conn, tmp, NULL)) == NULL)
-                goto error;
+            if ((chr = xenDaemonParseSxprChar(conn, tmp, NULL)) == NULL)
+                goto error;
+            if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->parallels[def->nparallels++] = chr;
         }
     } else {
         /* Fake a paravirt console, since that's not in the sexpr */
@@ -4726,9 +4732,8 @@
     xenUnifiedPrivatePtr priv;
     struct sexpr *root = NULL;
     int fd = -1, ret = -1;
-    int found = 0;
-    virDomainDefPtr def;
-    virDomainDiskDefPtr disk;
+    int found = 0, i;
+    virDomainDefPtr def;
 
     priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
 
@@ -4757,14 +4762,12 @@
     if (!(def = xenDaemonParseSxpr(domain->conn, root, priv->xendConfigVersion, NULL)))
         goto cleanup;
 
-    disk = def->disks;
-    while (disk) {
-        if (disk->src &&
-            STREQ(disk->src, path)) {
+    for (i = 0 ; i < def->ndisks ; i++) {
+        if (def->disks[i]->src &&
+            STREQ(def->disks[i]->src, path)) {
             found = 1;
             break;
         }
-        disk = disk->next;
     }
     if (!found) {
         virXendError (domain->conn, VIR_ERR_INVALID_ARG,
@@ -5211,21 +5214,20 @@
 
 int
 xenDaemonFormatSxprSound(virConnectPtr conn,
-                         virDomainSoundDefPtr sound,
+                         virDomainDefPtr def,
                          virBufferPtr buf)
 {
     const char *str;
-    virDomainSoundDefPtr prev = NULL;
-
-    while (sound) {
-        if (!(str = virDomainSoundModelTypeToString(sound->model))) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("unexpected sound model %d"), sound->model);
-            return -1;
-        }
-        virBufferVSprintf(buf, "%s%s", prev ? "," : "", str);
-        prev = sound;
-        sound = sound->next;
+    int i;
+
+    for (i = 0 ; i < def->nsounds ; i++) {
+        if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("unexpected sound model %d"),
+                         def->sounds[i]->model);
+            return -1;
+        }
+        virBufferVSprintf(buf, "%s%s", i ? "," : "", str);
     }
 
     return 0;
@@ -5275,9 +5277,6 @@
     char uuidstr[VIR_UUID_STRING_BUFLEN];
     const char *tmp;
     int hvm = 0, i;
-    virDomainNetDefPtr net;
-    virDomainDiskDefPtr disk;
-    virDomainInputDefPtr input;
 
     virBufferAddLit(&buf, "(vm ");
     virBufferVSprintf(&buf, "(name '%s')", def->name);
@@ -5389,16 +5388,14 @@
             /* get the cdrom device file */
             /* Only XenD <= 3.0.2 wants cdrom config here */
             if (xendConfigVersion == 1) {
-                disk = def->disks;
-                while (disk) {
-                    if (disk->type == VIR_DOMAIN_DISK_DEVICE_CDROM &&
-                        STREQ(disk->dst, "hdc") &&
-                        disk->src) {
+                for (i = 0 ; i < def->ndisks ; i++) {
+                    if (def->disks[i]->type == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+                        STREQ(def->disks[i]->dst, "hdc") &&
+                        def->disks[i]->src) {
                         virBufferVSprintf(&buf, "(cdrom '%s')",
-                                          disk->src);
+                                          def->disks[i]->src);
                         break;
                     }
-                    disk = disk->next;
                 }
             }
 
@@ -5411,16 +5408,13 @@
 
             virBufferAddLit(&buf, "(usb 1)");
 
-            input = def->inputs;
-            while (input) {
-                if (xenDaemonFormatSxprInput(conn, input, &buf) < 0)
-                    goto error;
-                input = input->next;
-            }
+            for (i = 0 ; i < def->ninputs ; i++)
+                if (xenDaemonFormatSxprInput(conn, def->inputs[i], &buf) < 0)
+                    goto error;
 
             if (def->parallels) {
                 virBufferAddLit(&buf, "(parallel ");
-                if (xenDaemonFormatSxprChr(conn, def->parallels, &buf) < 0)
+                if (xenDaemonFormatSxprChr(conn, def->parallels[0], &buf) < 0)
                     goto error;
                 virBufferAddLit(&buf, ")");
             } else {
@@ -5428,7 +5422,7 @@
             }
             if (def->serials) {
                 virBufferAddLit(&buf, "(serial ");
-                if (xenDaemonFormatSxprChr(conn, def->serials, &buf) < 0)
+                if (xenDaemonFormatSxprChr(conn, def->serials[0], &buf) < 0)
                     goto error;
                 virBufferAddLit(&buf, ")");
             } else {
@@ -5440,7 +5434,7 @@
 
             if (def->sounds) {
                 virBufferAddLit(&buf, "(soundhw '");
-                if (xenDaemonFormatSxprSound(conn, def->sounds, &buf) < 0)
+                if (xenDaemonFormatSxprSound(conn, def, &buf) < 0)
                     goto error;
                 virBufferAddLit(&buf, "')");
             }
@@ -5462,19 +5456,15 @@
         virBufferAddLit(&buf, "))");
     }
 
-    disk = def->disks;
-    while (disk) {
-        if (xenDaemonFormatSxprDisk(conn, disk, &buf, hvm, xendConfigVersion, 0) < 0)
-            goto error;
-        disk = disk->next;
-    }
-
-    net = def->nets;
-    while (net) {
-        if (xenDaemonFormatSxprNet(conn, net, &buf, hvm, xendConfigVersion, 0) < 0)
-            goto error;
-        net = net->next;
-    }
+    for (i = 0 ; i < def->ndisks ; i++)
+        if (xenDaemonFormatSxprDisk(conn, def->disks[i],
+                                    &buf, hvm, xendConfigVersion, 0) < 0)
+            goto error;
+
+    for (i = 0 ; i < def->nnets ; i++)
+        if (xenDaemonFormatSxprNet(conn, def->nets[i],
+                                   &buf, hvm, xendConfigVersion, 0) < 0)
+            goto error;
 
     /* New style PV graphics config xen >= 3.0.4,
      * or HVM graphics config xen >= 3.0.5 */
diff -r 44cb26ad18bc src/xend_internal.h
--- a/src/xend_internal.h	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/xend_internal.h	Fri Oct 03 12:44:51 2008 +0100
@@ -115,7 +115,7 @@
                        virBufferPtr buf);
 int
 xenDaemonFormatSxprSound(virConnectPtr conn,
-                         virDomainSoundDefPtr sound,
+                         virDomainDefPtr def,
                          virBufferPtr buf);
 
 char *
diff -r 44cb26ad18bc src/xm_internal.c
--- a/src/xm_internal.c	Fri Oct 03 12:21:48 2008 +0100
+++ b/src/xm_internal.c	Fri Oct 03 12:44:51 2008 +0100
@@ -51,8 +51,6 @@
 
 static int xenXMConfigSetString(virConfPtr conf, const char *setting,
                                 const char *str);
-static int xenXMDiskCompare(virDomainDiskDefPtr a,
-                            virDomainDiskDefPtr b);
 
 typedef struct xenXMConfCache *xenXMConfCachePtr;
 typedef struct xenXMConfCache {
@@ -888,20 +886,9 @@
                 disk->shared = 1;
 
             /* Maintain list in sorted order according to target device name */
-            if (def->disks == NULL) {
-                disk->next = def->disks;
-                def->disks = disk;
-            } else {
-                virDomainDiskDefPtr ptr = def->disks;
-                while (ptr) {
-                    if (!ptr->next || xenXMDiskCompare(disk, ptr->next) < 0) {
-                        disk->next = ptr->next;
-                        ptr->next = disk;
-                        break;
-                    }
-                    ptr = ptr->next;
-                }
-            }
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+                goto no_memory;
+            def->disks[def->ndisks++] = disk;
             disk = NULL;
 
             skipdisk:
@@ -928,25 +915,14 @@
             disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
             disk->readonly = 1;
 
-
-            /* Maintain list in sorted order according to target device name */
-            if (def->disks == NULL) {
-                disk->next = def->disks;
-                def->disks = disk;
-            } else {
-                virDomainDiskDefPtr ptr = def->disks;
-                while (ptr) {
-                    if (!ptr->next || xenXMDiskCompare(disk, ptr->next) < 0) {
-                        disk->next = ptr->next;
-                        ptr->next = disk;
-                        break;
-                    }
-                    ptr = ptr->next;
-                }
-            }
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+                goto no_memory;
+            def->disks[def->ndisks++] = disk;
             disk = NULL;
         }
     }
+    qsort(def->disks, def->ndisks, sizeof(*def->disks),
+          virDomainDiskQSort);
 
     list = virConfGetValue(conf, "vif");
     if (list && list->type == VIR_CONF_LIST) {
@@ -1064,15 +1040,9 @@
                 !(net->model = strdup(model)))
                 goto no_memory;
 
-            if (!def->nets) {
-                net->next = NULL;
-                def->nets = net;
-            } else {
-                virDomainNetDefPtr ptr = def->nets;
-                while (ptr->next)
-                    ptr = ptr->next;
-                ptr->next = net;
-            }
+            if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0)
+                goto no_memory;
+            def->nets[def->nnets++] = net;
             net = NULL;
 
         skipnic:
@@ -1094,7 +1064,12 @@
             input->type = STREQ(str, "tablet") ?
                 VIR_DOMAIN_INPUT_TYPE_TABLET :
                 VIR_DOMAIN_INPUT_TYPE_MOUSE;
-            def->inputs = input;
+            if (VIR_ALLOC_N(def->inputs, 1) < 0) {
+                virDomainInputDefFree(input);
+                goto no_memory;
+            }
+            def->inputs[0] = input;
+            def->ninputs = 1;
         }
     }
 
@@ -1212,17 +1187,38 @@
     }
 
     if (hvm) {
+        virDomainChrDefPtr chr = NULL;
+
         if (xenXMConfigGetString(conn, conf, "parallel", &str, NULL) < 0)
             goto cleanup;
         if (str && STRNEQ(str, "none") &&
-            !(def->parallels = xenDaemonParseSxprChar(conn, str, NULL)))
+            !(chr = xenDaemonParseSxprChar(conn, str, NULL)))
             goto cleanup;
+
+        if (chr) {
+            if (VIR_ALLOC_N(def->parallels, 1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->parallels[0] = chr;
+            def->nparallels++;
+            chr = NULL;
+        }
 
         if (xenXMConfigGetString(conn, conf, "serial", &str, NULL) < 0)
             goto cleanup;
         if (str && STRNEQ(str, "none") &&
-            !(def->serials = xenDaemonParseSxprChar(conn, str, NULL)))
+            !(chr = xenDaemonParseSxprChar(conn, str, NULL)))
             goto cleanup;
+
+        if (chr) {
+            if (VIR_ALLOC_N(def->serials, 1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->serials[0] = chr;
+            def->nserials++;
+        }
     } else {
         if (!(def->console = xenDaemonParseSxprChar(conn, "pty", NULL)))
             goto cleanup;
@@ -1821,8 +1817,6 @@
     char *cpus = NULL;
     const char *lifecycle;
     char uuid[VIR_UUID_STRING_BUFLEN];
-    virDomainDiskDefPtr disk;
-    virDomainNetDefPtr net;
     virConfValuePtr diskVal = NULL;
     virConfValuePtr netVal = NULL;
 
@@ -1915,15 +1909,16 @@
             goto no_memory;
 
         if (priv->xendConfigVersion == 1) {
-            disk = def->disks;
-            while (disk) {
-                if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
-                    disk->dst && STREQ(disk->dst, "hdc") && disk->src) {
-                    if (xenXMConfigSetString(conf, "cdrom", disk->src) < 0)
+            for (i = 0 ; i < def->ndisks ; i++) {
+                if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+                    def->disks[i]->dst &&
+                    STREQ(def->disks[i]->dst, "hdc") &&
+                    def->disks[i]->src) {
+                    if (xenXMConfigSetString(conf, "cdrom",
+                                             def->disks[i]->src) < 0)
                         goto no_memory;
                     break;
                 }
-                disk = disk->next;
             }
         }
 
@@ -1976,23 +1971,20 @@
 
 
     if (hvm) {
-        virDomainInputDefPtr input;
         if (def->emulator &&
             xenXMConfigSetString(conf, "device_model", def->emulator) < 0)
             goto no_memory;
 
-        input = def->inputs;
-        while (input) {
-            if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
+        for (i = 0 ; i < def->ninputs ; i++) {
+            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
                 if (xenXMConfigSetInt(conf, "usb", 1) < 0)
                     goto no_memory;
                 if (xenXMConfigSetString(conf, "usbdevice",
-                                         input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
+                                         def->inputs[i]->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
                                          "mouse" : "tablet") < 0)
                     goto no_memory;
                 break;
             }
-            input = input->next;
         }
     }
 
@@ -2092,27 +2084,24 @@
     }
 
     /* analyze of the devices */
-    disk = def->disks;
     if (VIR_ALLOC(diskVal) < 0)
         goto no_memory;
     diskVal->type = VIR_CONF_LIST;
     diskVal->list = NULL;
 
-    while (disk) {
+    for (i = 0 ; i < def->ndisks ; i++) {
         if (priv->xendConfigVersion == 1 &&
-            disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
-            disk->dst && STREQ(disk->dst, "hdc")) {
-            disk = disk->next;
+            def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+            def->disks[i]->dst &&
+            STREQ(def->disks[i]->dst, "hdc")) {
             continue;
         }
-        if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
+        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
             continue;
 
-        if (xenXMDomainConfigFormatDisk(conn, diskVal, disk,
+        if (xenXMDomainConfigFormatDisk(conn, diskVal, def->disks[i],
                                         hvm, priv->xendConfigVersion) < 0)
             goto cleanup;
-
-        disk = disk->next;
     }
     if (diskVal->list == NULL)
         VIR_FREE(diskVal);
@@ -2123,18 +2112,16 @@
     diskVal = NULL;
 
 
-    net = def->nets;
     if (VIR_ALLOC(netVal) < 0)
         goto no_memory;
     netVal->type = VIR_CONF_LIST;
     netVal->list = NULL;
 
-    while (net) {
-        if (xenXMDomainConfigFormatNet(conn, netVal, net,
+    for (i = 0 ; i < def->nnets ; i++) {
+        if (xenXMDomainConfigFormatNet(conn, netVal,
+                                       def->nets[i],
                                        hvm) < 0)
             goto cleanup;
-
-        net = net->next;
     }
     if (netVal->list == NULL)
         VIR_FREE(netVal);
@@ -2145,12 +2132,12 @@
     netVal = NULL;
 
     if (hvm) {
-        if (def->parallels) {
+        if (def->nparallels) {
             virBuffer buf = VIR_BUFFER_INITIALIZER;
             char *str;
             int ret;
 
-            ret = xenDaemonFormatSxprChr(conn, def->parallels, &buf);
+            ret = xenDaemonFormatSxprChr(conn, def->parallels[0], &buf);
             str = virBufferContentAndReset(&buf);
             if (ret == 0)
                 ret = xenXMConfigSetString(conf, "parallel", str);
@@ -2162,12 +2149,12 @@
                 goto no_memory;
         }
 
-        if (def->serials) {
+        if (def->nserials) {
             virBuffer buf = VIR_BUFFER_INITIALIZER;
             char *str;
             int ret;
 
-            ret = xenDaemonFormatSxprChr(conn, def->serials, &buf);
+            ret = xenDaemonFormatSxprChr(conn, def->serials[0], &buf);
             str = virBufferContentAndReset(&buf);
             if (ret == 0)
                 ret = xenXMConfigSetString(conf, "serial", str);
@@ -2184,7 +2171,7 @@
             virBuffer buf = VIR_BUFFER_INITIALIZER;
             char *str = NULL;
             int ret = xenDaemonFormatSxprSound(conn,
-                                               def->sounds,
+                                               def,
                                                &buf);
             str = virBufferContentAndReset(&buf);
             if (ret == 0)
@@ -2433,14 +2420,6 @@
     return virHashSize(nameConfigMap);
 }
 
-static int xenXMDiskCompare(virDomainDiskDefPtr a,
-                            virDomainDiskDefPtr b) {
-    if (a->bus == b->bus)
-        return virDiskNameToIndex(a->dst) - virDiskNameToIndex(b->dst);
-    else
-        return a->bus - b->bus;
-}
-
 
 /**
  * xenXMDomainAttachDevice:
@@ -2458,6 +2437,7 @@
     xenXMConfCachePtr entry = NULL;
     int ret = -1;
     virDomainDeviceDefPtr dev = NULL;
+    virDomainDefPtr def;
 
     if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
@@ -2473,6 +2453,7 @@
         return -1;
     if (!(entry = virHashLookup(configCache, filename)))
         return -1;
+    def = entry->def;
 
     if (!(dev = virDomainDeviceDefParse(domain->conn,
                                         entry->def,
@@ -2482,34 +2463,24 @@
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
     {
-        /* Maintain list in sorted order according to target device name */
-        if (entry->def->disks == NULL) {
-            dev->data.disk->next = entry->def->disks;
-            entry->def->disks = dev->data.disk;
-        } else {
-            virDomainDiskDefPtr ptr = entry->def->disks;
-            while (ptr) {
-                if (!ptr->next || xenXMDiskCompare(dev->data.disk, ptr->next) < 0) {
-                    dev->data.disk->next = ptr->next;
-                    ptr->next = dev->data.disk;
-                    break;
-                }
-                ptr = ptr->next;
-            }
+        if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+            xenXMError(domain->conn, VIR_ERR_NO_MEMORY, NULL);
+            goto cleanup;
         }
+        def->disks[def->ndisks++] = dev->data.disk;
         dev->data.disk = NULL;
+        qsort(def->disks, def->ndisks, sizeof(*def->disks),
+              virDomainDiskQSort);
     }
     break;
 
     case VIR_DOMAIN_DEVICE_NET:
     {
-        virDomainNetDefPtr net = entry->def->nets;
-        while (net && net->next)
-            net = net->next;
-        if (net)
-            net->next = dev->data.net;
-        else
-            entry->def->nets = dev->data.net;
+        if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0) {
+            xenXMError(domain->conn, VIR_ERR_NO_MEMORY, NULL);
+            goto cleanup;
+        }
+        def->nets[def->nnets++] = dev->data.net;
         dev->data.net = NULL;
         break;
     }
@@ -2571,7 +2542,9 @@
     const char *filename = NULL;
     xenXMConfCachePtr entry = NULL;
     virDomainDeviceDefPtr dev = NULL;
+    virDomainDefPtr def;
     int ret = -1;
+    int i;
 
     if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
@@ -2586,6 +2559,7 @@
         return -1;
     if (!(entry = virHashLookup(configCache, filename)))
         return -1;
+    def = entry->def;
 
     if (!(dev = virDomainDeviceDefParse(domain->conn,
                                         entry->def,
@@ -2595,42 +2569,34 @@
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
     {
-        virDomainDiskDefPtr disk = entry->def->disks;
-        virDomainDiskDefPtr prev = NULL;
-        while (disk) {
-            if (disk->dst &&
+        for (i = 0 ; i < def->ndisks ; i++) {
+            if (def->disks[i]->dst &&
                 dev->data.disk->dst &&
-                STREQ(disk->dst, dev->data.disk->dst)) {
-                if (prev) {
-                    prev->next = disk->next;
-                } else {
-                    entry->def->disks = disk->next;
-                }
-                virDomainDiskDefFree(disk);
+                STREQ(def->disks[i]->dst, dev->data.disk->dst)) {
+                virDomainDiskDefFree(def->disks[i]);
+                if (i < (def->ndisks - 1))
+                    memmove(def->disks + i,
+                            def->disks + i + 1,
+                            def->ndisks - (i + 1));
                 break;
             }
-            prev = disk;
-            disk = disk->next;
         }
         break;
     }
 
     case VIR_DOMAIN_DEVICE_NET:
     {
-        virDomainNetDefPtr net = entry->def->nets;
-        virDomainNetDefPtr prev = NULL;
-        while (net) {
-            if (!memcmp(net->mac, dev->data.net->mac, VIR_DOMAIN_NET_MAC_SIZE)) {
-                if (prev) {
-                    prev->next = net->next;
-                } else {
-                    entry->def->nets = net->next;
-                }
-                virDomainNetDefFree(net);
+        for (i = 0 ; i < def->nnets ; i++) {
+            if (!memcmp(def->nets[i]->mac,
+                        dev->data.net->mac,
+                        VIR_DOMAIN_NET_MAC_SIZE)) {
+                virDomainNetDefFree(def->nets[i]);
+                if (i < (def->nnets - 1))
+                    memmove(def->nets + i,
+                            def->nets + i + 1,
+                            def->nnets - (i + 1));
                 break;
             }
-            prev = net;
-            net = net->next;
         }
         break;
     }
diff -r 44cb26ad18bc tests/sexpr2xmldata/sexpr2xml-fv-v2.xml
--- a/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml	Fri Oct 03 12:21:48 2008 +0100
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml	Fri Oct 03 12:44:51 2008 +0100
@@ -18,16 +18,16 @@
   <on_crash>restart</on_crash>
   <devices>
     <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
+    <disk type='file' device='disk'>
+      <driver name='file'/>
+      <source file='/root/foo.img'/>
+      <target dev='hda' bus='ide'/>
+    </disk>
     <disk type='file' device='cdrom'>
       <driver name='file'/>
       <source file='/root/boot.iso'/>
       <target dev='hdc' bus='ide'/>
       <readonly/>
-    </disk>
-    <disk type='file' device='disk'>
-      <driver name='file'/>
-      <source file='/root/foo.img'/>
-      <target dev='hda' bus='ide'/>
     </disk>
     <interface type='bridge'>
       <mac address='00:16:3e:1b:b1:47'/>


-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list