diff --git a/0001-multipath-Write-proper-regex-into-multipath-conf.patch b/0001-multipath-Write-proper-regex-into-multipath-conf.patch index f7d6af9..c256592 100644 --- a/0001-multipath-Write-proper-regex-into-multipath-conf.patch +++ b/0001-multipath-Write-proper-regex-into-multipath-conf.patch @@ -1,7 +1,6 @@ From 4ce21a05fdfa91cb894d140c1962b29fb4b1431a Mon Sep 17 00:00:00 2001 From: Julian Wolf Date: Mon, 1 Sep 2014 15:46:21 +0200 -References: bnc#883883 Subject: multipath: Write proper regex into multipath.conf Signed-off-by: Julian Wolf diff --git a/kdump-count-const-slabs.patch b/kdump-count-const-slabs.patch new file mode 100644 index 0000000..04b1e10 --- /dev/null +++ b/kdump-count-const-slabs.patch @@ -0,0 +1,249 @@ +From: Petr Tesarik +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 + +--- + 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 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) { diff --git a/kdump-count-framebuffer.patch b/kdump-count-framebuffer.patch new file mode 100644 index 0000000..888005c --- /dev/null +++ b/kdump-count-framebuffer.patch @@ -0,0 +1,228 @@ +From: Petr Tesarik +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 + +--- + 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 + #include + #include ++#include ++#include + #include ++#include + + #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) { diff --git a/kdump.changes b/kdump.changes index 3ba5646..df65ae8 100644 --- a/kdump.changes +++ b/kdump.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +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 diff --git a/kdump.spec b/kdump.spec index 3ef4185..e241474 100644 --- a/kdump.spec +++ b/kdump.spec @@ -66,6 +66,8 @@ 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} @@ -105,6 +107,8 @@ Authors: %setup %patch0 -p1 %patch1 -p1 +%patch2 -p1 +%patch3 -p1 %build export CFLAGS="%optflags"