On Mon, Sep 24, 2007 at 11:30:53PM -0400, beth kon wrote: > [PATCH 2/2] - add capability to access topology information (cell to cpu > mapping) for each numa cell. > > Signed-off-by: Beth Kon (eak@xxxxxxxxxx) > > -- > Elizabeth Kon (Beth) > IBM Linux Technology Center > Open Hypervisor Team > email: eak@xxxxxxxxxx > > diff -urpN libvirt.cellsMemory/src/xend_internal.c libvirt.topology/src/xend_internal.c > --- libvirt.cellsMemory/src/xend_internal.c 2007-09-24 21:51:30.000000000 -0400 > +++ libvirt.topology/src/xend_internal.c 2007-09-24 23:09:20.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" > @@ -1873,6 +1874,181 @@ 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); > +} I'm always a bit vary of libc isXXXX since they tend to fluctuate based on locale while you don't expect so when parsing some input. In that case it's safe though. > +/** > + * 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, *offset; > + int cellNum, numCells = 0, numCpus, cellCpuCount = 0, nodeCpuCount = 0, start, finish, r; > + int i, len, cpuNum, *cpuIdsPtr = NULL, *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; > + } So if the host is not NUMA or an older Xen version, will you get that error back to the user ? > + 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); I know this indentation was borrowed from other code, but this hurts my love for proper indentation :-) > + 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" */ For multi lines comments we usually use /* * ..... * ..... */ > + while ((offset = strstr(offset, "node")) != NULL) { should you just skip blanks there instead ? > + 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 == '\n') { > + 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; > + cpuIdsPtr++; > + cellCpuCount++; > + nodeCpuCount++; > + if (next == ',') { > + offset++; > + continue; > + } else if (next == '\n') { > + break; > + } else { > + virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error"); > + goto error; > + } > + } > + } Loops look fine from visual inspection > + /* 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(cpuIdsPtr); > + return (0); > + > + > +vir_buffer_failed: > + virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate new buffer")); > + > +error: > + if (cpuIdsPtr) > + free(cpuIdsPtr); > + return (-1); > +} > + > #ifndef PROXY > /** > * sexpr_to_domain: > @@ -2601,6 +2777,39 @@ xenDaemonNodeGetInfo(virConnectPtr conn, > return (ret); > } > > +/** > + * xenDaemonNodeGetTopology: > + * @conn: pointer to the Xen Daemon block * @xml: buffer where the resulting XML will be stored > + * > + * 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-24 22:32: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-24 22:04:05.000000000 -0400 > +++ libvirt.topology/src/xen_internal.c 2007-09-24 22:32:53.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; > @@ -2466,6 +2466,10 @@ xenHypervisorMakeCapabilitiesXML(virConn > </guest>\n", -1); > if (r == -1) goto vir_buffer_failed; > } > + topology = xenDaemonNodeGetTopology(conn, xml); > + if (topology != 0) > + goto topology_failed; > + > r = virBufferAdd (xml, > "\ > </capabilities>\n", -1); > @@ -2478,6 +2482,7 @@ xenHypervisorMakeCapabilitiesXML(virConn > > vir_buffer_failed: > virXenError(VIR_ERR_NO_MEMORY, __FUNCTION__, 0); > + topology_failed: > virBufferFree (xml); > return NULL; > } Okay, end looks fine to me. Now we just need to check if this works :-) thanks ! Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@xxxxxxxxxx | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/ -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list