Accepting request 248056 from Kernel:kdump

- kdump-count-const-slabs.patch: Take constant-size slabs into
  account for "kdump calibrate" (bnc#879460).

- kdump-count-framebuffer.patch: Take framebuffer size into account
  for "kdumptool calibrate" (bnc#879460). (forwarded request 248055 from ptesarik)

OBS-URL: https://build.opensuse.org/request/show/248056
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/kdump?expand=0&rev=77
This commit is contained in:
Stephan Kulow 2014-09-08 19:28:42 +00:00 committed by Git OBS Bridge
commit 5989740255
5 changed files with 535 additions and 0 deletions

View File

@ -0,0 +1,249 @@
From: Petr Tesarik <ptesarik@suse.cz>
Date: Mon Sep 8 17:33:38 2014 +0200
Subject: Take constant-size slabs into account for "kdump calibrate"
References: bnc#879460
Patch-mainline: v0.8.16
Git-commit: 3a7c9b3a02893ab9ac39e23cae5ead9e42716927
Some slabs do not depend on available memory or system utilization.
Their size can be taken directly from the running kernel.
Note that the size of the ACPI slab cache may vary widely across
machines (e.g. mine has only a few hundred kilobytes, while another
one I saw had over 10 megabytes).
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
kdumptool/calibrate.cc | 213 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 213 insertions(+)
--- a/kdumptool/calibrate.cc
+++ b/kdumptool/calibrate.cc
@@ -448,6 +448,201 @@ unsigned long Framebuffers::size(void) c
}
//}}}
+//{{{ SlabInfo -----------------------------------------------------------------
+
+class SlabInfo {
+
+ public:
+ /**
+ * Initialize a new SlabInfo object.
+ *
+ * @param[in] line Line from /proc/slabinfo
+ */
+ SlabInfo(const KString &line);
+
+ protected:
+ bool m_comment;
+ KString m_name;
+ unsigned long m_active_objs;
+ unsigned long m_num_objs;
+ unsigned long m_obj_size;
+ unsigned long m_obj_per_slab;
+ unsigned long m_pages_per_slab;
+ unsigned long m_active_slabs;
+ unsigned long m_num_slabs;
+
+ public:
+ bool isComment(void) const
+ throw ()
+ { return m_comment; }
+
+ const KString &name(void) const
+ throw ()
+ { return m_name; }
+
+ unsigned long activeObjs(void) const
+ throw ()
+ { return m_active_objs; }
+
+ unsigned long numObjs(void) const
+ throw ()
+ { return m_num_objs; }
+
+ unsigned long objSize(void) const
+ throw ()
+ { return m_obj_size; }
+
+ unsigned long objPerSlab(void) const
+ throw ()
+ { return m_obj_per_slab; }
+
+ unsigned long pagesPerSlab(void) const
+ throw ()
+ { return m_pages_per_slab; }
+
+ unsigned long activeSlabs(void) const
+ throw ()
+ { return m_active_slabs; }
+
+ unsigned long numSlabs(void) const
+ throw ()
+ { return m_num_slabs; }
+};
+
+// -----------------------------------------------------------------------------
+SlabInfo::SlabInfo(const KString &line)
+{
+ static const char slabdata_mark[] = " : slabdata ";
+
+ std::istringstream ss(line);
+ ss >> m_name;
+ if (!ss)
+ throw KError("Invalid slabinfo line: " + line);
+
+ if (m_name[0] == '#') {
+ m_comment = true;
+ return;
+ }
+ m_comment = false;
+
+ ss >> m_active_objs >> m_num_objs >> m_obj_size
+ >> m_obj_per_slab >> m_pages_per_slab;
+ if (!ss)
+ throw KError("Invalid slabinfo line: " + line);
+
+ size_t sdpos = line.find(slabdata_mark, ss.tellg());
+ if (sdpos == KString::npos)
+ throw KError("Invalid slabinfo line: " + line);
+
+ ss.seekg(sdpos + sizeof(slabdata_mark) - 1, ss.beg);
+ ss >> m_active_slabs >> m_num_slabs;
+ if (!ss)
+ throw KError("Invalid slabinfo line: " + line);
+}
+
+//}}}
+//{{{ SlabInfos ----------------------------------------------------------------
+
+// Taken from procps:
+#define SLABINFO_LINE_LEN 2048
+#define SLABINFO_VER_LEN 100
+
+class SlabInfos {
+
+ public:
+ typedef std::map<KString, const SlabInfo*> Map;
+
+ /**
+ * Initialize a new SlabInfos object.
+ *
+ * @param[in] procdir Mount point for procfs
+ */
+ SlabInfos(const char *procdir = "/proc")
+ throw ()
+ : m_path(FilePath(procdir).appendPath("slabinfo"))
+ {}
+
+ ~SlabInfos()
+ { destroyInfo(); }
+
+ protected:
+ /**
+ * Path to the slabinfo file
+ */
+ const FilePath m_path;
+
+ /**
+ * SlabInfo for each slab
+ */
+ Map m_info;
+
+ private:
+ /**
+ * Destroy SlabInfo objects in m_info.
+ */
+ void destroyInfo(void)
+ throw();
+
+ public:
+ /**
+ * Read the information about each slab.
+ */
+ const Map& getInfo(void);
+};
+
+// -----------------------------------------------------------------------------
+void SlabInfos::destroyInfo(void)
+ throw()
+{
+ Map::iterator it;
+ for (it = m_info.begin(); it != m_info.end(); ++it)
+ delete it->second;
+ m_info.clear();
+}
+
+// -----------------------------------------------------------------------------
+const SlabInfos::Map& SlabInfos::getInfo(void)
+{
+ static const char verhdr[] = "slabinfo - version: ";
+ char buf[SLABINFO_VER_LEN], *p, *end;
+ unsigned long major, minor;
+
+ std::ifstream f(m_path.c_str());
+ if (!f)
+ throw KError(m_path + ": Open failed");
+ f.getline(buf, sizeof buf);
+ if (f.bad())
+ throw KError(m_path + ": Read failed");
+ else if (!f || strncmp(buf, verhdr, sizeof(verhdr)-1))
+ throw KError(m_path + ": Invalid version");
+ p = buf + sizeof(verhdr) - 1;
+
+ major = strtoul(p, &end, 10);
+ if (end == p || *end != '.')
+ throw KError(m_path + ": Invalid version");
+ p = end + 1;
+ minor = strtoul(p, &end, 10);
+ if (end == p || *end != '\0')
+ throw KError(m_path + ": Invalid version");
+ Debug::debug()->dbg("Found slabinfo version %lu.%lu", major, minor);
+
+ if (major != 2)
+ throw KError(m_path + ": Unsupported slabinfo version");
+
+ char line[SLABINFO_LINE_LEN];
+ while(f.getline(line, SLABINFO_LINE_LEN)) {
+ SlabInfo *si = new SlabInfo(line);
+ if (si->isComment()) {
+ delete si;
+ continue;
+ }
+ m_info[si->name()] = si;
+ }
+
+ return m_info;
+}
+
+//}}}
//{{{ Calibrate ----------------------------------------------------------------
// -----------------------------------------------------------------------------
@@ -498,6 +693,24 @@ void Calibrate::execute()
required += DEF_FRAMEBUFFER_KB;
}
+ // Add space for constant slabs
+ try {
+ SlabInfos slab;
+ SlabInfos::Map info = slab.getInfo();
+ SlabInfos::Map::iterator it;
+ for (it = info.begin(); it != info.end(); ++it) {
+ if (it->first.startsWith("Acpi-") ||
+ it->first.startsWith("ftrace_") ) {
+ unsigned long slabsize = it->second->numSlabs() *
+ it->second->pagesPerSlab() * pagesize / 1024;
+ Debug::debug()->dbg("Adding %ld KiB for %s slab cache",
+ slabsize, it->second->name().c_str());
+ }
+ }
+ } catch (KError e) {
+ Debug::debug()->dbg("Cannot get slab sizes: %s", e.what());
+ }
+
// Add memory based on CPU count
unsigned long cpus;
if (CAN_REDUCE_CPUS) {

View File

@ -0,0 +1,228 @@
From: Petr Tesarik <ptesarik@suse.cz>
Date: Mon Sep 8 09:28:04 2014 +0200
Subject: Take framebuffer size into account for "kdumptool calibrate"
References: bnc#879460
Patch-mainline: v0.8.16
Git-commit: 77ad2fff73fc6dd2dd0615e56967721ba9b96d83
Git-commit: 7cd4e826671ded8fe36a4b4bdeef1223ce8397ca
Depending on the resolution, framebuffer(s) may considerably influence
kdump kernel requirements.
Note that there is no framebuffer on z/Series, so after reading sysfs
fails, the default size for s390(x) is zero.
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
kdumptool/calibrate.cc | 153 +++++++++++++++++++++++++++++++++++++++++++++++++
kdumptool/fileutil.cc | 2
kdumptool/fileutil.h | 2
3 files changed, 155 insertions(+), 2 deletions(-)
--- a/kdumptool/fileutil.cc
+++ b/kdumptool/fileutil.cc
@@ -295,7 +295,7 @@ FilePath FilePath::getCanonicalPath(cons
}
// -----------------------------------------------------------------------------
-StringVector FilePath::listDir(const ListDirFilter &filter)
+StringVector FilePath::listDir(const ListDirFilter &filter) const
throw (KError)
{
StringVector v;
--- a/kdumptool/fileutil.h
+++ b/kdumptool/fileutil.h
@@ -224,7 +224,7 @@ class FilePath : public KString {
* list, @c false if all files should be included
* @exception KError if something went wrong
*/
- StringVector listDir(const ListDirFilter &filter)
+ StringVector listDir(const ListDirFilter &filter) const
throw (KError);
/**
--- a/kdumptool/calibrate.cc
+++ b/kdumptool/calibrate.cc
@@ -19,7 +19,10 @@
#include <iostream>
#include <fstream>
#include <cerrno>
+#include <cstring>
+#include <cstdlib>
#include <unistd.h>
+#include <dirent.h>
#include "subcommand.h"
#include "debug.h"
@@ -173,6 +176,13 @@ static inline unsigned long s390x_align_
// Estimated non-changing dynamic data (sysfs, procfs, etc.)
#define KERNEL_DYNAMIC_KB MB(4)
+// Default framebuffer size: 1024x768 @ 32bpp, except on mainframe
+#if defined(__s390__) || defined(__s390x__)
+# define DEF_FRAMEBUFFER_KB 0
+#else
+# define DEF_FRAMEBUFFER_KB (768UL*4)
+#endif
+
// large hashes, default settings: -> per MiB
// PID: sizeof(void*) for each 256 KiB 4
// Dentry cache: sizeof(void*) for each 8 KiB 128
@@ -303,6 +313,141 @@ unsigned long SystemCPU::count(const cha
}
//}}}
+//{{{ Framebuffer --------------------------------------------------------------
+
+class Framebuffer {
+
+ public:
+ /**
+ * Initialize a new Framebuffer object.
+ *
+ * @param[in] fbpath Framebuffer sysfs directory path
+ */
+ Framebuffer(const char *fbpath)
+ throw ()
+ : m_dir(fbpath)
+ {}
+
+ protected:
+ /**
+ * Path to the framebuffer device base directory
+ */
+ const FilePath m_dir;
+
+ public:
+ /**
+ * Get length of the framebuffer [in bytes].
+ */
+ unsigned long size(void) const;
+};
+
+// -----------------------------------------------------------------------------
+unsigned long Framebuffer::size(void) const
+{
+ FilePath fp;
+ std::ifstream f;
+ unsigned long width, height, stride;
+ char sep;
+
+ fp.assign(m_dir);
+ fp.appendPath("virtual_size");
+ f.open(fp.c_str());
+ if (!f)
+ throw KError(fp + ": Open failed");
+ f >> width >> sep >> height;
+ f.close();
+ if (f.bad())
+ throw KError(fp + ": Read failed");
+ else if (!f || sep != ',')
+ throw KError(fp + ": Invalid content!");
+ Debug::debug()->dbg("Framebuffer virtual size: %lux%lu", width, height);
+
+ fp.assign(m_dir);
+ fp.appendPath("stride");
+ f.open(fp.c_str());
+ if (!f)
+ throw KError(fp + ": Open failed");
+ f >> stride;
+ f.close();
+ if (f.bad())
+ throw KError(fp + ": Read failed");
+ else if (!f || sep != ',')
+ throw KError(fp + ": Invalid content!");
+ Debug::debug()->dbg("Framebuffer stride: %lu bytes", stride);
+
+ return stride * height;
+}
+
+//}}}
+//{{{ Framebuffers -------------------------------------------------------------
+
+class Framebuffers {
+
+ public:
+ /**
+ * Initialize a new Framebuffer object.
+ *
+ * @param[in] sysdir Mount point for sysfs
+ */
+ Framebuffers(const char *sysdir = "/sys")
+ throw ()
+ : m_fbdir(FilePath(sysdir).appendPath("class/graphics"))
+ {}
+
+ protected:
+ /**
+ * Path to the base directory with links to framebuffer devices
+ */
+ const FilePath m_fbdir;
+
+ /**
+ * Filter only valid framebuffer device name
+ */
+ class DirFilter : public ListDirFilter {
+
+ public:
+ virtual ~DirFilter()
+ {}
+
+ bool test(const struct dirent *d) const
+ {
+ char *end;
+ if (strncmp(d->d_name, "fb", 2))
+ return false;
+ strtoul(d->d_name + 2, &end, 10);
+ return (*end == '\0' && end != d->d_name + 2);
+ }
+ };
+
+ public:
+ /**
+ * Get size of all framebuffers [in bytes].
+ */
+ unsigned long size(void) const;
+};
+
+// -----------------------------------------------------------------------------
+unsigned long Framebuffers::size(void) const
+{
+ Debug::debug()->trace("Framebuffers::size()");
+
+ unsigned long ret = 0UL;
+
+ StringVector v = m_fbdir.listDir(DirFilter());
+ for (StringVector::const_iterator it = v.begin(); it != v.end(); ++it) {
+ Debug::debug()->dbg("Found framebuffer: %s", it->c_str());
+
+ FilePath fp(m_fbdir);
+ fp.appendPath(*it);
+ Framebuffer fb(fp.c_str());
+ ret += fb.size();
+ }
+
+ Debug::debug()->dbg("Total size of all framebuffers: %lu bytes", ret);
+ return ret;
+}
+
+//}}}
//{{{ Calibrate ----------------------------------------------------------------
// -----------------------------------------------------------------------------
@@ -345,6 +490,14 @@ void Calibrate::execute()
// Run-time kernel requirements
required = KERNEL_KB + ramfs + KERNEL_DYNAMIC_KB;
+ try {
+ Framebuffers fb;
+ required += fb.size() / 1024UL;
+ } catch(KError e) {
+ Debug::debug()->dbg("Cannot get framebuffer size: %s", e.what());
+ required += DEF_FRAMEBUFFER_KB;
+ }
+
// Add memory based on CPU count
unsigned long cpus;
if (CAN_REDUCE_CPUS) {

View File

@ -0,0 +1,34 @@
From: Petr Tesarik <ptesarik@suse.cz>
Date: Fri Sep 5 12:26:36 2014 +0200
Subject: Use device from /etc/fstab to mount / and /boot
References: bnc#892451
Patch-mainline: v0.8.16
Git-commit: 2895d4a8d24dd9b0a83e64cd58e464a3eaf7fe96
Since kdump_read_mounts() falls back to /proc/mounts, the root/boot
mount points must not be changed if they were found in /etc/fstab
previously.
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
diff --git a/init/setup-kdump.functions b/init/setup-kdump.functions
index a676a82..2b96f8e 100644
--- a/init/setup-kdump.functions
+++ b/init/setup-kdump.functions
@@ -388,12 +388,14 @@ function kdump_get_mountpoints() # {{{
kdump_opts=( )
while read device mountpoint filesystem opts dummy ; do
- if [ "$mountpoint" = "/" ] ; then
+ if [ "$mountpoint" = "/" -a \
+ -z "$rootmnt" ] ; then
rootdev="$device"
rootmnt="$mountpoint"
rootfstype="$filesystem"
rootopts="$opts"
- elif [ "$mountpoint" = "/boot" ] ; then
+ elif [ "$mountpoint" = "/boot" -a \
+ -z "$bootmnt" ] ; then
bootdev="$device"
bootmnt="$mountpoint"
bootfstype="$filesystem"

View File

@ -1,3 +1,21 @@
-------------------------------------------------------------------
Mon Sep 8 15:36:29 UTC 2014 - ptesarik@suse.cz
- kdump-count-const-slabs.patch: Take constant-size slabs into
account for "kdump calibrate" (bnc#879460).
-------------------------------------------------------------------
Mon Sep 8 07:40:17 UTC 2014 - ptesarik@suse.cz
- kdump-count-framebuffer.patch: Take framebuffer size into account
for "kdumptool calibrate" (bnc#879460).
-------------------------------------------------------------------
Fri Sep 5 11:42:40 UTC 2014 - ptesarik@suse.cz
- kdump-use-fstab-device.patch: Use device from /etc/fstab to mount
/ and /boot (bnc#892451).
-------------------------------------------------------------------
Mon Sep 1 14:21:38 UTC 2014 - juwolf@suse.com

View File

@ -65,6 +65,9 @@ Source: %{name}-%{version}.tar.bz2
Source2: %{name}-rpmlintrc
Source3: kdump.service
Patch0: 0001-multipath-Write-proper-regex-into-multipath-conf.patch
Patch1: %{name}-use-fstab-device.patch
Patch2: %{name}-count-framebuffer.patch
Patch3: %{name}-count-const-slabs.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
# rename "kdump-helpers" (10.3) -> "kdump" (11.0/SP2)
Provides: kdump-helpers = %{version}
@ -103,6 +106,9 @@ Authors:
%prep
%setup
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%build
export CFLAGS="%optflags"