From ad18ff9dbfb00f41647dfffc055720642c99d666 Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Date: Fri, 2 Mar 2012 10:54:22 +0800
Subject: [PATCH] add nodeGetCPUmap() for getting available CPU IDs in a
 cpumap.

Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
 src/libvirt_private.syms |  1 +
 src/nodeinfo.c           | 68 +++++++++++++++++++++++++++++++++++++++-
 src/nodeinfo.h           |  5 ++-
 3 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6939e503d4..1f58832ebb 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -802,6 +802,7 @@ virNodeDeviceObjUnlock;
 
 # nodeinfo.h
 nodeCapsInitNUMA;
+nodeGetCPUmap;
 nodeGetCPUStats;
 nodeGetCellsFreeMemory;
 nodeGetFreeMemory;
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 0c86a7eb90..709e94a4a6 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -1,7 +1,7 @@
 /*
  * nodeinfo.c: Helper routines for OS specific node information
  *
- * Copyright (C) 2006-2008, 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2008, 2010-2012 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -31,6 +31,7 @@
 #include <dirent.h>
 #include <sys/utsname.h>
 #include <sched.h>
+#include "conf/domain_conf.h"
 
 #if HAVE_NUMACTL
 # define NUMA_VERSION1_COMPATIBILITY 1
@@ -569,6 +570,47 @@ int linuxNodeGetMemoryStats(FILE *meminfo,
 cleanup:
     return ret;
 }
+
+/*
+ * Linux maintains cpu bit map. For example, if cpuid=5's flag is not set
+ * and max cpu is 7. The map file shows 0-4,6-7. This function parses
+ * it and returns cpumap.
+ */
+static char *
+linuxParseCPUmap(int *max_cpuid, const char *path)
+{
+    char *map = NULL;
+    char *str = NULL;
+    int max_id, i;
+
+    if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+
+    if (VIR_ALLOC_N(map, VIR_DOMAIN_CPUMASK_LEN) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+    if (virDomainCpuSetParse(str, 0, map,
+                             VIR_DOMAIN_CPUMASK_LEN) < 0) {
+        goto error;
+    }
+
+    for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; i++) {
+        if (map[i]) {
+            max_id = i;
+        }
+    }
+    *max_cpuid = max_id;
+
+    return map;
+
+error:
+    VIR_FREE(str);
+    VIR_FREE(map);
+    return NULL;
+}
 #endif
 
 int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
@@ -712,6 +754,30 @@ int nodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED,
 #endif
 }
 
+char *
+nodeGetCPUmap(virConnectPtr conn ATTRIBUTE_UNUSED,
+              int *max_id ATTRIBUTE_UNUSED,
+              const char *mapname ATTRIBUTE_UNUSED)
+{
+#ifdef __linux__
+    char *path;
+    char *cpumap;
+
+    if (virAsprintf(&path, CPU_SYS_PATH "/%s", mapname) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    cpumap = linuxParseCPUmap(max_id, path);
+    VIR_FREE(path);
+    return cpumap;
+#else
+    nodeReportError(VIR_ERR_NO_SUPPORT, "%s",
+                    _("node cpumap not implemented on this platform"));
+    return NULL;
+#endif
+}
+
 #if HAVE_NUMACTL
 # if LIBNUMA_API_VERSION <= 1
 #  define NUMA_MAX_N_CPUS 4096
diff --git a/src/nodeinfo.h b/src/nodeinfo.h
index 47661527dd..7d2ef1d224 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -1,7 +1,7 @@
 /*
  * nodeinfo.c: Helper routines for OS specific node information
  *
- * Copyright (C) 2006-2008, 2011 Red Hat, Inc.
+ * Copyright (C) 2006-2008, 2011-2012 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -46,4 +46,7 @@ int nodeGetCellsFreeMemory(virConnectPtr conn,
                            int maxCells);
 unsigned long long nodeGetFreeMemory(virConnectPtr conn);
 
+char *nodeGetCPUmap(virConnectPtr conn,
+                    int *max_id,
+                    const char *mapname);
 #endif /* __VIR_NODEINFO_H__*/