From 79d39b0a11892cf0321224cb8c12034f3c6c0bc7 Mon Sep 17 00:00:00 2001
From: Patrick Daly <pdaly@codeaurora.org>
Date: Tue, 28 Mar 2017 14:56:24 -0700
Subject: [PATCH] lrdpv2: pagetracking: Add support for order > 0 pages

The stack trace saved by PAGE_OWNER is only set for the first pfn in a page
even if it has order > 0. Previously, invalid stack traces were printed out
for "tail pages".

Change-Id: I65162c7d4220348759525871f0c1d708098ffc2d
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
---
 linux-ramdump-parser-v2/mm.py                   | 15 +++++++++++++++
 linux-ramdump-parser-v2/parsers/pagetracking.py | 15 +++++++++++----
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/linux-ramdump-parser-v2/mm.py b/linux-ramdump-parser-v2/mm.py
index 4ac9c68..538af9c 100644
--- a/linux-ramdump-parser-v2/mm.py
+++ b/linux-ramdump-parser-v2/mm.py
@@ -19,6 +19,21 @@ def page_buddy(ramdump, page):
     return val == 0xffffff80
 
 
+def page_count(ramdump, page):
+    """Commit: 0139aa7b7fa12ceef095d99dc36606a5b10ab83a
+    mm: rename _count, field of the struct page, to _refcount"""
+    if (ramdump.version < (4, 6, 0)):
+        count = ramdump.read_structure_field(page, 'struct page',
+                                             '_count.counter')
+    else:
+        count = ramdump.read_structure_field(page, 'struct page',
+                                             '_refcount.counter')
+    return count
+
+
+def page_ref_count(ramdump, page):
+    return page_count(ramdump, page)
+
 def get_debug_flags(ramdump, page):
     debug_flag_offset = ramdump.field_offset('struct page', 'debug_flags')
     flagval = ramdump.read_word(page + debug_flag_offset)
diff --git a/linux-ramdump-parser-v2/parsers/pagetracking.py b/linux-ramdump-parser-v2/parsers/pagetracking.py
index e7ec446..1d37141 100644
--- a/linux-ramdump-parser-v2/parsers/pagetracking.py
+++ b/linux-ramdump-parser-v2/parsers/pagetracking.py
@@ -11,7 +11,7 @@
 
 from print_out import print_out_str
 from parser_util import register_parser, RamParser
-from mm import pfn_to_page, page_buddy
+from mm import pfn_to_page, page_buddy, page_count
 
 
 @register_parser('--print-pagetracking', 'print page tracking information (if available)')
@@ -63,14 +63,18 @@ class PageTracking(RamParser):
 
         for pfn in range(min_pfn, max_pfn):
             page = pfn_to_page(self.ramdump, pfn)
+            order = 0
 
-            # validate this page is free
-            if page_buddy(self.ramdump, page):
+            """must be allocated, and the first pfn of an order > 0 page"""
+            if (page_buddy(self.ramdump, page) or
+                    page_count(self.ramdump, page) == 0):
                 continue
             if (self.ramdump.kernel_version <= (3, 19, 0)):
                 nr_trace_entries = self.ramdump.read_int(
                     page + trace_offset + nr_entries_offset)
                 struct_holding_trace_entries = page
+                order = self.ramdump.read_structure_field(
+                            page, 'struct page', 'order')
             else:
                 phys = pfn << 12
                 if phys is None or phys is 0:
@@ -85,11 +89,14 @@ class PageTracking(RamParser):
                 nr_trace_entries = self.ramdump.read_int(
                                     temp_page_ext + nr_entries_offset)
                 struct_holding_trace_entries = temp_page_ext
+                order = self.ramdump.read_structure_field(
+                            temp_page_ext, 'struct page_ext', 'order')
 
             if nr_trace_entries <= 0 or nr_trace_entries > 16:
                 continue
 
-            out_tracking.write('PFN 0x{0:x} page 0x{1:x} \n'.format(pfn, page))
+            out_tracking.write('PFN 0x{:x}-0x{:x} page 0x{:x}\n'.format(
+                pfn, pfn + (1 << order) - 1, page))
 
             alloc_str = ''
             for i in range(0, nr_trace_entries):
-- 
GitLab