diff --git a/OOMAnalyser.html b/OOMAnalyser.html
index 10a82ff..a3cb1eb 100644
--- a/OOMAnalyser.html
+++ b/OOMAnalyser.html
@@ -104,6 +104,13 @@ THIS PROGRAM COMES WITH NO WARRANTY
/* empty - used to show sections for manually triggered OOMs */
}
+ .js-pagesize-guessed--show {
+ /* empty - used to show if the page size is guessed */
+ }
+ .js-pagesize-determined--show {
+ /* empty - used to show if the page size is determined */
+ }
+
.js-pstable_sort_col0 {
/* empty - used to sort process table */
}
@@ -871,7 +878,14 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
Page size |
|
- Guessed |
+
+
+ Extracted from DMA zone buddyinfo
+
+
+ Guessed
+
+ |
diff --git a/OOMAnalyser.py b/OOMAnalyser.py
index ce90677..721e46a 100644
--- a/OOMAnalyser.py
+++ b/OOMAnalyser.py
@@ -2799,6 +2799,9 @@ class OOMAnalyser:
)
"""RE to extract free memory chunks of a memor zone"""
+ REC_PAGE_SIZE = re.compile("Node 0 DMA: \d+\*(?P\d+)kB")
+ """RE to extract the page size from buddyinfo DMA zone"""
+
REC_WATERMARK = re.compile(
"Node (?P\d+) (?PDMA|DMA32|Normal) "
"free:(?P\d+)kB "
@@ -3018,11 +3021,23 @@ class OOMAnalyser:
call_trace += "{}\n".format(line.strip())
self.oom_result.details["call_trace"] = call_trace
+ self._extract_page_size()
self._extract_pstable()
self._extract_gpf_mask()
self._extract_buddyinfo()
self._extract_watermarks()
+ def _extract_page_size(self):
+ """Extract page size from buddyinfo DMZ zone"""
+ match = self.REC_PAGE_SIZE.search(self.oom_entity.text)
+ if match:
+ self.oom_result.details["page_size_kb"] = int(match.group("page_size"))
+ self.oom_result.details["_page_size_guessed"] = False
+ else:
+ # educated guess
+ self.oom_result.details["page_size_kb"] = 4
+ self.oom_result.details["_page_size_guessed"] = True
+
def _extract_pstable(self):
"""Extract process table"""
self.oom_result.details["_pstable"] = {}
@@ -3049,10 +3064,8 @@ class OOMAnalyser:
This function fills:
* OOMResult.buddyinfo with [][][] =
* OOMResult.buddyinfo with [zone]["total_free_kb_per_node"][node] = int(total_free_kb_per_node)
- * OOMResult.details["_buddyinfo_pagesize_kb"] with the extracted page size
"""
self.oom_result.buddyinfo = {}
- self.oom_result.details["_buddyinfo_pagesize_kb"] = None
buddy_info = self.oom_result.buddyinfo
self.oom_entity.find_text(self.oom_result.kconfig.zoneinfo_start)
@@ -3095,11 +3108,6 @@ class OOMAnalyser:
node
]
- if not self.oom_result.details["_buddyinfo_pagesize_kb"] and order == 0:
- size = element.split("*")[1]
- size = size[:-2] # strip "kB"
- self.oom_result.details["_buddyinfo_pagesize_kb"] = int(size)
-
# MAX_ORDER is actually maximum order plus one. For example,
# a value of 11 means that the largest free memory block is 2^10 pages.
# __pragma__ ('jsiter')
@@ -3352,7 +3360,6 @@ class OOMAnalyser:
highest_zoneidx = self.oom_result.kconfig.ZONE_TYPES.index(zone)
lowmem_reserve = watermark_info[zone][node]["lowmem_reserve"]
min_kb = watermark_info[zone][node]["low"]
- page_size = self.oom_result.details["_buddyinfo_pagesize_kb"]
# reduce minimum watermark for high priority calls
# ALLOC_HIGH == __GFP_HIGH
@@ -3363,7 +3370,13 @@ class OOMAnalyser:
# check watermarks, if these are not met, then a high-order request also
# cannot go ahead even if a suitable page happened to be free.
- if free_kb <= (min_kb + (lowmem_reserve[highest_zoneidx] * page_size)):
+ if free_kb <= (
+ min_kb
+ + (
+ lowmem_reserve[highest_zoneidx]
+ * self.oom_result.details["page_size_kb"]
+ )
+ ):
self.oom_result.mem_alloc_failure = (
OOMMemoryAllocFailureType.failed_below_low_watermark
)
@@ -3515,9 +3528,6 @@ class OOMAnalyser:
dist = "Ubuntu"
self.oom_result.details["dist"] = dist
- # educated guess
- self.oom_result.details["page_size_kb"] = 4
-
def _calc_from_oom_details(self):
"""
Calculate values from already extracted details
@@ -4404,6 +4414,7 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
self._show_ram_usage()
self._show_alloc_failure()
self._show_memory_fragmentation()
+ self._show_page_size()
# generate process table
self._show_pstable()
@@ -4446,6 +4457,15 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
else:
show_elements(".js-memory-no-heavy-fragmentation--show")
+ def _show_page_size(self):
+ """Show page size"""
+ if self.oom_result.details.get("_page_size_guessed", True):
+ hide_elements(".js-pagesize-determined--show")
+ show_elements(".js-pagesize-guessed--show")
+ else:
+ show_elements(".js-pagesize-determined--show")
+ hide_elements(".js-pagesize-guessed--show")
+
def _show_ram_usage(self):
"""Generate RAM usage diagram"""
ram_title_attr = (
diff --git a/test.py b/test.py
index dc130ca..a6a46c5 100755
--- a/test.py
+++ b/test.py
@@ -1049,6 +1049,25 @@ Hardware name: HP ProLiant DL385 G7, BIOS A18 12/08/2012
% (node, zone),
)
+ def test_013_page_size(self):
+ """Test determination of the page size"""
+ oom = OOMAnalyser.OOMEntity(OOMAnalyser.OOMDisplay.example_rhel7)
+ analyser = OOMAnalyser.OOMAnalyser(oom)
+ success = analyser.analyse()
+ self.assertTrue(success, "OOM analysis failed")
+
+ page_size_kb = analyser.oom_result.details["page_size_kb"]
+ self.assertEqual(
+ page_size_kb,
+ 4,
+ "Unexpected page size (got %s, expect: 4)" % page_size_kb,
+ )
+ self.assertEqual(
+ analyser.oom_result.details["_page_size_guessed"],
+ False,
+ "Page size guessed and not determinated",
+ )
+
if __name__ == "__main__":
unittest.main(verbosity=2)