Fix for the "kmem -i" option on Linux 5.0 and later kernels that
contain commit ca79b0c211af63fa3276f0e3fd7dd9ada2439839, titled
"mm: convert totalram_pages and totalhigh_pages variables to atomic".
Without the patch, the command prints some incorrect values, and
besides doesn't print high/low memory information on kernels which
are configured with CONFIG_HIGHMEM.

crash> kmem -i
                 PAGES        TOTAL      PERCENTAGE
    TOTAL MEM  -4395174638254716088  53602483503169.4 GB         ----
         FREE   398314       1.5 GB    0% of TOTAL MEM
         USED  -4395174638255114402  53602483503167.9 GB    0% of TOTAL MEM
...

Tested with 5.0 and 4.20 Fedora kernels for x86_64 and x86.

Signed-off-by: Kazuhito Hagio <[email protected]>
---
 memory.c | 75 +++++++++++++++++++++++++++-----------------------------
 1 file changed, 36 insertions(+), 39 deletions(-)

diff --git a/memory.c b/memory.c
index 9c1019a..ab561b3 100644
--- a/memory.c
+++ b/memory.c
@@ -910,26 +910,40 @@ vm_init(void)
        if (IS_VMALLOC_ADDR(vt->mem_map))
                vt->flags |= V_MEM_MAP;
        vt->total_pages = BTOP(VTOP(vt->high_memory));
-       switch (get_syment_array("totalram_pages", sp_array, 2)) 
-       {
-       case 1:
-               get_symbol_data("totalram_pages", sizeof(ulong), 
-                       &vt->totalram_pages);
-               break;
-       case 2:
-               if (!(readmem(sp_array[0]->value, KVADDR, 
-                   &value1, sizeof(ulong), 
-                   "totalram_pages #1", RETURN_ON_ERROR)))
+
+       if (symbol_exists("_totalram_pages")) {
+               readmem(symbol_value("_totalram_pages") +
+                       OFFSET(atomic_t_counter), KVADDR,
+                       &vt->totalram_pages, sizeof(ulong),
+                       "_totalram_pages", FAULT_ON_ERROR);
+       } else {
+               switch (get_syment_array("totalram_pages", sp_array, 2))
+               {
+               case 1:
+                       get_symbol_data("totalram_pages", sizeof(ulong),
+                               &vt->totalram_pages);
                        break;
-                if (!(readmem(sp_array[1]->value, KVADDR,
-                    &value2, sizeof(ulong), 
-                   "totalram_pages #2", RETURN_ON_ERROR)))
-                        break;
-               vt->totalram_pages = MAX(value1, value2);
-               break;
+               case 2:
+                       if (!(readmem(sp_array[0]->value, KVADDR,
+                           &value1, sizeof(ulong),
+                           "totalram_pages #1", RETURN_ON_ERROR)))
+                               break;
+                       if (!(readmem(sp_array[1]->value, KVADDR,
+                           &value2, sizeof(ulong),
+                           "totalram_pages #2", RETURN_ON_ERROR)))
+                               break;
+                       vt->totalram_pages = MAX(value1, value2);
+                       break;
+               }
        }
 
-       if (symbol_exists("totalhigh_pages")) {
+       if (symbol_exists("_totalhigh_pages")) {
+               readmem(symbol_value("_totalhigh_pages") +
+                       OFFSET(atomic_t_counter), KVADDR,
+                       &vt->totalhigh_pages, sizeof(ulong),
+                       "_totalhigh_pages", FAULT_ON_ERROR);
+               vt->total_pages += vt->totalhigh_pages;
+       } else if (symbol_exists("totalhigh_pages")) {
                switch (get_syment_array("totalhigh_pages", sp_array, 2))
                {
                case 1:
@@ -8169,7 +8183,6 @@ dump_kmeminfo(void)
        long nr_file_pages, nr_slab;
        ulong swapper_space_nrpages;
        ulong pct;
-       ulong value1, value2;
        uint tmp;
        struct meminfo meminfo;
        struct gnu_request req;
@@ -8177,7 +8190,6 @@ dump_kmeminfo(void)
         ulong get_totalram;
         ulong get_buffers;
         ulong get_slabs;
-        struct syment *sp_array[2];
        char buf[BUFSIZE];
 
 
@@ -8210,7 +8222,8 @@ dump_kmeminfo(void)
          *    Prior to 2.3.36, count all mem_map pages minus the reserved ones.
          *    From 2.3.36 onwards, use "totalram_pages" if set.
         */
-       if (symbol_exists("totalram_pages")) {  
+       if (symbol_exists("totalram_pages") ||
+           symbol_exists("_totalram_pages")) {
                totalram_pages = vt->totalram_pages ? 
                        vt->totalram_pages : get_totalram; 
        } else 
@@ -8362,25 +8375,9 @@ dump_kmeminfo(void)
        fprintf(fp, "%13s  %7ld  %11s  %3ld%% of TOTAL MEM\n",
                "SLAB", get_slabs, pages_to_size(get_slabs, buf), pct);
 
-        if (symbol_exists("totalhigh_pages")) {
-               switch (get_syment_array("totalhigh_pages", sp_array, 2))
-               {
-               case 1:
-                       get_symbol_data("totalhigh_pages", sizeof(ulong),
-                               &totalhigh_pages);
-                       break;
-               case 2:
-                       if (!(readmem(sp_array[0]->value, KVADDR,
-                           &value1, sizeof(ulong),
-                           "totalhigh_pages #1", RETURN_ON_ERROR)))
-                               break;
-                       if (!(readmem(sp_array[1]->value, KVADDR,
-                           &value2, sizeof(ulong),
-                           "totalhigh_pages #2", RETURN_ON_ERROR)))
-                               break;
-                       totalhigh_pages = MAX(value1, value2);
-                       break;
-               }
+       if (symbol_exists("totalhigh_pages") ||
+           symbol_exists("_totalhigh_pages")) {
+               totalhigh_pages = vt->totalhigh_pages;
 
                pct = totalhigh_pages ?
                        (totalhigh_pages * 100)/totalram_pages : 0;
-- 
2.17.0

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to