Blob Blame History Raw
From 702382ac8b5385ce15f807016582b54793141c4b Mon Sep 17 00:00:00 2001
From: Dan Callaghan <dcallagh@redhat.com>
Date: Mon, 13 Jul 2015 15:06:59 +1000
Subject: [PATCH 18/26] guess memory size from memory hotplug info (#694)

---
 src/core/Makefile |  2 +-
 src/core/mem.cc   | 35 +++++++++++++++++++++++++++++++++--
 src/core/sysfs.cc | 16 ++++++++++++++++
 src/core/sysfs.h  |  2 ++
 4 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/src/core/Makefile b/src/core/Makefile
index 2d95a80..884a963 100644
--- a/src/core/Makefile
+++ b/src/core/Makefile
@@ -39,7 +39,7 @@ main.o: device-tree.h pci.h pcmcia.h pcmcia-legacy.h ide.h scsi.h spd.h
 main.o: network.h isapnp.h fb.h usb.h sysfs.h display.h parisc.h cpufreq.h
 main.o: ideraid.h mounts.h smp.h abi.h s390.h virtio.h pnp.h vio.h
 print.o: print.h hw.h options.h version.h osutils.h config.h
-mem.o: version.h config.h mem.h hw.h
+mem.o: version.h config.h mem.h hw.h sysfs.h
 dmi.o: version.h config.h dmi.h hw.h osutils.h
 device-tree.o: version.h device-tree.h hw.h osutils.h
 cpuinfo.o: version.h cpuinfo.h hw.h osutils.h
diff --git a/src/core/mem.cc b/src/core/mem.cc
index 686cc16..72bfb35 100644
--- a/src/core/mem.cc
+++ b/src/core/mem.cc
@@ -5,9 +5,10 @@
  * sources:
  * - the size of /proc/kcore
  * - the value returned by the sysconf libc function
+ * - the sum of sizes of kernel hotplug memory blocks
  * - the sum of sizes of individual memory banks
  *
- * NOTE: Except in last case, this guess can be widely inaccurate, as the
+ * NOTE: In the first two cases this guess can be widely inaccurate, as the
  * kernel itself limits the memory addressable by userspace processes.
  * Because of that, this module reports the biggest value found if it can't
  * access the size of individual memory banks (information filled in by other
@@ -17,6 +18,7 @@
 
 #include "version.h"
 #include "config.h"
+#include "sysfs.h"
 #include "mem.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -52,6 +54,31 @@ static unsigned long long get_sysconf_size()
 }
 
 
+static unsigned long long get_hotplug_size()
+{
+  vector < sysfs::entry > entries = sysfs::entries_by_bus("memory");
+
+  if (entries.empty())
+    return 0;
+
+  unsigned long long memblocksize =
+    sysfs::entry::byPath("/system/memory").hex_attr("block_size_bytes");
+  if (memblocksize == 0)
+    return 0;
+
+  unsigned long long totalsize = 0;
+  for (vector < sysfs::entry >::iterator it = entries.begin();
+      it != entries.end(); ++it)
+  {
+    const sysfs::entry & e = *it;
+    if (e.string_attr("online") != "1")
+      continue;
+    totalsize += memblocksize;
+  }
+  return totalsize;
+}
+
+
 static unsigned long long count_memorybanks_size(hwNode & n)
 {
   hwNode *memory = n.getChild("core/memory");
@@ -93,9 +120,11 @@ bool scan_memory(hwNode & n)
   hwNode *memory = n.getChild("core/memory");
   unsigned long long logicalmem = 0;
   unsigned long long kcore = 0;
+  unsigned long long hotplug_size = 0;
 
   logicalmem = get_sysconf_size();
   kcore = get_kcore_size();
+  hotplug_size = get_hotplug_size();
   count_memorybanks_size(n);
   claim_memory(n);
 
@@ -127,7 +156,9 @@ bool scan_memory(hwNode & n)
     if (memory->getSize() > logicalmem)           // we already have a value
       return true;
 
-    if ((logicalmem == 0)
+    if (hotplug_size > logicalmem)
+      memory->setSize(hotplug_size);
+    else if ((logicalmem == 0)
       || ((kcore > logicalmem) && (kcore < 2 * logicalmem)))
       memory->setSize(kcore);
     else
diff --git a/src/core/sysfs.cc b/src/core/sysfs.cc
index fb7f2bb..d17d33d 100644
--- a/src/core/sysfs.cc
+++ b/src/core/sysfs.cc
@@ -239,6 +239,13 @@ entry entry::byClass(string devclass, string devname)
 }
 
 
+entry entry::byPath(string path)
+{
+  entry e(fs.path + "/devices" + path);
+  return e;
+}
+
+
 entry::entry(const string & devpath)
 {
   This = new entry_i;
@@ -318,6 +325,15 @@ string entry::string_attr(const string & name, const string & def) const
 }
 
 
+unsigned long long entry::hex_attr(const string & name, unsigned long long def) const
+{
+  string val = string_attr(name, "");
+  if (val.empty())
+    return def;
+  return strtoull(val.c_str(), NULL, 16);
+}
+
+
 vector < string > entry::multiline_attr(const string & name) const
 {
   vector < string > lines;
diff --git a/src/core/sysfs.h b/src/core/sysfs.h
index 7ceb395..a6d69ed 100644
--- a/src/core/sysfs.h
+++ b/src/core/sysfs.h
@@ -15,6 +15,7 @@ namespace sysfs
 
       static entry byBus(string devbus, string devname);
       static entry byClass(string devclass, string devname);
+      static entry byPath(string path);
 
       entry & operator =(const entry &);
       entry(const entry &);
@@ -28,6 +29,7 @@ namespace sysfs
       entry parent() const;
       string name_in_class(const string &) const;
       string string_attr(const string & name, const string & def = "") const;
+      unsigned long long hex_attr(const string & name, unsigned long long def = 0) const;
       vector < string > multiline_attr(const string & name) const;
 
       struct entry_i * This;
-- 
2.10.2