Compare commits

..

No commits in common. "4e12c22c10b5f389953be0d073a6247926e218a1" and "bd3085c6672d24261d901131c0cd51df34f3c985" have entirely different histories.

3 changed files with 91 additions and 249 deletions

View File

@ -115,10 +115,6 @@ THIS PROGRAM COMES WITH NO WARRANTY
/* empty - used to hide/show details for memory fragmentation */
}
.js-memory-shortage-node--hide {
/* empty - used to show the NUMA node with memory shortage */
}
.js-oom-automatic--show {
/* empty - used to show sections for automatically triggered OOMs */
}
@ -449,7 +445,7 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
requested a memory chunk of order <span class="trigger_proc_order"></span> from the
&quot;<span class="trigger_proc_mem_zone"></span>&quot; memory zone.
This is 2<span class="text__superscript">order</span> pages ==
That are 2<span class="text__superscript">order</span> pages ==
2<span class="trigger_proc_order text__superscript"></span> pages ==
<span class="trigger_proc_requested_memory_pages"></span>
a <span class="page_size_kb"></span> ==
@ -459,17 +455,17 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
<div class="js-text--default-hide js-text--display-none js-alloc-failure--show">
<p>
<span class="js-text--default-hide js-text--display-none js-alloc-failure-below-low-watermark--show">
The request failed because the free memory would be below the memory low watermark
after its completion.
The request failed because after its fulfillment the free memory would be below the memory
low watermark.
</span>
<span class="js-text--default-hide js-text--display-none js-alloc-failure-no-free-chunks--show">
If this requirement was satisfied, the free memory would still be above the low memory watermark.
If this requirement were met, the free memory would still be above the low memory watermark.
The request failed because there is no free chunk in the current or higher order.
</span>
<span class="js-text--default-hide js-text--display-none js-alloc-failure-unknown-reason-show">
The request failed, but the reason is unknown.
</span>
This memory shortage triggers the OOM process.
The memory shortage triggers the OOM process.
</p>
</div>
<p>
@ -562,7 +558,7 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
<td class="trigger_proc_mem_zone text--align-right"></td>
<td>Memory zone from which the requested storage chunk should come.</td>
</tr>
<tr class="js-text--default-hide js-oom-automatic--show js-memory-shortage-node--hide">
<tr class="js-oom-automatic--show">
<td>Requested memory: node</td>
<td class="trigger_proc_numa_node text--align-right"></td>
<td>
@ -1091,7 +1087,6 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
<li>Add check for heavy memory fragmentation</li>
<li>Summary of the analysis revised</li>
<li>Show memory watermarks together will all details</li>
<li>Add support for kernel 6.0 and newer</li>
<li>...</li>
</ol>

View File

@ -277,8 +277,7 @@ class BaseKernelConfig:
True,
),
# split caused by a limited number of iterations during converting PY regex into JS regex
# Source: mm/page_alloc.c:__show_free_areas()
"Overall Mem-Info (part 1)": (
"Mem-Info (part 1)": (
r"^Mem-Info:.*" r"(?:\n)"
# first line (starting w/o a space)
r"^active_anon:(?P<active_anon_pages>\d+) inactive_anon:(?P<inactive_anon_pages>\d+) "
@ -292,7 +291,7 @@ class BaseKernelConfig:
r"unstable:(?P<unstable_pages>\d+)",
True,
),
"Overall Mem-Info (part 2)": (
"Mem-Info (part 2)": (
r"^ slab_reclaimable:(?P<slab_reclaimable_pages>\d+) slab_unreclaimable:(?P<slab_unreclaimable_pages>\d+)"
r"(?:\n)"
r"^ mapped:(?P<mapped_pages>\d+) shmem:(?P<shmem_pages>\d+) pagetables:(?P<pagetables_pages>\d+) "
@ -313,7 +312,6 @@ class BaseKernelConfig:
r"^(?P<pagecache_total_pages>\d+) total pagecache pages.*$",
True,
),
# Source:mm/swap_state.c:show_swap_cache_info()
"Swap usage information": (
r"^(?P<swap_cache_pages>\d+) pages in swap cache"
r"(?:\n)"
@ -536,6 +534,12 @@ class BaseKernelConfig:
pstable_non_ints = ["pid", "name", "notes"]
"""Columns that are not converted to an integer"""
REC_PROCESS_LINE = re.compile(
r"^\[(?P<pid>[ \d]+)\]\s+(?P<uid>\d+)\s+(?P<tgid>\d+)\s+(?P<total_vm_pages>\d+)\s+(?P<rss_pages>\d+)\s+"
r"(?P<nr_ptes_pages>\d+)\s+(?P<swapents_pages>\d+)\s+(?P<oom_score_adj>-?\d+)\s+(?P<name>.+)\s*"
)
"""Match content of process table"""
pstable_start = "[ pid ]"
"""
Pattern to find the start of the process table
@ -556,40 +560,12 @@ class BaseKernelConfig:
@type: (int, int, str)
"""
REC_FREE_MEMORY_CHUNKS = re.compile(
"Node (?P<node>\d+) (?P<zone>DMA|DMA32|Normal): (?P<zone_usage>.*) = (?P<total_free_kb_per_node>\d+)kB"
)
"""RE to extract free memory chunks of a memory zone"""
REC_OOM_BEGIN = re.compile(r"invoked oom-killer:", re.MULTILINE)
rec_oom_begin = re.compile(r"invoked oom-killer:", re.MULTILINE)
"""RE to match the first line of an OOM block"""
REC_OOM_END = re.compile(r"^Killed process \d+", re.MULTILINE)
rec_oom_end = re.compile(r"^Killed process \d+", re.MULTILINE)
"""RE to match the last line of an OOM block"""
REC_PAGE_SIZE = re.compile("Node 0 DMA: \d+\*(?P<page_size>\d+)kB")
"""RE to extract the page size from buddyinfo DMA zone"""
REC_PROCESS_LINE = re.compile(
r"^\[(?P<pid>[ \d]+)\]\s+(?P<uid>\d+)\s+(?P<tgid>\d+)\s+(?P<total_vm_pages>\d+)\s+(?P<rss_pages>\d+)\s+"
r"(?P<nr_ptes_pages>\d+)\s+(?P<swapents_pages>\d+)\s+(?P<oom_score_adj>-?\d+)\s+(?P<name>.+)\s*"
)
"""Match content of process table"""
REC_WATERMARK = re.compile(
"Node (?P<node>\d+) (?P<zone>DMA|DMA32|Normal) "
"free:(?P<free>\d+)kB "
"min:(?P<min>\d+)kB "
"low:(?P<low>\d+)kB "
"high:(?P<high>\d+)kB "
".*"
)
"""
RE to extract watermark information in a memory zone
Source: mm/page_alloc.c:__show_free_areas()
"""
watermark_start = "Node 0 DMA free:"
"""
Pattern to find the start of the memory watermark information
@ -1449,7 +1425,7 @@ class KernelConfig_4_6(KernelConfig_4_5):
}
# The "oom_reaper" line is optionally
REC_OOM_END = re.compile(
rec_oom_end = re.compile(
r"^((Out of memory.*|Memory cgroup out of memory): Killed process \d+|oom_reaper:)",
re.MULTILINE,
)
@ -1551,6 +1527,7 @@ class KernelConfig_4_8(KernelConfig_4_6):
class KernelConfig_4_9(KernelConfig_4_8):
# Supported changes:
# * "mm: oom: deduplicate victim selection code for memcg and global oom" (7c5f64f84483bd13886348edda8b3e7b799a7fdb)
# * update GFP flags
name = "Configuration for Linux kernel 4.9 or later"
release = (4, 9, "")
@ -2127,6 +2104,7 @@ class KernelConfig_4_18(KernelConfig_4_15):
class KernelConfig_4_19(KernelConfig_4_18):
# Supported changes:
# * mm, oom: describe task memory unit, larger PID pad (c3b78b11efbb2865433abf9d22c004ffe4a73f5c)
# * update GFP flags
name = "Configuration for Linux kernel 4.19 or later"
release = (4, 19, "")
@ -2137,6 +2115,7 @@ class KernelConfig_4_19(KernelConfig_4_18):
class KernelConfig_5_0(KernelConfig_4_19):
# Supported changes:
# * "mm, oom: reorganize the oom report in dump_header" (ef8444ea01d7442652f8e1b8a8b94278cb57eafd)
# * update GFP flags
name = "Configuration for Linux kernel 5.0 or later"
release = (5, 0, "")
@ -2243,12 +2222,13 @@ class KernelConfig_5_1(KernelConfig_5_0):
class KernelConfig_5_8(KernelConfig_5_1):
# Supported changes:
# * "mm/writeback: discard NR_UNSTABLE_NFS, use NR_WRITEBACK instead" (8d92890bd6b8502d6aee4b37430ae6444ade7a8c)
# * update GFP flags
name = "Configuration for Linux kernel 5.8 or later"
release = (5, 8, "")
EXTRACT_PATTERN_OVERLAY_58 = {
"Overall Mem-Info (part 1)": (
"Mem-Info (part 1)": (
r"^Mem-Info:.*" r"(?:\n)"
# first line (starting w/o a space)
r"^active_anon:(?P<active_anon_pages>\d+) inactive_anon:(?P<inactive_anon_pages>\d+) "
@ -2356,25 +2336,7 @@ class KernelConfig_5_14(KernelConfig_5_8):
}
class KernelConfig_5_16(KernelConfig_5_14):
# Supported changes:
# * mm/page_alloc.c: show watermark_boost of zone in zoneinfo (a6ea8b5b9f1c)
name = "Configuration for Linux kernel 5.16 or later"
release = (5, 16, "")
REC_WATERMARK = re.compile(
"Node (?P<node>\d+) (?P<zone>DMA|DMA32|Normal) "
"free:(?P<free>\d+)kB "
"boost:(?P<boost>\d+)kB "
"min:(?P<min>\d+)kB "
"low:(?P<low>\d+)kB "
"high:(?P<high>\d+)kB "
".*"
)
class KernelConfig_5_18(KernelConfig_5_16):
class KernelConfig_5_18(KernelConfig_5_14):
# Supported changes:
# * update GFP flags
@ -2466,146 +2428,8 @@ class KernelConfig_5_18(KernelConfig_5_16):
}
class KernelConfig_6_0(KernelConfig_5_18):
# Supported changes:
# * update GFP flags
# * "mm/swap: remove swap_cache_info statistics" (442701e7058b)
name = "Configuration for Linux kernel 6.0 or later"
release = (6, 0, "")
# NOTE: These flags are automatically extracted from a gfp.h file.
# Please do not change them manually!
GFP_FLAGS = {
#
#
# Useful GFP flag combinations:
"GFP_ATOMIC": {"value": "__GFP_HIGH | __GFP_ATOMIC | __GFP_KSWAPD_RECLAIM"},
"GFP_HIGHUSER": {"value": "GFP_USER | __GFP_HIGHMEM"},
"GFP_HIGHUSER_MOVABLE": {
"value": "GFP_HIGHUSER | __GFP_MOVABLE | __GFP_SKIP_KASAN_POISON | __GFP_SKIP_KASAN_UNPOISON"
},
"GFP_KERNEL": {"value": "__GFP_RECLAIM | __GFP_IO | __GFP_FS"},
"GFP_KERNEL_ACCOUNT": {"value": "GFP_KERNEL | __GFP_ACCOUNT"},
"GFP_NOFS": {"value": "__GFP_RECLAIM | __GFP_IO"},
"GFP_NOIO": {"value": "__GFP_RECLAIM"},
"GFP_NOWAIT": {"value": "__GFP_KSWAPD_RECLAIM"},
"GFP_TRANSHUGE": {"value": "GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM"},
"GFP_TRANSHUGE_LIGHT": {
"value": "GFP_HIGHUSER_MOVABLE | __GFP_COMP | __GFP_NOMEMALLOC | __GFP_NOWARN & ~__GFP_RECLAIM"
},
"GFP_USER": {"value": "__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL"},
#
#
# Modifier, mobility and placement hints:
"__GFP_ACCOUNT": {"value": "___GFP_ACCOUNT"},
"__GFP_ATOMIC": {"value": "___GFP_ATOMIC"},
"__GFP_COMP": {"value": "___GFP_COMP"},
"__GFP_DIRECT_RECLAIM": {"value": "___GFP_DIRECT_RECLAIM"},
"__GFP_DMA": {"value": "___GFP_DMA"},
"__GFP_DMA32": {"value": "___GFP_DMA32"},
"__GFP_FS": {"value": "___GFP_FS"},
"__GFP_HARDWALL": {"value": "___GFP_HARDWALL"},
"__GFP_HIGH": {"value": "___GFP_HIGH"},
"__GFP_HIGHMEM": {"value": "___GFP_HIGHMEM"},
"__GFP_IO": {"value": "___GFP_IO"},
"__GFP_KSWAPD_RECLAIM": {"value": "___GFP_KSWAPD_RECLAIM"},
"__GFP_MEMALLOC": {"value": "___GFP_MEMALLOC"},
"__GFP_MOVABLE": {"value": "___GFP_MOVABLE"},
"__GFP_NOFAIL": {"value": "___GFP_NOFAIL"},
"__GFP_NOLOCKDEP": {"value": "___GFP_NOLOCKDEP"},
"__GFP_NOMEMALLOC": {"value": "___GFP_NOMEMALLOC"},
"__GFP_NORETRY": {"value": "___GFP_NORETRY"},
"__GFP_NOWARN": {"value": "___GFP_NOWARN"},
"__GFP_RECLAIM": {"value": "___GFP_DIRECT_RECLAIM | ___GFP_KSWAPD_RECLAIM"},
"__GFP_RECLAIMABLE": {"value": "___GFP_RECLAIMABLE"},
"__GFP_RETRY_MAYFAIL": {"value": "___GFP_RETRY_MAYFAIL"},
"__GFP_SKIP_KASAN_POISON": {"value": "___GFP_SKIP_KASAN_POISON"},
"__GFP_SKIP_KASAN_UNPOISON": {"value": "___GFP_SKIP_KASAN_UNPOISON"},
"__GFP_SKIP_ZERO": {"value": "___GFP_SKIP_ZERO"},
"__GFP_WRITE": {"value": "___GFP_WRITE"},
"__GFP_ZERO": {"value": "___GFP_ZERO"},
"__GFP_ZEROTAGS": {"value": "___GFP_ZEROTAGS"},
#
#
# Plain integer GFP bitmasks (for internal use only):
"___GFP_DMA": {"value": 0x01},
"___GFP_HIGHMEM": {"value": 0x02},
"___GFP_DMA32": {"value": 0x04},
"___GFP_MOVABLE": {"value": 0x08},
"___GFP_RECLAIMABLE": {"value": 0x10},
"___GFP_HIGH": {"value": 0x20},
"___GFP_IO": {"value": 0x40},
"___GFP_FS": {"value": 0x80},
"___GFP_ZERO": {"value": 0x100},
"___GFP_ATOMIC": {"value": 0x200},
"___GFP_DIRECT_RECLAIM": {"value": 0x400},
"___GFP_KSWAPD_RECLAIM": {"value": 0x800},
"___GFP_WRITE": {"value": 0x1000},
"___GFP_NOWARN": {"value": 0x2000},
"___GFP_RETRY_MAYFAIL": {"value": 0x4000},
"___GFP_NOFAIL": {"value": 0x8000},
"___GFP_NORETRY": {"value": 0x10000},
"___GFP_MEMALLOC": {"value": 0x20000},
"___GFP_COMP": {"value": 0x40000},
"___GFP_NOMEMALLOC": {"value": 0x80000},
"___GFP_HARDWALL": {"value": 0x100000},
"___GFP_ACCOUNT": {"value": 0x400000},
"___GFP_ZEROTAGS": {"value": 0x800000},
"___GFP_SKIP_ZERO": {"value": 0x1000000},
"___GFP_SKIP_KASAN_UNPOISON": {"value": 0x2000000},
"___GFP_SKIP_KASAN_POISON": {"value": 0x4000000},
"___GFP_NOLOCKDEP": {"value": 0x8000000},
}
EXTRACT_PATTERN_OVERLAY_60 = {
"Swap usage information": (
r"^(?P<swap_cache_pages>\d+) pages in swap cache"
r"(?:\n)"
r"^Free swap = (?P<swap_free_kb>\d+)kB"
r"(?:\n)"
r"^Total swap = (?P<swap_total_kb>\d+)kB",
False,
),
}
def __init__(self):
super().__init__()
self.EXTRACT_PATTERN.update(self.EXTRACT_PATTERN_OVERLAY_60)
class KernelConfig_6_1(KernelConfig_6_0):
# Supported changes:
# * "mm: add NR_SECONDARY_PAGETABLE to count secondary page table uses." (ebc97a52b5d6)
name = "Configuration for Linux kernel 6.1 or later"
release = (6, 1, "")
EXTRACT_PATTERN_OVERLAY_61 = {
"Overall Mem-Info (part 2)": (
r"^ slab_reclaimable:(?P<slab_reclaimable_pages>\d+) slab_unreclaimable:(?P<slab_unreclaimable_pages>\d+)"
r"(?:\n)"
r"^ mapped:(?P<mapped_pages>\d+) shmem:(?P<shmem_pages>\d+) pagetables:(?P<pagetables_pages>\d+)"
r"(?:\n)"
r"^ sec_pagetables:(?P<sec_pagetables>\d+) bounce:(?P<bounce_pages>\d+)"
r"(?:\n)"
r"^ kernel_misc_reclaimable:(?P<kernel_misc_reclaimable>\d+)"
r"(?:\n)"
r"^ free:(?P<free_pages>\d+) free_pcp:(?P<free_pcp_pages>\d+) free_cma:(?P<free_cma_pages>\d+)",
True,
),
}
def __init__(self):
super().__init__()
self.EXTRACT_PATTERN.update(self.EXTRACT_PATTERN_OVERLAY_61)
AllKernelConfigs = [
KernelConfig_6_1(),
KernelConfig_6_0(),
KernelConfig_5_18(),
KernelConfig_5_16(),
KernelConfig_5_14(),
KernelConfig_5_8(),
KernelConfig_5_1(),
@ -2703,7 +2527,7 @@ class OOMEntity:
@see: _rsyslog_unescape_lf()
"""
pattern = r"^\s+ (active_file|unevictable|slab_reclaimable|mapped|sec_pagetables|kernel_misc_reclaimable|free):.+$"
pattern = r"^\s+ (active_file|unevictable|slab_reclaimable|mapped|free):.+$"
rec = re.compile(pattern)
add_cols = ""
@ -2840,18 +2664,12 @@ class OOMEntity:
return stripped_lines
def goto_previous_line(self):
"""Set line pointer to previous line
If using in front of an iterator:
The line pointer in self.current_line points to the first line of a block.
An iterator based loop starts with a next() call (as defined by the iterator
protocol). This causes the current line to be skipped. Therefore, the line
pointer is set to the previous line.
"""
if self.current_line > 0:
self.current_line -= 1
return
def back(self):
"""Return the previous line"""
if self.current_line - 1 < 0:
raise StopIteration()
self.current_line -= 1
return self.lines[self.current_line]
def current(self):
"""Return the current line"""
@ -2980,24 +2798,23 @@ class OOMAnalyser:
)
"""RE to match the OOM line with kernel version"""
REC_SPLIT_KVERSION = re.compile(
r"(?P<kernel_version>"
r"(?P<major>\d+)\.(?P<minor>\d+)" # major . minor
r"(\.\d+)?" # optional: patch level
r"(-[\w.-]+)?" # optional: -rc6, -arch-1, -19-generic
r")"
REC_FREE_MEMORY_CHUNKS = re.compile(
"Node (?P<node>\d+) (?P<zone>DMA|DMA32|Normal): (?P<zone_usage>.*) = (?P<total_free_kb_per_node>\d+)kB"
)
"""
RE for splitting the kernel version into parts
"""RE to extract free memory chunks of a memor zone"""
Examples:
- 5.19-rc6
- 4.14.288
- 5.18.6-arch1-1
- 5.13.0-19-generic #19-Ubuntu
- 5.13.0-1028-aws #31~20.04.1-Ubuntu
- 3.10.0-514.6.1.el7.x86_64 #1
"""
REC_PAGE_SIZE = re.compile("Node 0 DMA: \d+\*(?P<page_size>\d+)kB")
"""RE to extract the page size from buddyinfo DMA zone"""
REC_WATERMARK = re.compile(
"Node (?P<node>\d+) (?P<zone>DMA|DMA32|Normal) "
"free:(?P<free>\d+)kB "
"min:(?P<min>\d+)kB "
"low:(?P<low>\d+)kB "
"high:(?P<high>\d+)kB "
".*"
)
"""RE to extract watermark information in a memory zone"""
def __init__(self, oom):
self.oom_entity = oom
@ -3016,6 +2833,25 @@ class OOMAnalyser:
self.oom_result.kversion = match.group("kernel_version")
return True
rec_split_kversion = re.compile(
r"(?P<kernel_version>"
r"(?P<major>\d+)\.(?P<minor>\d+)" # major . minor
r"(\.\d+)?" # optional: patch level
r"(-[\w.-]+)?" # optional: -rc6, -arch-1, -19-generic
r")"
)
"""
RE for splitting the kernel version into parts
Examples:
- 5.19-rc6
- 4.14.288
- 5.18.6-arch1-1
- 5.13.0-19-generic #19-Ubuntu
- 5.13.0-1028-aws #31~20.04.1-Ubuntu
- 3.10.0-514.6.1.el7.x86_64 #1
"""
def _check_kversion_greater_equal(self, kversion, min_version):
"""
Returns True if the kernel version is greater or equal to the minimum version
@ -3024,7 +2860,7 @@ class OOMAnalyser:
@param (int, int, str) min_version: Minimum version
@rtype: bool
"""
match = self.REC_SPLIT_KVERSION.match(kversion)
match = self.rec_split_kversion.match(kversion)
if not match:
self.oom_result.error_msg = (
@ -3093,12 +2929,12 @@ class OOMAnalyser:
self.oom_state = OOMEntityState.unknown
self.oom_result.error_msg = "Unknown OOM format"
if not self.oom_result.kconfig.REC_OOM_BEGIN.search(self.oom_entity.text):
if not self.oom_result.kconfig.rec_oom_begin.search(self.oom_entity.text):
self.state = OOMEntityState.invalid
self.oom_result.error_msg = "The inserted text is not a valid OOM block! The initial pattern was not found!"
return False
if not self.oom_result.kconfig.REC_OOM_END.search(self.oom_entity.text):
if not self.oom_result.kconfig.rec_oom_end.search(self.oom_entity.text):
self.state = OOMEntityState.started
self.oom_result.error_msg = (
"The inserted OOM is incomplete! The initial pattern was found but not the "
@ -3123,7 +2959,7 @@ class OOMAnalyser:
block += "{}\n".format(line)
for line in self.oom_entity:
if ":" in line:
self.oom_entity.goto_previous_line()
self.oom_entity.back()
break
block += "{}\n".format(line)
return block
@ -3197,7 +3033,7 @@ class OOMAnalyser:
def _extract_page_size(self):
"""Extract page size from buddyinfo DMZ zone"""
match = self.oom_result.kconfig.REC_PAGE_SIZE.search(self.oom_entity.text)
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
@ -3237,9 +3073,14 @@ class OOMAnalyser:
buddy_info = self.oom_result.buddyinfo
self.oom_entity.find_text(self.oom_result.kconfig.zoneinfo_start)
self.oom_entity.goto_previous_line()
# Currently omm_entity point to the first line of the buddyinfo.
# The iterator protocol uses the next() call. However, this will cause the
# current line to be skipped.
# Therefore, we reset the counter by one line.
self.oom_entity.back()
for line in self.oom_entity:
match = self.oom_result.kconfig.REC_FREE_MEMORY_CHUNKS.match(line)
match = self.REC_FREE_MEMORY_CHUNKS.match(line)
if not match:
continue
node = int(match.group("node"))
@ -3294,11 +3135,16 @@ class OOMAnalyser:
watermark_info = self.oom_result.watermarks
self.oom_entity.find_text(self.oom_result.kconfig.watermark_start)
# Currently omm_entity point to the first line of the watermark information.
# The iterator protocol uses the next() call. However, this will cause the
# current line to be skipped.
# Therefore, we reset the counter by one line.
self.oom_entity.back()
node = None
zone = None
self.oom_entity.goto_previous_line()
for line in self.oom_entity:
match = self.oom_result.kconfig.REC_WATERMARK.match(line)
match = self.REC_WATERMARK.match(line)
if not match:
if line.startswith("lowmem_reserve[]:"):
# zone and node are defined in the previous round
@ -3505,7 +3351,7 @@ class OOMAnalyser:
)
return
# Node with memory shortage: watermark "free" < "min"
# Search node with memory shortage: watermark "free" < "min"
node = self.oom_result.details["trigger_proc_numa_node"]
if node is None:
return
@ -3601,8 +3447,11 @@ class OOMAnalyser:
def _calc_swap_values(self):
"""Calculate all swap related values"""
if "swap_total_kb" in self.oom_result.details:
try:
self.oom_result.swap_active = self.oom_result.details["swap_total_kb"] > 0
except KeyError:
self.oom_result.swap_active = False
if not self.oom_result.swap_active:
return
@ -4607,8 +4456,6 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
show_elements(".js-memory-heavy-fragmentation--show")
else:
show_elements(".js-memory-no-heavy-fragmentation--show")
if self.oom_result.details["trigger_proc_numa_node"] is None:
hide_elements(".js-memory-shortage-node--hide")
def _show_page_size(self):
"""Show page size"""

View File

@ -37,8 +37,8 @@ class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
class TestBase(unittest.TestCase):
text_alloc_failed_below_low_watermark = (
"The request failed because the free memory would be below the memory low "
"watermark after its completion."
"The request failed because after its fulfillment the free memory would "
"be below the memory low watermark."
)
text_alloc_failed_no_free_chunks = (
"The request failed because there is no free chunk in the current or "
@ -776,7 +776,7 @@ Hardware name: HP ProLiant DL385 G7, BIOS A18 12/08/2012
"CPU: 4 PID: 29481 Comm: sed Not tainted 5.23.0 #1",
),
(
OOMAnalyser.KernelConfig_6_1(),
OOMAnalyser.KernelConfig_5_18(),
"CPU: 4 PID: 29481 Comm: sed Not tainted 6.12.0 #1",
),
(