Host Numa information in dom0

'xm info' command now also gives the cpu topology & host numa
information. This will be later used to build guest numa support.  The
patch basically changes physinfo sysctl, and adds topology_info &
numa_info sysctls, and also changes the python & libxc code
accordingly.

Signed-off-by: Nitin A Kamble <nitin.a.kamble@intel.com>
This commit is contained in:
Keir Fraser committed 2010-04-07 16:22:05 +01:00
1 parent 35e9666fc4
commit 4d6e834ba9
10 files changed
+448 -135

No files matched your search

+150 -63
View File
@@ -1151,105 +1151,178 @@ static PyObject *pyxc_pages_to_kib(XcObject *self, PyObject *args)
return PyLong_FromUnsignedLong(pages_to_kib(pages));
}
static PyObject *pyxc_physinfo(XcObject *self)
{
#define MAX_CPU_ID 255
xc_physinfo_t info;
xc_physinfo_t pinfo;
char cpu_cap[128], virt_caps[128], *p;
int i, j, max_cpu_id, nr_nodes = 0;
uint64_t free_heap;
PyObject *ret_obj, *node_to_cpu_obj, *node_to_memory_obj;
PyObject *node_to_dma32_mem_obj;
xc_cpu_to_node_t map[MAX_CPU_ID + 1];
int i;
const char *virtcap_names[] = { "hvm", "hvm_directio" };
set_xen_guest_handle(info.cpu_to_node, map);
info.max_cpu_id = MAX_CPU_ID;
if ( xc_physinfo(self->xc_handle, &info) != 0 )
if ( xc_physinfo(self->xc_handle, &pinfo) != 0 )
return pyxc_error_to_exception();
p = cpu_cap;
*p = '\0';
for ( i = 0; i < sizeof(info.hw_cap)/4; i++ )
p += sprintf(p, "%08x:", info.hw_cap[i]);
for ( i = 0; i < sizeof(pinfo.hw_cap)/4; i++ )
p += sprintf(p, "%08x:", pinfo.hw_cap[i]);
*(p-1) = 0;
p = virt_caps;
*p = '\0';
for ( i = 0; i < 2; i++ )
if ( (info.capabilities >> i) & 1 )
if ( (pinfo.capabilities >> i) & 1 )
p += sprintf(p, "%s ", virtcap_names[i]);
if ( p != virt_caps )
*(p-1) = '\0';
max_cpu_id = info.max_cpu_id;
if ( max_cpu_id > MAX_CPU_ID )
max_cpu_id = MAX_CPU_ID;
return Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s,s:s}",
"nr_nodes", pinfo.nr_nodes,
"threads_per_core", pinfo.threads_per_core,
"cores_per_socket", pinfo.cores_per_socket,
"sockets_per_node", pinfo.sockets_per_node,
"nr_cpus", pinfo.nr_cpus,
"total_memory", pages_to_kib(pinfo.total_pages),
"free_memory", pages_to_kib(pinfo.free_pages),
"scrub_memory", pages_to_kib(pinfo.scrub_pages),
"cpu_khz", pinfo.cpu_khz,
"hw_caps", cpu_cap,
"virt_caps", virt_caps);
}
/* Construct node-to-* lists. */
node_to_cpu_obj = PyList_New(0);
node_to_memory_obj = PyList_New(0);
node_to_dma32_mem_obj = PyList_New(0);
for ( i = 0; i <= info.max_node_id; i++ )
static PyObject *pyxc_topologyinfo(XcObject *self)
{
#define MAX_CPU_INDEX 255
xc_topologyinfo_t tinfo;
int i, max_cpu_index;
PyObject *ret_obj;
PyObject *cpu_to_core_obj, *cpu_to_socket_obj, *cpu_to_node_obj;
xc_cpu_to_core_t coremap[MAX_CPU_INDEX + 1];
xc_cpu_to_socket_t socketmap[MAX_CPU_INDEX + 1];
xc_cpu_to_node_t nodemap[MAX_CPU_INDEX + 1];
set_xen_guest_handle(tinfo.cpu_to_core, coremap);
set_xen_guest_handle(tinfo.cpu_to_socket, socketmap);
set_xen_guest_handle(tinfo.cpu_to_node, nodemap);
tinfo.max_cpu_index = MAX_CPU_INDEX;
if ( xc_topologyinfo(self->xc_handle, &tinfo) != 0 )
return pyxc_error_to_exception();
max_cpu_index = tinfo.max_cpu_index;
if ( max_cpu_index > MAX_CPU_INDEX )
max_cpu_index = MAX_CPU_INDEX;
/* Construct cpu-to-* lists. */
cpu_to_core_obj = PyList_New(0);
cpu_to_socket_obj = PyList_New(0);
cpu_to_node_obj = PyList_New(0);
for ( i = 0; i < max_cpu_index; i++ )
{
int node_exists = 0;
PyObject *pyint;
/* CPUs. */
PyObject *cpus = PyList_New(0);
for ( j = 0; j <= max_cpu_id; j++ )
{
if ( i != map[j] )
continue;
pyint = PyInt_FromLong(j);
PyList_Append(cpus, pyint);
Py_DECREF(pyint);
node_exists = 1;
}
PyList_Append(node_to_cpu_obj, cpus);
Py_DECREF(cpus);
pyint = PyInt_FromLong(coremap[i]);
PyList_Append(cpu_to_core_obj, pyint);
Py_DECREF(pyint);
/* Memory. */
xc_availheap(self->xc_handle, 0, 0, i, &free_heap);
node_exists = node_exists || (free_heap != 0);
pyint = PyInt_FromLong(free_heap / 1024);
PyList_Append(node_to_memory_obj, pyint);
pyint = PyInt_FromLong(socketmap[i]);
PyList_Append(cpu_to_socket_obj, pyint);
Py_DECREF(pyint);
pyint = PyInt_FromLong(nodemap[i]);
PyList_Append(cpu_to_node_obj, pyint);
Py_DECREF(pyint);
}
ret_obj = Py_BuildValue("{s:i}", "max_cpu_index", max_cpu_index);
PyDict_SetItemString(ret_obj, "cpu_to_core", cpu_to_core_obj);
Py_DECREF(cpu_to_core_obj);
PyDict_SetItemString(ret_obj, "cpu_to_socket", cpu_to_socket_obj);
Py_DECREF(cpu_to_socket_obj);
PyDict_SetItemString(ret_obj, "cpu_to_node", cpu_to_node_obj);
Py_DECREF(cpu_to_node_obj);
return ret_obj;
#undef MAX_CPU_INDEX
}
static PyObject *pyxc_numainfo(XcObject *self)
{
#define MAX_NODE_INDEX 31
xc_numainfo_t ninfo;
int i, j, max_node_index;
uint64_t free_heap;
PyObject *ret_obj;
PyObject *node_to_memsize_obj, *node_to_memfree_obj;
PyObject *node_to_dma32_mem_obj, *node_to_node_dist_obj;
xc_node_to_memsize_t node_memsize[MAX_NODE_INDEX + 1];
xc_node_to_memfree_t node_memfree[MAX_NODE_INDEX + 1];
xc_node_to_node_dist_t nodes_dist[(MAX_NODE_INDEX * MAX_NODE_INDEX) + 1];
set_xen_guest_handle(ninfo.node_to_memsize, node_memsize);
set_xen_guest_handle(ninfo.node_to_memfree, node_memfree);
set_xen_guest_handle(ninfo.node_to_node_distance, nodes_dist);
ninfo.max_node_index = MAX_NODE_INDEX;
if( xc_numainfo(self->xc_handle, &ninfo) != 0 )
return pyxc_error_to_exception();
max_node_index = ninfo.max_node_index;
if ( max_node_index > MAX_NODE_INDEX )
max_node_index = MAX_NODE_INDEX;
/* Construct node-to-* lists. */
node_to_memsize_obj = PyList_New(0);
node_to_memfree_obj = PyList_New(0);
node_to_dma32_mem_obj = PyList_New(0);
node_to_node_dist_obj = PyList_New(0);
for ( i = 0; i < max_node_index; i++ )
{
PyObject *pyint;
/* Total Memory */
pyint = PyInt_FromLong(node_memsize[i] >> 20); /* MB */
PyList_Append(node_to_memsize_obj, pyint);
Py_DECREF(pyint);
/* Free Memory */
pyint = PyInt_FromLong(node_memfree[i] >> 20); /* MB */
PyList_Append(node_to_memfree_obj, pyint);
Py_DECREF(pyint);
/* DMA memory. */
xc_availheap(self->xc_handle, 0, 32, i, &free_heap);
pyint = PyInt_FromLong(free_heap / 1024);
pyint = PyInt_FromLong(free_heap >> 20); /* MB */
PyList_Append(node_to_dma32_mem_obj, pyint);
Py_DECREF(pyint);
if ( node_exists )
nr_nodes++;
/* Node to Node Distance */
for ( j = 0; j < ninfo.max_node_index; j++ )
{
pyint = PyInt_FromLong(nodes_dist[(i * ninfo.max_node_index) + j]);
PyList_Append(node_to_node_dist_obj, pyint);
Py_DECREF(pyint);
}
}
ret_obj = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s:s:s}",
"nr_nodes", nr_nodes,
"max_node_id", info.max_node_id,
"max_cpu_id", info.max_cpu_id,
"threads_per_core", info.threads_per_core,
"cores_per_socket", info.cores_per_socket,
"nr_cpus", info.nr_cpus,
"total_memory", pages_to_kib(info.total_pages),
"free_memory", pages_to_kib(info.free_pages),
"scrub_memory", pages_to_kib(info.scrub_pages),
"cpu_khz", info.cpu_khz,
"hw_caps", cpu_cap,
"virt_caps", virt_caps);
PyDict_SetItemString(ret_obj, "node_to_cpu", node_to_cpu_obj);
Py_DECREF(node_to_cpu_obj);
PyDict_SetItemString(ret_obj, "node_to_memory", node_to_memory_obj);
Py_DECREF(node_to_memory_obj);
ret_obj = Py_BuildValue("{s:i}", "max_node_index", max_node_index);
PyDict_SetItemString(ret_obj, "node_memsize", node_to_memsize_obj);
Py_DECREF(node_to_memsize_obj);
PyDict_SetItemString(ret_obj, "node_memfree", node_to_memfree_obj);
Py_DECREF(node_to_memfree_obj);
PyDict_SetItemString(ret_obj, "node_to_dma32_mem", node_to_dma32_mem_obj);
Py_DECREF(node_to_dma32_mem_obj);
PyDict_SetItemString(ret_obj, "node_to_node_dist", node_to_node_dist_obj);
Py_DECREF(node_to_node_dist_obj);
return ret_obj;
#undef MAX_CPU_ID
#undef MAX_NODE_INDEX
}
static PyObject *pyxc_xeninfo(XcObject *self)
@@ -2058,6 +2131,20 @@ static PyMethodDef pyxc_methods[] = {
"Returns [dict]: information about the hardware"
" [None]: on failure.\n" },
{ "topologyinfo",
(PyCFunction)pyxc_topologyinfo,
METH_NOARGS, "\n"
"Get information about the cpu topology on the host machine\n"
"Returns [dict]: information about the cpu topology on host"
" [None]: on failure.\n" },
{ "numainfo",
(PyCFunction)pyxc_numainfo,
METH_NOARGS, "\n"
"Get NUMA information on the host machine\n"
"Returns [dict]: NUMA information on host"
" [None]: on failure.\n" },
{ "xeninfo",
(PyCFunction)pyxc_xeninfo,
METH_NOARGS, "\n"
+37 -32
View File
@@ -878,66 +878,71 @@ class XendNode:
def list_to_strrange(self,list):
return self.format_pairs(self.list_to_rangepairs(list))
def format_node_to_cpu(self, pinfo):
str=''
whitespace=''
def format_cpu_to_core_socket_node(self, tinfo):
try:
node_to_cpu=pinfo['node_to_cpu']
for i in range(0, pinfo['max_node_id']+1):
str+='%snode%d:%s\n' % (whitespace,
i,
self.list_to_strrange(node_to_cpu[i]))
whitespace='%25s' % ''
except:
str='none\n'
return str[:-1];
def format_node_to_memory(self, pinfo, key):
str=''
whitespace=''
try:
node_to_memory=pinfo[key]
for i in range(0, pinfo['max_node_id']+1):
str+='%snode%d:%d\n' % (whitespace,
i,
node_to_memory[i] / 1024)
whitespace='%25s' % ''
nr_cpus=tinfo['max_cpu_index']
str='\ncpu: core socket node\n'
for i in range(0, nr_cpus):
str+='%3d:%8d %8d %8d\n' % (i,
tinfo['cpu_to_core'][i],
tinfo['cpu_to_socket'][i],
tinfo['cpu_to_node'][i])
except:
str='none\n'
return str[:-1];
def format_numa_info(self, ninfo):
try:
nr_nodes=ninfo['max_node_index']
str='\nnode: TotalMemory FreeMemory dma32Memory NodeDist:'
for i in range(0, nr_nodes):
str+='%4d ' % i
str+='\n'
for i in range(0, nr_nodes):
str+='%4d: %8dMB %8dMB %8dMB :' % (i,
ninfo['node_memsize'][i],
ninfo['node_memfree'][i],
ninfo['node_to_dma32_mem'][i])
for j in range(0, nr_nodes):
str+='%4d ' % ninfo['node_to_node_dist'][(i*nr_nodes)+j]
str+='\n'
except:
str='none\n'
return str[:-1];
def physinfo(self):
info = self.xc.physinfo()
tinfo = self.xc.topologyinfo()
ninfo = self.xc.numainfo()
info['cpu_mhz'] = info['cpu_khz'] / 1000
# physinfo is in KiB, need it in MiB
info['total_memory'] = info['total_memory'] / 1024
info['free_memory'] = info['free_memory'] / 1024
info['node_to_cpu'] = self.format_node_to_cpu(info)
info['node_to_memory'] = \
self.format_node_to_memory(info, 'node_to_memory')
info['node_to_dma32_mem'] = \
self.format_node_to_memory(info, 'node_to_dma32_mem')
info['cpu_topology'] = \
self.format_cpu_to_core_socket_node(tinfo)
info['numa_info'] = \
self.format_numa_info(ninfo)
ITEM_ORDER = ['nr_cpus',
'nr_nodes',
'cores_per_socket',
'threads_per_core',
'sockets_per_node',
'cpu_mhz',
'hw_caps',
'virt_caps',
'total_memory',
'free_memory',
'node_to_cpu',
'node_to_memory',
'node_to_dma32_mem',
'max_node_id'
'cpu_topology',
'numa_info',
]
return [[k, info[k]] for k in ITEM_ORDER]
def pciinfo(self):
from xen.xend.server.pciif import get_all_assigned_pci_devices
assigned_devs = get_all_assigned_pci_devices()
+5 -9
View File
@@ -184,15 +184,11 @@ def free(need_mem, dominfo):
waitscrub = 1
vcpus = dominfo.info['cpus'][0]
for vcpu in vcpus:
nodenum = 0
for node in physinfo['node_to_cpu']:
for cpu in node:
if vcpu == cpu:
if oldnode == -1:
oldnode = nodenum
elif oldnode != nodenum:
waitscrub = 0
nodenum = nodenum + 1
nodenum = xc.numainfo()['cpu_to_node'][cpu]
if oldnode == -1:
oldnode = nodenum
elif oldnode != nodenum:
waitscrub = 0
if waitscrub == 1 and scrub_mem > 0:
log.debug("wait for scrub %s", scrub_mem)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.