[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libvir] [RFC][PATCH 2/2] Tested NUMA patches for available memory and topology



Patch for accessing topology information.

--
Elizabeth Kon (Beth)
IBM Linux Technology Center
Open Hypervisor Team
email: eak us ibm com

diff -urpN libvirt.cellsMemory/src/xend_internal.c libvirt.topology/src/xend_internal.c
--- libvirt.cellsMemory/src/xend_internal.c	2007-09-27 18:39:52.000000000 -0400
+++ libvirt.topology/src/xend_internal.c	2007-09-28 00:26:47.000000000 -0400
@@ -30,6 +30,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <libxml/uri.h>
+#include <ctype.h>
 #include <errno.h>
 
 #include "libvirt/libvirt.h"
@@ -1869,6 +1870,198 @@ sexpr_to_xend_node_info(struct sexpr *ro
     return (0);
 }
 
+/**
+ * getNumber:
+ * @pointer: pointer to string beginning with  numerical characters
+ * @result: pointer to integer for storing the numerical result
+ *
+ * Internal routine extracting a number from the beginning of a string
+ *
+ * Returns the number of characters that were extracted as digits
+ * or -1 if no digits were found.
+ */
+static int
+getNumber (const char * pointer, int * result) {
+    int len = 0;
+    while (isdigit(*(pointer + len)))
+        len++;
+    if (len == 0)
+        return -1;
+    *(result) = atoi(pointer);
+    return (len);
+}
+
+/**
+ * sexpr_to_xend_topology_xml:
+ * @root: an S-Expression describing a node
+ *
+ * Internal routine creating an XML string with the values from
+ * the node root provided.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int 
+sexpr_to_xend_topology_xml(virConnectPtr conn, struct sexpr *root, virBufferPtr xml)
+{
+    const char *nodeToCpu;
+    const char *offset;
+    int cellNum;
+    int numCells = 0;
+    int numCpus;
+    int cellCpuCount = 0; 
+    int nodeCpuCount = 0; 
+    int start; 
+    int finish;
+    int r;
+    int i;
+    int len; 
+    int cpuNum; 
+    int *cpuIdsPtr = NULL; 
+    int *iCpuIdsPtr = NULL;
+    char next;
+
+    nodeToCpu = sexpr_node(root, "node/node_to_cpu");
+    if (nodeToCpu == NULL) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("failed to parse topology information"));
+        goto error;
+    }
+
+    numCells = sexpr_int(root, "node/nr_nodes");
+    numCpus = sexpr_int(root, "node/nr_cpus");
+
+    /* array for holding all cpu numbers associated with a single cell. 
+     * Should never need more than numCpus (which is total number of 
+     * cpus for the node) 
+     */
+    cpuIdsPtr = iCpuIdsPtr = malloc(numCpus * sizeof(int));
+    if (cpuIdsPtr == NULL) {
+        goto vir_buffer_failed;
+    }
+
+    /* start filling in xml */
+    r = virBufferVSprintf (xml,
+                               "\
+  <topology>\n\
+    <cells num='%d'>\n",
+                           numCells);
+    if (r == -1) goto vir_buffer_failed;
+
+    offset = nodeToCpu;
+    /* now iterate through all cells and find associated cpu ids */
+    /* example of string being parsed: "node0:0-3,7,9-10\n   node1:11-14\n" */
+    while ((offset = strstr(offset, "node")) != NULL) {
+        cpuIdsPtr = iCpuIdsPtr;
+        cellCpuCount = 0;
+        offset +=4;
+        if ((len = getNumber(offset, &cellNum)) < 0) {
+            virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error");
+            goto error;
+        }
+        offset += len;
+        if (*(offset) != ':') {
+            virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error");
+            goto error;
+        }
+        offset++;
+        /* get list of cpus associated w/ single cell */
+        while (1) {
+            if ((len = getNumber(offset, &cpuNum)) < 0) {
+                virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error");
+                goto error;
+            }
+            offset += len;
+            next = *(offset);
+            if (next == '-') {
+                offset++;
+                start = cpuNum;
+                if ((len = getNumber(offset, &finish)) < 0) {
+                    virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error");
+                    goto error;
+                }
+                if (start > finish) {
+                    virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error");
+                    goto error;
+
+                }
+                for (i=start; i<=finish && nodeCpuCount<numCpus; i++) {
+                    *(cpuIdsPtr++) = i;
+                    cellCpuCount++;
+                    nodeCpuCount++;
+                }
+                if (nodeCpuCount > numCpus) {
+                    virXendError(conn, VIR_ERR_XEN_CALL, 
+                                 "conflicting cpu counts");
+                    goto error;
+                }
+                offset += len;
+                next = *(offset);
+                offset++;
+                if (next == ',') {
+                    continue;
+                } else if ((next == '\\') || (next =='\0')) {
+                    break;
+                } else {
+                    virXendError(conn, VIR_ERR_XEN_CALL, 
+                                 " topology string syntax error");
+                    goto error;
+                }
+            } else {
+                /* add the single number */
+                if (nodeCpuCount >= numCpus) {
+                    virXendError(conn, VIR_ERR_XEN_CALL, 
+                                 "conflicting cpu counts");
+                    goto error;
+                }
+                *(cpuIdsPtr++) = cpuNum;
+                cellCpuCount++;
+                nodeCpuCount++;
+                if (next == ',') {
+                    offset++;
+                    continue;
+                } else if ((next == '\\') || (next =='\0')) {
+                    break;
+                } else {
+                    virXendError(conn, VIR_ERR_XEN_CALL, 
+                                 " topology string syntax error");
+                    goto error;
+                }
+            }
+        }    
+
+        /* add xml for all cpus associated with one cell */
+        r = virBufferVSprintf (xml, "\
+      <cell id='%d'>\n\
+        <cpus num='%d'>\n", cellNum, cellCpuCount);
+        if (r == -1) goto vir_buffer_failed;
+
+        for (i = 0; i < cellCpuCount; i++) {
+            r = virBufferVSprintf (xml, "\
+           <cpu id='%d'/>\n", *(iCpuIdsPtr + i));
+        if (r == -1) goto vir_buffer_failed;
+        }
+        r = virBufferAdd (xml, "\
+        </cpus>\n\
+      </cell>\n", -1);
+        if (r == -1) goto vir_buffer_failed;
+    }            
+    r = virBufferAdd (xml, "\
+    </cells>\n\
+  </topology>\n", -1);
+    if (r == -1) goto vir_buffer_failed;
+    free(iCpuIdsPtr);
+    return (0);
+    
+
+vir_buffer_failed:
+    virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate new buffer"));
+        
+error:
+    if (iCpuIdsPtr)
+        free(iCpuIdsPtr);
+    return (-1);
+}
+
 #ifndef PROXY
 /**
  * sexpr_to_domain:
@@ -2589,6 +2782,39 @@ xenDaemonNodeGetInfo(virConnectPtr conn,
     return (ret);
 }
 
+/**
+ * xenDaemonNodeGetTopology:
+ * @conn: pointer to the Xen Daemon block
+ *
+ * This method retrieves a node's topology information.
+ *
+ * Returns -1 in case of error, 0 otherwise.
+ */
+int
+xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) {
+    int ret = -1;
+    struct sexpr *root;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (xml == NULL) {
+        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+        }
+
+    root = sexpr_get(conn, "/xend/node/");
+    if (root == NULL) {
+        return (-1);
+    }
+
+    ret = sexpr_to_xend_topology_xml(conn, root, xml);
+    sexpr_free(root);
+    return (ret);
+}
+
 #ifndef PROXY
 /**
  * xenDaemonGetType:
diff -urpN libvirt.cellsMemory/src/xend_internal.h libvirt.topology/src/xend_internal.h
--- libvirt.cellsMemory/src/xend_internal.h	2007-09-10 17:35:39.000000000 -0400
+++ libvirt.topology/src/xend_internal.h	2007-09-28 00:26:53.000000000 -0400
@@ -19,6 +19,7 @@
 #include <stdbool.h>
 
 #include "libvirt/libvirt.h"
+#include "buf.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -182,6 +183,7 @@ int xenDaemonOpen(virConnectPtr conn, co
 int xenDaemonClose(virConnectPtr conn);
 int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
 int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
+int xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml);
 int xenDaemonDomainSuspend(virDomainPtr domain);
 int xenDaemonDomainResume(virDomainPtr domain);
 int xenDaemonDomainShutdown(virDomainPtr domain);
diff -urpN libvirt.cellsMemory/src/xen_internal.c libvirt.topology/src/xen_internal.c
--- libvirt.cellsMemory/src/xen_internal.c	2007-09-27 22:23:50.000000000 -0400
+++ libvirt.topology/src/xen_internal.c	2007-09-28 00:27:02.000000000 -0400
@@ -2228,7 +2228,7 @@ xenHypervisorMakeCapabilitiesXML(virConn
     char line[1024], *str, *token;
     regmatch_t subs[4];
     char *saveptr = NULL;
-    int i, r;
+    int i, r, topology;
 
     char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
     int host_pae = 0;
@@ -2405,6 +2405,12 @@ xenHypervisorMakeCapabilitiesXML(virConn
   </host>\n", -1);
     if (r == -1) goto vir_buffer_failed;
 
+    if (sys_interface_version >= 4) {
+        topology = xenDaemonNodeGetTopology(conn, xml);
+        if (topology != 0)
+            goto topology_failed;
+    }
+
     for (i = 0; i < nr_guest_archs; ++i) {
         r = virBufferVSprintf (xml,
                                "\
@@ -2466,6 +2472,7 @@ xenHypervisorMakeCapabilitiesXML(virConn
   </guest>\n", -1);
         if (r == -1) goto vir_buffer_failed;
     }
+
     r = virBufferAdd (xml,
                       "\
 </capabilities>\n", -1);
@@ -2478,6 +2485,7 @@ xenHypervisorMakeCapabilitiesXML(virConn
 
  vir_buffer_failed:
     virXenError(VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
+ topology_failed:
     virBufferFree (xml);
     return NULL;
 }

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]