File kdump-fate318842-0001-use-proc-iomem.patch of Package kdump
From: Petr Tesarik <ptesarik@suse.com>
Date: Thu, 17 Sep 2015 13:41:22 +0200
Subject: Use /proc/iomem to determine total system RAM
References: FATE#318842, bsc#882082
Patch-mainline: v0.8.16
Git-commit: 2f94cadb7e6932a64836634ad00b975b3678eedc
Util::getMemorySize() reads MemTotal from /proc/meminfo. However, this
value does not include memory already reserved for the crash kernel.
Instead, get the total RAM by parsing /proc/iomem.
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
kdumptool/calibrate.cc | 150 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 149 insertions(+), 1 deletion(-)
--- a/kdumptool/calibrate.cc
+++ b/kdumptool/calibrate.cc
@@ -21,6 +21,7 @@
#include <cerrno>
#include <cstring>
#include <cstdlib>
+#include <limits>
#include <unistd.h>
#include <dirent.h>
@@ -645,6 +646,152 @@ const SlabInfos::Map& SlabInfos::getInfo
}
//}}}
+//{{{ MemRange -----------------------------------------------------------------
+
+class MemRange {
+
+ public:
+
+ typedef unsigned long long Addr;
+
+ /**
+ * Initialize a new MemRange object.
+ *
+ * @param[in] start First address within the range
+ * @param[in] end Last address within the range
+ */
+ MemRange(Addr start, Addr end)
+ throw ()
+ : m_start(start), m_end(end)
+ {}
+
+ /**
+ * Get first address in range.
+ */
+ Addr start(void) const
+ throw ()
+ { return m_start; }
+
+ /**
+ * Get last address in range.
+ */
+ Addr end(void) const
+ throw ()
+ { return m_end; }
+
+ /**
+ * Get range length.
+ *
+ * @return number of bytes in the range
+ */
+ Addr length() const
+ throw ()
+ { return m_end - m_start + 1; }
+
+ protected:
+
+ Addr m_start, m_end;
+};
+
+//}}}
+//{{{ MemMap -------------------------------------------------------------------
+
+class MemMap {
+
+ public:
+
+ typedef std::list<const MemRange*> List;
+
+ /**
+ * Initialize a new MemMap object.
+ *
+ * @param[in] procdir Mount point for procfs
+ */
+ MemMap(const char *procdir = "/proc");
+
+ ~MemMap()
+ { destroyRanges(); }
+
+ /**
+ * Get the total System RAM (in bytes).
+ */
+ unsigned long long total(void) const
+ throw ();
+
+ private:
+
+ List m_ranges;
+
+ /**
+ * Destroy MemRange objects in m_ranges.
+ */
+ void destroyRanges(void)
+ throw();
+};
+
+MemMap::MemMap(const char *procdir)
+{
+ FilePath path(procdir);
+
+ path.appendPath("iomem");
+ ifstream f(path.c_str());
+ if (!f)
+ throw KError(path + ": Open failed");
+
+ f.setf(std::ios::hex, std::ios::basefield);
+ while (f) {
+ if (f.peek() != ' ' && !f.eof()) {
+ MemRange::Addr start, end;
+
+ if (!(f >> start))
+ throw KError("Invalid resource start");
+ if (f.get() != '-')
+ throw KError("Invalid range delimiter");
+ if (!(f >> end))
+ throw KError("Invalid resource end");
+
+ int c;
+ while ((c = f.get()) == ' ');
+ if (c != ':')
+ throw KError("Invalid resource name delimiter");
+ while ((c = f.get()) == ' ');
+ f.unget();
+
+ std::string name;
+ std::getline(f, name);
+ if (name == "System RAM")
+ m_ranges.push_back(new MemRange(start, end));
+ } else
+ f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+ }
+
+ f.close();
+}
+
+// -----------------------------------------------------------------------------
+void MemMap::destroyRanges(void)
+ throw()
+{
+ List::iterator it;
+ for (it = m_ranges.begin(); it != m_ranges.end(); ++it)
+ delete *it;
+ m_ranges.clear();
+}
+
+// -----------------------------------------------------------------------------
+unsigned long long MemMap::total(void) const
+ throw ()
+{
+ List::const_iterator it;
+ unsigned long long ret = 0;
+
+ for (it = m_ranges.begin(); it != m_ranges.end(); ++it)
+ ret += (*it)->length();
+
+ return ret;
+}
+
+//}}}
//{{{ Calibrate ----------------------------------------------------------------
// -----------------------------------------------------------------------------
@@ -673,7 +820,8 @@ void Calibrate::execute()
bool needsnet = config->needsNetwork();
// Get total RAM size
- unsigned long memtotal = Util::getMemorySize();
+ MemMap mm;
+ unsigned long memtotal = shr_round_up(mm.total(), 10);
Debug::debug()->dbg("Expected total RAM: %lu KiB", memtotal);
// Calculate boot requirements