* [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
@ 2025-04-23 1:48 Ye Liu
2025-04-23 9:45 ` Florian Weimer
2025-04-23 22:00 ` SeongJae Park
0 siblings, 2 replies; 9+ messages in thread
From: Ye Liu @ 2025-04-23 1:48 UTC (permalink / raw)
To: akpm
Cc: linux-debuggers, linux-kernel, linux-mm, linux-toolchains,
osandov, paulmck, sweettea-kernel, liuye, ye.liu
From: Ye Liu <liuye@kylinos.cn>
Introduces a new drgn script, `show_page_info.py`, which allows users
to analyze the state of a page given a process ID (PID) and a virtual
address (VADDR). This can help kernel developers or debuggers easily
inspect page-related information in a live kernel or vmcore.
The script extracts information such as the page flags, mapping, and
other metadata relevant to diagnosing memory issues.
Output example:
sudo ./show_page_info.py 1 0x7f43df5acf00
PID: 1 Comm: systemd mm: 0xffff8881273bbc40
Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
User Virtual Address: 0x7f43df5acf00
Page Address: 0xffffea00049a0b00
Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
PG_private|PG_reported
Page Size: 16384
Page PFN: 0x12682c
Page Physical: 0x12682c000
Page Virtual: 0xffff88812682c000
Page Refcount: 37
Page Mapcount: 7
Page Index: 0x0
Page Memcg Data: 0xffff88812642c000
Memcg Name: init.scope
Memcg Path: /sys/fs/cgroup/memory/init.scope
Page Mapping: 0xffff88810f086a70
Page Anon/File: File
Page VMA: 0xffff88810e4af3b8
VMA Start: 0x7f43df5ac000
VMA End: 0x7f43df5b0000
This page is part of a compound page.
This page is the head page of a compound page.
Head Page: 0xffffea00049a0b00
Compound Order: 2
Number of Pages: 4
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Changes in v3:
- Adjust display style.
- Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/
Changes in v2:
- Move the show_page_info.py file to tools/mm.
- Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/
---
MAINTAINERS | 5 ++
tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++
2 files changed, 125 insertions(+)
create mode 100755 tools/mm/show_page_info.py
diff --git a/MAINTAINERS b/MAINTAINERS
index 17ed0b5ffdd2..85686a30dc72 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst
F: include/linux/page_table_check.h
F: mm/page_table_check.c
+PAGE STATE DEBUG SCRIPT
+M: Ye Liu <liuye@kylinos.cn>
+S: Maintained
+F: tools/mm/show_page_info.py
+
PANASONIC LAPTOP ACPI EXTRAS DRIVER
M: Kenneth Chan <kenneth.t.chan@gmail.com>
L: platform-driver-x86@vger.kernel.org
diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py
new file mode 100755
index 000000000000..8622c5499dfe
--- /dev/null
+++ b/tools/mm/show_page_info.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env drgn
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright (C) 2025 Ye Liu <liuye@kylinos.cn>
+
+import argparse
+from drgn import Object
+from drgn.helpers.linux import find_task, follow_page, page_size
+from drgn.helpers.linux.mm import (
+ decode_page_flags, page_to_pfn, page_to_phys, page_to_virt, vma_find,
+ PageSlab, PageCompound, PageHead, PageTail, compound_head, compound_order, compound_nr
+)
+from drgn.helpers.linux.cgroup import cgroup_name, cgroup_path
+
+DESC = """
+This is a drgn script to show the page state.
+For more info on drgn, visit https://github.com/osandov/drgn.
+"""
+
+MEMCG_DATA_OBJEXTS = 1 << 0
+MEMCG_DATA_KMEM = 1 << 1
+__NR_MEMCG_DATA_FLAGS = 1 << 2
+
+def format_page_data(data):
+ """Format raw page data into a readable hex dump."""
+ chunks = [data[i:i+8] for i in range(0, len(data), 8)]
+ hex_chunks = ["".join(f"{b:02x}" for b in chunk[::-1]) for chunk in chunks]
+ lines = [" ".join(hex_chunks[i:i+4]) for i in range(0, len(hex_chunks), 4)]
+ return "\n".join(f"Raw: {line}" for line in lines)
+
+def get_memcg_info(page):
+ """Retrieve memory cgroup information for a page."""
+ memcg_data = page.memcg_data.value_()
+ if memcg_data & MEMCG_DATA_OBJEXTS:
+ memcg_value = 0
+ elif memcg_data & MEMCG_DATA_KMEM:
+ objcg = Object(prog, "struct obj_cgroup *", address=memcg_data & ~__NR_MEMCG_DATA_FLAGS)
+ memcg_value = objcg.memcg.value_()
+ else:
+ memcg_value = memcg_data & ~__NR_MEMCG_DATA_FLAGS
+
+ memcg = Object(prog, "struct mem_cgroup *", address=memcg_value)
+ cgrp = memcg.css.cgroup
+ return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}"
+
+def show_page_state(page, addr, mm, pid, task):
+ """Display detailed information about a page."""
+ print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}')
+ print(format_page_data(prog.read(page.value_(), 64)))
+ fields = {
+ "User Virtual Address": hex(addr),
+ "Page Address": hex(page.value_()),
+ "Page Flags": decode_page_flags(page),
+ "Page Size": page_size(page).value_(),
+ "Page PFN": hex(page_to_pfn(page).value_()),
+ "Page Physical": hex(page_to_phys(page).value_()),
+ "Page Virtual": hex(page_to_virt(page).value_()),
+ "Page Refcount": page._refcount.counter.value_(),
+ "Page Mapcount": page._mapcount.counter.value_(),
+ "Page Index": hex(page.index.value_()),
+ "Page Memcg Data": hex(page.memcg_data.value_()),
+ }
+
+ memcg_name, memcg_path = get_memcg_info(page)
+ fields["Memcg Name"] = memcg_name
+ fields["Memcg Path"] = memcg_path
+ fields["Page Mapping"] = hex(page.mapping.value_())
+ fields["Page Anon/File"] = "Anon" if page.mapping.value_() & 0x1 else "File"
+
+ vma = vma_find(mm, addr)
+ fields["Page VMA"] = hex(vma.value_())
+ fields["VMA Start"] = hex(vma.vm_start.value_())
+ fields["VMA End"] = hex(vma.vm_end.value_())
+
+ # Calculate the maximum field name length for alignment
+ max_field_len = max(len(field) for field in fields)
+
+ # Print aligned fields
+ for field, value in fields.items():
+ print(f"{field}:".ljust(max_field_len + 2) + f"{value}")
+
+ # Additional information about the page
+ if PageSlab(page):
+ print("This page belongs to the slab allocator.")
+
+ if PageCompound(page):
+ print("This page is part of a compound page.")
+ if PageHead(page):
+ print("This page is the head page of a compound page.")
+ if PageTail(page):
+ print("This page is the tail page of a compound page.")
+ print(f"{'Head Page:'.ljust(max_field_len + 2)}{hex(compound_head(page).value_())}")
+ print(f"{'Compound Order:'.ljust(max_field_len + 2)}{compound_order(page).value_()}")
+ print(f"{'Number of Pages:'.ljust(max_field_len + 2)}{compound_nr(page).value_()}")
+ else:
+ print("This page is not part of a compound page.")
+
+def main():
+ """Main function to parse arguments and display page state."""
+ parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter)
+ parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)')
+ parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)')
+ args = parser.parse_args()
+
+ try:
+ vaddr = int(args.vaddr, 16)
+ except ValueError:
+ print(f"Error: Invalid virtual address format: {args.vaddr}")
+ return
+
+ task = find_task(args.pid)
+ mm = task.mm
+ page = follow_page(mm, vaddr)
+
+ if page:
+ show_page_state(page, vaddr, mm, args.pid, task)
+ else:
+ print(f"Address {hex(vaddr)} is not mapped.")
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-23 1:48 [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR Ye Liu
@ 2025-04-23 9:45 ` Florian Weimer
2025-04-24 2:17 ` Ye Liu
2025-04-23 22:00 ` SeongJae Park
1 sibling, 1 reply; 9+ messages in thread
From: Florian Weimer @ 2025-04-23 9:45 UTC (permalink / raw)
To: Ye Liu
Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains,
osandov, paulmck, sweettea-kernel, liuye
* Ye Liu:
> From: Ye Liu <liuye@kylinos.cn>
>
> Introduces a new drgn script, `show_page_info.py`, which allows users
> to analyze the state of a page given a process ID (PID) and a virtual
> address (VADDR). This can help kernel developers or debuggers easily
> inspect page-related information in a live kernel or vmcore.
>
> The script extracts information such as the page flags, mapping, and
> other metadata relevant to diagnosing memory issues.
>
> Output example:
> sudo ./show_page_info.py 1 0x7f43df5acf00
> PID: 1 Comm: systemd mm: 0xffff8881273bbc40
> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
> User Virtual Address: 0x7f43df5acf00
> Page Address: 0xffffea00049a0b00
> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
> PG_private|PG_reported
> Page Size: 16384
> Page PFN: 0x12682c
> Page Physical: 0x12682c000
> Page Virtual: 0xffff88812682c000
> Page Refcount: 37
> Page Mapcount: 7
> Page Index: 0x0
> Page Memcg Data: 0xffff88812642c000
> Memcg Name: init.scope
> Memcg Path: /sys/fs/cgroup/memory/init.scope
> Page Mapping: 0xffff88810f086a70
> Page Anon/File: File
> Page VMA: 0xffff88810e4af3b8
> VMA Start: 0x7f43df5ac000
> VMA End: 0x7f43df5b0000
> This page is part of a compound page.
> This page is the head page of a compound page.
> Head Page: 0xffffea00049a0b00
> Compound Order: 2
> Number of Pages: 4
Does this show the page access flags anywhere in the output? If not,
would it be possible to include this information?
Thanks,
Florian
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-23 1:48 [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR Ye Liu
2025-04-23 9:45 ` Florian Weimer
@ 2025-04-23 22:00 ` SeongJae Park
2025-04-24 1:55 ` Ye Liu
1 sibling, 1 reply; 9+ messages in thread
From: SeongJae Park @ 2025-04-23 22:00 UTC (permalink / raw)
To: Ye Liu
Cc: SeongJae Park, akpm, linux-debuggers, linux-kernel, linux-mm,
linux-toolchains, osandov, paulmck, sweettea-kernel, liuye
On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote:
> From: Ye Liu <liuye@kylinos.cn>
>
> Introduces a new drgn script, `show_page_info.py`, which allows users
> to analyze the state of a page given a process ID (PID) and a virtual
> address (VADDR). This can help kernel developers or debuggers easily
> inspect page-related information in a live kernel or vmcore.
>
> The script extracts information such as the page flags, mapping, and
> other metadata relevant to diagnosing memory issues.
>
> Output example:
> sudo ./show_page_info.py 1 0x7f43df5acf00
> PID: 1 Comm: systemd mm: 0xffff8881273bbc40
> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
> User Virtual Address: 0x7f43df5acf00
> Page Address: 0xffffea00049a0b00
> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
> PG_private|PG_reported
> Page Size: 16384
Should this be called folio size? Or, could this simply removed since Compound
Order is given below?
> Page PFN: 0x12682c
> Page Physical: 0x12682c000
> Page Virtual: 0xffff88812682c000
> Page Refcount: 37
> Page Mapcount: 7
> Page Index: 0x0
> Page Memcg Data: 0xffff88812642c000
> Memcg Name: init.scope
> Memcg Path: /sys/fs/cgroup/memory/init.scope
> Page Mapping: 0xffff88810f086a70
> Page Anon/File: File
> Page VMA: 0xffff88810e4af3b8
> VMA Start: 0x7f43df5ac000
> VMA End: 0x7f43df5b0000
> This page is part of a compound page.
> This page is the head page of a compound page.
> Head Page: 0xffffea00049a0b00
> Compound Order: 2
> Number of Pages: 4
>
> Signed-off-by: Ye Liu <liuye@kylinos.cn>
>
> Changes in v3:
> - Adjust display style.
> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/
>
> Changes in v2:
> - Move the show_page_info.py file to tools/mm.
> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/
> ---
> MAINTAINERS | 5 ++
> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++
> 2 files changed, 125 insertions(+)
> create mode 100755 tools/mm/show_page_info.py
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 17ed0b5ffdd2..85686a30dc72 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst
> F: include/linux/page_table_check.h
> F: mm/page_table_check.c
>
> +PAGE STATE DEBUG SCRIPT
> +M: Ye Liu <liuye@kylinos.cn>
> +S: Maintained
> +F: tools/mm/show_page_info.py
> +
> PANASONIC LAPTOP ACPI EXTRAS DRIVER
> M: Kenneth Chan <kenneth.t.chan@gmail.com>
> L: platform-driver-x86@vger.kernel.org
> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py
> new file mode 100755
> index 000000000000..8622c5499dfe
> --- /dev/null
> +++ b/tools/mm/show_page_info.py
[...]
> +def main():
> + """Main function to parse arguments and display page state."""
> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter)
> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)')
> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)')
> + args = parser.parse_args()
> +
> + try:
> + vaddr = int(args.vaddr, 16)
> + except ValueError:
> + print(f"Error: Invalid virtual address format: {args.vaddr}")
> + return
> +
> + task = find_task(args.pid)
> + mm = task.mm
> + page = follow_page(mm, vaddr)
I tried this script on my test machine and got the below error:
$ cat ./a.c
#include <stdio.h>
int main(void)
{
int foo;
printf("hello\n");
printf("%x\n", &foo);
scanf("%d\n", &foo);
return 0;
}
$ gcc ./a.c
$ ./a.out &
[2] 45666
hello
f7eb7c0c
$ sudo ./tools/mm/show_page_info.py 45666 0xf7eb7c0c
Traceback (most recent call last):
File "/usr/local/bin/drgn", line 33, in <module>
sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main
runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__")
File "<frozen runpy>", line 291, in run_path
File "<frozen runpy>", line 98, in _run_module_code
File "<frozen runpy>", line 88, in _run_code
File "./tools/mm/show_page_info.py", line 120, in <module>
main()
File "./tools/mm/show_page_info.py", line 112, in main
page = follow_page(mm, vaddr)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1068, in follow_page
return phys_to_page(follow_phys(mm, addr))
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1109, in follow_phys
return Object(prog, "phys_addr_t", _linux_helper_follow_phys(prog, mm.pgd, addr))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_drgn.FaultError: address is not mapped: 0xf7eb7c0c
Am I doing something wrong?
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-23 22:00 ` SeongJae Park
@ 2025-04-24 1:55 ` Ye Liu
2025-04-24 2:51 ` SeongJae Park
0 siblings, 1 reply; 9+ messages in thread
From: Ye Liu @ 2025-04-24 1:55 UTC (permalink / raw)
To: SeongJae Park
Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains,
osandov, paulmck, sweettea-kernel, liuye
在 2025/4/24 06:00, SeongJae Park 写道:
> On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote:
>
>> From: Ye Liu <liuye@kylinos.cn>
>>
>> Introduces a new drgn script, `show_page_info.py`, which allows users
>> to analyze the state of a page given a process ID (PID) and a virtual
>> address (VADDR). This can help kernel developers or debuggers easily
>> inspect page-related information in a live kernel or vmcore.
>>
>> The script extracts information such as the page flags, mapping, and
>> other metadata relevant to diagnosing memory issues.
>>
>> Output example:
>> sudo ./show_page_info.py 1 0x7f43df5acf00
>> PID: 1 Comm: systemd mm: 0xffff8881273bbc40
>> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
>> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
>> User Virtual Address: 0x7f43df5acf00
>> Page Address: 0xffffea00049a0b00
>> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
>> PG_private|PG_reported
>> Page Size: 16384
> Should this be called folio size? Or, could this simply removed since Compound
> Order is given below?
Page size refers to the base page size, which equals PAGESIZE.
Folio size can be calculated using the Compound Order, but of course,
it can also be shown directly as a result.
>> Page PFN: 0x12682c
>> Page Physical: 0x12682c000
>> Page Virtual: 0xffff88812682c000
>> Page Refcount: 37
>> Page Mapcount: 7
>> Page Index: 0x0
>> Page Memcg Data: 0xffff88812642c000
>> Memcg Name: init.scope
>> Memcg Path: /sys/fs/cgroup/memory/init.scope
>> Page Mapping: 0xffff88810f086a70
>> Page Anon/File: File
>> Page VMA: 0xffff88810e4af3b8
>> VMA Start: 0x7f43df5ac000
>> VMA End: 0x7f43df5b0000
>> This page is part of a compound page.
>> This page is the head page of a compound page.
>> Head Page: 0xffffea00049a0b00
>> Compound Order: 2
>> Number of Pages: 4
>>
>> Signed-off-by: Ye Liu <liuye@kylinos.cn>
>>
>> Changes in v3:
>> - Adjust display style.
>> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/
>>
>> Changes in v2:
>> - Move the show_page_info.py file to tools/mm.
>> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/
>> ---
>> MAINTAINERS | 5 ++
>> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++
>> 2 files changed, 125 insertions(+)
>> create mode 100755 tools/mm/show_page_info.py
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 17ed0b5ffdd2..85686a30dc72 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst
>> F: include/linux/page_table_check.h
>> F: mm/page_table_check.c
>>
>> +PAGE STATE DEBUG SCRIPT
>> +M: Ye Liu <liuye@kylinos.cn>
>> +S: Maintained
>> +F: tools/mm/show_page_info.py
>> +
>> PANASONIC LAPTOP ACPI EXTRAS DRIVER
>> M: Kenneth Chan <kenneth.t.chan@gmail.com>
>> L: platform-driver-x86@vger.kernel.org
>> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py
>> new file mode 100755
>> index 000000000000..8622c5499dfe
>> --- /dev/null
>> +++ b/tools/mm/show_page_info.py
> [...]
>> +def main():
>> + """Main function to parse arguments and display page state."""
>> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter)
>> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)')
>> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)')
>> + args = parser.parse_args()
>> +
>> + try:
>> + vaddr = int(args.vaddr, 16)
>> + except ValueError:
>> + print(f"Error: Invalid virtual address format: {args.vaddr}")
>> + return
>> +
>> + task = find_task(args.pid)
>> + mm = task.mm
>> + page = follow_page(mm, vaddr)
> I tried this script on my test machine and got the below error:
>
> $ cat ./a.c
> #include <stdio.h>
>
> int main(void)
> {
> int foo;
> printf("hello\n");
> printf("%x\n", &foo);
To avoid address truncation, you can use the %p format specifier
instead of %x or %lx when printing a pointer (memory address).
Thanks,
Ye Liu
> scanf("%d\n", &foo);
> return 0;
> }
> $ gcc ./a.c
> $ ./a.out &
> [2] 45666
> hello
> f7eb7c0c
>
> $ sudo ./tools/mm/show_page_info.py 45666 0xf7eb7c0c
> Traceback (most recent call last):
> File "/usr/local/bin/drgn", line 33, in <module>
> sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')())
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main
> runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__")
> File "<frozen runpy>", line 291, in run_path
> File "<frozen runpy>", line 98, in _run_module_code
> File "<frozen runpy>", line 88, in _run_code
> File "./tools/mm/show_page_info.py", line 120, in <module>
> main()
> File "./tools/mm/show_page_info.py", line 112, in main
> page = follow_page(mm, vaddr)
> ^^^^^^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1068, in follow_page
> return phys_to_page(follow_phys(mm, addr))
> ^^^^^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1109, in follow_phys
> return Object(prog, "phys_addr_t", _linux_helper_follow_phys(prog, mm.pgd, addr))
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> _drgn.FaultError: address is not mapped: 0xf7eb7c0c
>
> Am I doing something wrong?
>
>
> Thanks,
> SJ
>
> [...]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-23 9:45 ` Florian Weimer
@ 2025-04-24 2:17 ` Ye Liu
0 siblings, 0 replies; 9+ messages in thread
From: Ye Liu @ 2025-04-24 2:17 UTC (permalink / raw)
To: Florian Weimer
Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains,
osandov, paulmck, sweettea-kernel, liuye
在 2025/4/23 17:45, Florian Weimer 写道:
> * Ye Liu:
>
>> From: Ye Liu <liuye@kylinos.cn>
>>
>> Introduces a new drgn script, `show_page_info.py`, which allows users
>> to analyze the state of a page given a process ID (PID) and a virtual
>> address (VADDR). This can help kernel developers or debuggers easily
>> inspect page-related information in a live kernel or vmcore.
>>
>> The script extracts information such as the page flags, mapping, and
>> other metadata relevant to diagnosing memory issues.
>>
>> Output example:
>> sudo ./show_page_info.py 1 0x7f43df5acf00
>> PID: 1 Comm: systemd mm: 0xffff8881273bbc40
>> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
>> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
>> User Virtual Address: 0x7f43df5acf00
>> Page Address: 0xffffea00049a0b00
>> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
>> PG_private|PG_reported
>> Page Size: 16384
>> Page PFN: 0x12682c
>> Page Physical: 0x12682c000
>> Page Virtual: 0xffff88812682c000
>> Page Refcount: 37
>> Page Mapcount: 7
>> Page Index: 0x0
>> Page Memcg Data: 0xffff88812642c000
>> Memcg Name: init.scope
>> Memcg Path: /sys/fs/cgroup/memory/init.scope
>> Page Mapping: 0xffff88810f086a70
>> Page Anon/File: File
>> Page VMA: 0xffff88810e4af3b8
>> VMA Start: 0x7f43df5ac000
>> VMA End: 0x7f43df5b0000
>> This page is part of a compound page.
>> This page is the head page of a compound page.
>> Head Page: 0xffffea00049a0b00
>> Compound Order: 2
>> Number of Pages: 4
> Does this show the page access flags anywhere in the output? If not,
> would it be possible to include this information?
This script is currently a basic version, and we plan to gradually add
more detailed information about pages, including the page access flags
you mentioned, as well as PGD, PUD, PMD, PTE, file/anon rmap folios,
and more. This will be refined over time.
Thanks,
Ye Liu
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-24 1:55 ` Ye Liu
@ 2025-04-24 2:51 ` SeongJae Park
2025-04-24 3:24 ` Ye Liu
2025-04-24 3:27 ` Ye Liu
0 siblings, 2 replies; 9+ messages in thread
From: SeongJae Park @ 2025-04-24 2:51 UTC (permalink / raw)
To: Ye Liu
Cc: SeongJae Park, akpm, linux-debuggers, linux-kernel, linux-mm,
linux-toolchains, osandov, paulmck, sweettea-kernel, liuye
On Thu, 24 Apr 2025 09:55:22 +0800 Ye Liu <ye.liu@linux.dev> wrote:
>
> 在 2025/4/24 06:00, SeongJae Park 写道:
> > On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote:
> >
> >> From: Ye Liu <liuye@kylinos.cn>
> >>
> >> Introduces a new drgn script, `show_page_info.py`, which allows users
> >> to analyze the state of a page given a process ID (PID) and a virtual
> >> address (VADDR). This can help kernel developers or debuggers easily
> >> inspect page-related information in a live kernel or vmcore.
> >>
> >> The script extracts information such as the page flags, mapping, and
> >> other metadata relevant to diagnosing memory issues.
> >>
> >> Output example:
> >> sudo ./show_page_info.py 1 0x7f43df5acf00
> >> PID: 1 Comm: systemd mm: 0xffff8881273bbc40
> >> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
> >> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
> >> User Virtual Address: 0x7f43df5acf00
> >> Page Address: 0xffffea00049a0b00
> >> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
> >> PG_private|PG_reported
> >> Page Size: 16384
> > Should this be called folio size? Or, could this simply removed since Compound
> > Order is given below?
>
>
> Page size refers to the base page size, which equals PAGESIZE.
Shouldn't 'prog["PAGE_SIZE"]' is used for what you are saying? This tool is
using drgn.helpers.linux.page_size()[1] to print this, though?
+def show_page_state(page, addr, mm, pid, task):
+ """Display detailed information about a page."""
+ print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}')
+ print(format_page_data(prog.read(page.value_(), 64)))
+ fields = {
+ "User Virtual Address": hex(addr),
+ "Page Address": hex(page.value_()),
+ "Page Flags": decode_page_flags(page),
+ "Page Size": page_size(page).value_(),
[1] https://drgn.readthedocs.io/en/stable/helpers.html#drgn.helpers.linux.mm.page_size
> Folio size can be calculated using the Compound Order, but of course,
> it can also be shown directly as a result.
>
> >> Page PFN: 0x12682c
> >> Page Physical: 0x12682c000
> >> Page Virtual: 0xffff88812682c000
> >> Page Refcount: 37
> >> Page Mapcount: 7
> >> Page Index: 0x0
> >> Page Memcg Data: 0xffff88812642c000
> >> Memcg Name: init.scope
> >> Memcg Path: /sys/fs/cgroup/memory/init.scope
> >> Page Mapping: 0xffff88810f086a70
> >> Page Anon/File: File
> >> Page VMA: 0xffff88810e4af3b8
> >> VMA Start: 0x7f43df5ac000
> >> VMA End: 0x7f43df5b0000
> >> This page is part of a compound page.
> >> This page is the head page of a compound page.
> >> Head Page: 0xffffea00049a0b00
> >> Compound Order: 2
> >> Number of Pages: 4
> >>
> >> Signed-off-by: Ye Liu <liuye@kylinos.cn>
> >>
> >> Changes in v3:
> >> - Adjust display style.
> >> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/
> >>
> >> Changes in v2:
> >> - Move the show_page_info.py file to tools/mm.
> >> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/
> >> ---
> >> MAINTAINERS | 5 ++
> >> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++
> >> 2 files changed, 125 insertions(+)
> >> create mode 100755 tools/mm/show_page_info.py
> >>
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 17ed0b5ffdd2..85686a30dc72 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst
> >> F: include/linux/page_table_check.h
> >> F: mm/page_table_check.c
> >>
> >> +PAGE STATE DEBUG SCRIPT
> >> +M: Ye Liu <liuye@kylinos.cn>
> >> +S: Maintained
> >> +F: tools/mm/show_page_info.py
> >> +
> >> PANASONIC LAPTOP ACPI EXTRAS DRIVER
> >> M: Kenneth Chan <kenneth.t.chan@gmail.com>
> >> L: platform-driver-x86@vger.kernel.org
> >> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py
> >> new file mode 100755
> >> index 000000000000..8622c5499dfe
> >> --- /dev/null
> >> +++ b/tools/mm/show_page_info.py
> > [...]
> >> +def main():
> >> + """Main function to parse arguments and display page state."""
> >> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter)
> >> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)')
> >> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)')
> >> + args = parser.parse_args()
> >> +
> >> + try:
> >> + vaddr = int(args.vaddr, 16)
> >> + except ValueError:
> >> + print(f"Error: Invalid virtual address format: {args.vaddr}")
> >> + return
> >> +
> >> + task = find_task(args.pid)
> >> + mm = task.mm
> >> + page = follow_page(mm, vaddr)
> > I tried this script on my test machine and got the below error:
> >
> > $ cat ./a.c
> > #include <stdio.h>
> >
> > int main(void)
> > {
> > int foo;
> > printf("hello\n");
> > printf("%x\n", &foo);
>
> To avoid address truncation, you can use the %p format specifier
> instead of %x or %lx when printing a pointer (memory address).
Ah, you're correct, thank you. After fixing my test, the error I reported
before is disappeared. But I think the follow_page() error handling would
better to be updated to catch the exception and provide a better error message?
Also, I'm getting below new error:
$ sudo ./tools/mm/show_page_info.py 47657 0x7fffaf925b6c
PID: 47657 Comm: a.out mm: 0xffff959c8a022100
Raw: 0017ffffc0020828 ffffea6b0c201408 ffffea6b0fc65648 ffff959d32bec9c1
Raw: 00000007fffffffc 0000000000000000 0000000100000000 ffff959cba058000
Traceback (most recent call last):
File "/usr/local/bin/drgn", line 33, in <module>
sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main
runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__")
File "<frozen runpy>", line 291, in run_path
File "<frozen runpy>", line 98, in _run_module_code
File "<frozen runpy>", line 88, in _run_code
File "./tools/mm/show_page_info.py", line 120, in <module>
main()
File "./tools/mm/show_page_info.py", line 115, in main
show_page_state(page, vaddr, mm, args.pid, task)
File "./tools/mm/show_page_info.py", line 63, in show_page_state
memcg_name, memcg_path = get_memcg_info(page)
^^^^^^^^^^^^^^^^^^^^
File "./tools/mm/show_page_info.py", line 43, in get_memcg_info
return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}"
^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/cgroup.py", line 71, in cgroup_name
return kernfs_name(cgrp.kn)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/kernfs.py", line 32, in kernfs_name
return kn.name.string_() if kn.parent else b"/"
^^^^^^^^^
AttributeError: 'struct kernfs_node' has no member 'parent'. Did you mean: '__parent'?
Seems not entirely this script's fault but due to the recent 'struct
kernfs_node' change or my old version of drgn? But anyway, I think it is
better to provide a better error message to users. I'm also curious if you
have a plan for finding and fixing or avoiding this kind of future breakages.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-24 2:51 ` SeongJae Park
@ 2025-04-24 3:24 ` Ye Liu
2025-04-24 3:49 ` SeongJae Park
2025-04-24 3:27 ` Ye Liu
1 sibling, 1 reply; 9+ messages in thread
From: Ye Liu @ 2025-04-24 3:24 UTC (permalink / raw)
To: SeongJae Park
Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains,
osandov, paulmck, sweettea-kernel, liuye
在 2025/4/24 10:51, SeongJae Park 写道:
> On Thu, 24 Apr 2025 09:55:22 +0800 Ye Liu <ye.liu@linux.dev> wrote:
>
>> 在 2025/4/24 06:00, SeongJae Park 写道:
>>> On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote:
>>>
>>>> From: Ye Liu <liuye@kylinos.cn>
>>>>
>>>> Introduces a new drgn script, `show_page_info.py`, which allows users
>>>> to analyze the state of a page given a process ID (PID) and a virtual
>>>> address (VADDR). This can help kernel developers or debuggers easily
>>>> inspect page-related information in a live kernel or vmcore.
>>>>
>>>> The script extracts information such as the page flags, mapping, and
>>>> other metadata relevant to diagnosing memory issues.
>>>>
>>>> Output example:
>>>> sudo ./show_page_info.py 1 0x7f43df5acf00
>>>> PID: 1 Comm: systemd mm: 0xffff8881273bbc40
>>>> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
>>>> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
>>>> User Virtual Address: 0x7f43df5acf00
>>>> Page Address: 0xffffea00049a0b00
>>>> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
>>>> PG_private|PG_reported
>>>> Page Size: 16384
>>> Should this be called folio size? Or, could this simply removed since Compound
>>> Order is given below?
>>
>> Page size refers to the base page size, which equals PAGESIZE.
> Shouldn't 'prog["PAGE_SIZE"]' is used for what you are saying? This tool is
> using drgn.helpers.linux.page_size()[1] to print this, though?
>
> +def show_page_state(page, addr, mm, pid, task):
> + """Display detailed information about a page."""
> + print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}')
> + print(format_page_data(prog.read(page.value_(), 64)))
> + fields = {
> + "User Virtual Address": hex(addr),
> + "Page Address": hex(page.value_()),
> + "Page Flags": decode_page_flags(page),
> + "Page Size": page_size(page).value_(),
>
> [1] https://drgn.readthedocs.io/en/stable/helpers.html#drgn.helpers.linux.mm.page_size
>
>> Folio size can be calculated using the Compound Order, but of course,
>> it can also be shown directly as a result.
>>
>>>> Page PFN: 0x12682c
>>>> Page Physical: 0x12682c000
>>>> Page Virtual: 0xffff88812682c000
>>>> Page Refcount: 37
>>>> Page Mapcount: 7
>>>> Page Index: 0x0
>>>> Page Memcg Data: 0xffff88812642c000
>>>> Memcg Name: init.scope
>>>> Memcg Path: /sys/fs/cgroup/memory/init.scope
>>>> Page Mapping: 0xffff88810f086a70
>>>> Page Anon/File: File
>>>> Page VMA: 0xffff88810e4af3b8
>>>> VMA Start: 0x7f43df5ac000
>>>> VMA End: 0x7f43df5b0000
>>>> This page is part of a compound page.
>>>> This page is the head page of a compound page.
>>>> Head Page: 0xffffea00049a0b00
>>>> Compound Order: 2
>>>> Number of Pages: 4
>>>>
>>>> Signed-off-by: Ye Liu <liuye@kylinos.cn>
>>>>
>>>> Changes in v3:
>>>> - Adjust display style.
>>>> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/
>>>>
>>>> Changes in v2:
>>>> - Move the show_page_info.py file to tools/mm.
>>>> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/
>>>> ---
>>>> MAINTAINERS | 5 ++
>>>> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++
>>>> 2 files changed, 125 insertions(+)
>>>> create mode 100755 tools/mm/show_page_info.py
>>>>
>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>> index 17ed0b5ffdd2..85686a30dc72 100644
>>>> --- a/MAINTAINERS
>>>> +++ b/MAINTAINERS
>>>> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst
>>>> F: include/linux/page_table_check.h
>>>> F: mm/page_table_check.c
>>>>
>>>> +PAGE STATE DEBUG SCRIPT
>>>> +M: Ye Liu <liuye@kylinos.cn>
>>>> +S: Maintained
>>>> +F: tools/mm/show_page_info.py
>>>> +
>>>> PANASONIC LAPTOP ACPI EXTRAS DRIVER
>>>> M: Kenneth Chan <kenneth.t.chan@gmail.com>
>>>> L: platform-driver-x86@vger.kernel.org
>>>> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py
>>>> new file mode 100755
>>>> index 000000000000..8622c5499dfe
>>>> --- /dev/null
>>>> +++ b/tools/mm/show_page_info.py
>>> [...]
>>>> +def main():
>>>> + """Main function to parse arguments and display page state."""
>>>> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter)
>>>> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)')
>>>> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)')
>>>> + args = parser.parse_args()
>>>> +
>>>> + try:
>>>> + vaddr = int(args.vaddr, 16)
>>>> + except ValueError:
>>>> + print(f"Error: Invalid virtual address format: {args.vaddr}")
>>>> + return
>>>> +
>>>> + task = find_task(args.pid)
>>>> + mm = task.mm
>>>> + page = follow_page(mm, vaddr)
>>> I tried this script on my test machine and got the below error:
>>>
>>> $ cat ./a.c
>>> #include <stdio.h>
>>>
>>> int main(void)
>>> {
>>> int foo;
>>> printf("hello\n");
>>> printf("%x\n", &foo);
>> To avoid address truncation, you can use the %p format specifier
>> instead of %x or %lx when printing a pointer (memory address).
> Ah, you're correct, thank you. After fixing my test, the error I reported
> before is disappeared. But I think the follow_page() error handling would
> better to be updated to catch the exception and provide a better error message?
You're absolutely right, I initially overlooked the error handling in
follow_page(). I’ll update it to catch exceptions and provide clearer,
more user-friendly error messages.
> Also, I'm getting below new error:
>
> $ sudo ./tools/mm/show_page_info.py 47657 0x7fffaf925b6c
> PID: 47657 Comm: a.out mm: 0xffff959c8a022100
> Raw: 0017ffffc0020828 ffffea6b0c201408 ffffea6b0fc65648 ffff959d32bec9c1
> Raw: 00000007fffffffc 0000000000000000 0000000100000000 ffff959cba058000
> Traceback (most recent call last):
> File "/usr/local/bin/drgn", line 33, in <module>
> sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')())
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main
> runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__")
> File "<frozen runpy>", line 291, in run_path
> File "<frozen runpy>", line 98, in _run_module_code
> File "<frozen runpy>", line 88, in _run_code
> File "./tools/mm/show_page_info.py", line 120, in <module>
> main()
> File "./tools/mm/show_page_info.py", line 115, in main
> show_page_state(page, vaddr, mm, args.pid, task)
> File "./tools/mm/show_page_info.py", line 63, in show_page_state
> memcg_name, memcg_path = get_memcg_info(page)
> ^^^^^^^^^^^^^^^^^^^^
> File "./tools/mm/show_page_info.py", line 43, in get_memcg_info
> return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}"
> ^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/cgroup.py", line 71, in cgroup_name
> return kernfs_name(cgrp.kn)
> ^^^^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/kernfs.py", line 32, in kernfs_name
> return kn.name.string_() if kn.parent else b"/"
> ^^^^^^^^^
> AttributeError: 'struct kernfs_node' has no member 'parent'. Did you mean: '__parent'?
>
> Seems not entirely this script's fault but due to the recent 'struct
> kernfs_node' change or my old version of drgn? But anyway, I think it is
> better to provide a better error message to users. I'm also curious if you
> have a plan for finding and fixing or avoiding this kind of future breakages.
As for the new error you encountered, it does appear to stem from a recent
change to the struct kernfs_node, or possibly from a mismatch between
kernel headers and the drgn version. While it may not be a bug in the
script itself, I agree that the script should handle such scenarios more
gracefully.
Regarding compatibility across versions, this is definitely something worth
paying attention to. Currently, the script is being adapted based on the
latest drgn and kernel versions. If future changes to kernel structures
occur, I plan to patch the script accordingly to maintain compatibility.
That said, I’m very open to suggestions — do you have any ideas on how
we could better detect or guard against these kinds of breakages
proactively?
Thanks again for raising this!
Thanks,
Ye Liu
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-24 2:51 ` SeongJae Park
2025-04-24 3:24 ` Ye Liu
@ 2025-04-24 3:27 ` Ye Liu
1 sibling, 0 replies; 9+ messages in thread
From: Ye Liu @ 2025-04-24 3:27 UTC (permalink / raw)
To: SeongJae Park
Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains,
osandov, paulmck, sweettea-kernel, liuye
在 2025/4/24 10:51, SeongJae Park 写道:
> On Thu, 24 Apr 2025 09:55:22 +0800 Ye Liu <ye.liu@linux.dev> wrote:
>
>> 在 2025/4/24 06:00, SeongJae Park 写道:
>>> On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote:
>>>
>>>> From: Ye Liu <liuye@kylinos.cn>
>>>>
>>>> Introduces a new drgn script, `show_page_info.py`, which allows users
>>>> to analyze the state of a page given a process ID (PID) and a virtual
>>>> address (VADDR). This can help kernel developers or debuggers easily
>>>> inspect page-related information in a live kernel or vmcore.
>>>>
>>>> The script extracts information such as the page flags, mapping, and
>>>> other metadata relevant to diagnosing memory issues.
>>>>
>>>> Output example:
>>>> sudo ./show_page_info.py 1 0x7f43df5acf00
>>>> PID: 1 Comm: systemd mm: 0xffff8881273bbc40
>>>> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70
>>>> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000
>>>> User Virtual Address: 0x7f43df5acf00
>>>> Page Address: 0xffffea00049a0b00
>>>> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active|
>>>> PG_private|PG_reported
>>>> Page Size: 16384
>>> Should this be called folio size? Or, could this simply removed since Compound
>>> Order is given below?
>>
>> Page size refers to the base page size, which equals PAGESIZE.
> Shouldn't 'prog["PAGE_SIZE"]' is used for what you are saying? This tool is
> using drgn.helpers.linux.page_size()[1] to print this, though?
>
> +def show_page_state(page, addr, mm, pid, task):
> + """Display detailed information about a page."""
> + print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}')
> + print(format_page_data(prog.read(page.value_(), 64)))
> + fields = {
> + "User Virtual Address": hex(addr),
> + "Page Address": hex(page.value_()),
> + "Page Flags": decode_page_flags(page),
> + "Page Size": page_size(page).value_(),
>
> [1] https://drgn.readthedocs.io/en/stable/helpers.html#drgn.helpers.linux.mm.page_size
You're right — I'll update it to use prog["PAGE_SIZE"] here.
>> Folio size can be calculated using the Compound Order, but of course,
>> it can also be shown directly as a result.
>>
>>>> Page PFN: 0x12682c
>>>> Page Physical: 0x12682c000
>>>> Page Virtual: 0xffff88812682c000
>>>> Page Refcount: 37
>>>> Page Mapcount: 7
>>>> Page Index: 0x0
>>>> Page Memcg Data: 0xffff88812642c000
>>>> Memcg Name: init.scope
>>>> Memcg Path: /sys/fs/cgroup/memory/init.scope
>>>> Page Mapping: 0xffff88810f086a70
>>>> Page Anon/File: File
>>>> Page VMA: 0xffff88810e4af3b8
>>>> VMA Start: 0x7f43df5ac000
>>>> VMA End: 0x7f43df5b0000
>>>> This page is part of a compound page.
>>>> This page is the head page of a compound page.
>>>> Head Page: 0xffffea00049a0b00
>>>> Compound Order: 2
>>>> Number of Pages: 4
>>>>
>>>> Signed-off-by: Ye Liu <liuye@kylinos.cn>
>>>>
>>>> Changes in v3:
>>>> - Adjust display style.
>>>> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/
>>>>
>>>> Changes in v2:
>>>> - Move the show_page_info.py file to tools/mm.
>>>> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/
>>>> ---
>>>> MAINTAINERS | 5 ++
>>>> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++
>>>> 2 files changed, 125 insertions(+)
>>>> create mode 100755 tools/mm/show_page_info.py
>>>>
>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>> index 17ed0b5ffdd2..85686a30dc72 100644
>>>> --- a/MAINTAINERS
>>>> +++ b/MAINTAINERS
>>>> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst
>>>> F: include/linux/page_table_check.h
>>>> F: mm/page_table_check.c
>>>>
>>>> +PAGE STATE DEBUG SCRIPT
>>>> +M: Ye Liu <liuye@kylinos.cn>
>>>> +S: Maintained
>>>> +F: tools/mm/show_page_info.py
>>>> +
>>>> PANASONIC LAPTOP ACPI EXTRAS DRIVER
>>>> M: Kenneth Chan <kenneth.t.chan@gmail.com>
>>>> L: platform-driver-x86@vger.kernel.org
>>>> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py
>>>> new file mode 100755
>>>> index 000000000000..8622c5499dfe
>>>> --- /dev/null
>>>> +++ b/tools/mm/show_page_info.py
>>> [...]
>>>> +def main():
>>>> + """Main function to parse arguments and display page state."""
>>>> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter)
>>>> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)')
>>>> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)')
>>>> + args = parser.parse_args()
>>>> +
>>>> + try:
>>>> + vaddr = int(args.vaddr, 16)
>>>> + except ValueError:
>>>> + print(f"Error: Invalid virtual address format: {args.vaddr}")
>>>> + return
>>>> +
>>>> + task = find_task(args.pid)
>>>> + mm = task.mm
>>>> + page = follow_page(mm, vaddr)
>>> I tried this script on my test machine and got the below error:
>>>
>>> $ cat ./a.c
>>> #include <stdio.h>
>>>
>>> int main(void)
>>> {
>>> int foo;
>>> printf("hello\n");
>>> printf("%x\n", &foo);
>> To avoid address truncation, you can use the %p format specifier
>> instead of %x or %lx when printing a pointer (memory address).
> Ah, you're correct, thank you. After fixing my test, the error I reported
> before is disappeared. But I think the follow_page() error handling would
> better to be updated to catch the exception and provide a better error message?
>
> Also, I'm getting below new error:
>
> $ sudo ./tools/mm/show_page_info.py 47657 0x7fffaf925b6c
> PID: 47657 Comm: a.out mm: 0xffff959c8a022100
> Raw: 0017ffffc0020828 ffffea6b0c201408 ffffea6b0fc65648 ffff959d32bec9c1
> Raw: 00000007fffffffc 0000000000000000 0000000100000000 ffff959cba058000
> Traceback (most recent call last):
> File "/usr/local/bin/drgn", line 33, in <module>
> sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')())
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main
> runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__")
> File "<frozen runpy>", line 291, in run_path
> File "<frozen runpy>", line 98, in _run_module_code
> File "<frozen runpy>", line 88, in _run_code
> File "./tools/mm/show_page_info.py", line 120, in <module>
> main()
> File "./tools/mm/show_page_info.py", line 115, in main
> show_page_state(page, vaddr, mm, args.pid, task)
> File "./tools/mm/show_page_info.py", line 63, in show_page_state
> memcg_name, memcg_path = get_memcg_info(page)
> ^^^^^^^^^^^^^^^^^^^^
> File "./tools/mm/show_page_info.py", line 43, in get_memcg_info
> return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}"
> ^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/cgroup.py", line 71, in cgroup_name
> return kernfs_name(cgrp.kn)
> ^^^^^^^^^^^^^^^^^^^^
> File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/kernfs.py", line 32, in kernfs_name
> return kn.name.string_() if kn.parent else b"/"
> ^^^^^^^^^
> AttributeError: 'struct kernfs_node' has no member 'parent'. Did you mean: '__parent'?
>
> Seems not entirely this script's fault but due to the recent 'struct
> kernfs_node' change or my old version of drgn? But anyway, I think it is
> better to provide a better error message to users. I'm also curious if you
> have a plan for finding and fixing or avoiding this kind of future breakages.
>
>
> Thanks,
> SJ
>
> [...]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR
2025-04-24 3:24 ` Ye Liu
@ 2025-04-24 3:49 ` SeongJae Park
0 siblings, 0 replies; 9+ messages in thread
From: SeongJae Park @ 2025-04-24 3:49 UTC (permalink / raw)
To: Ye Liu
Cc: SeongJae Park, akpm, linux-debuggers, linux-kernel, linux-mm,
linux-toolchains, osandov, paulmck, sweettea-kernel, liuye
On Thu, 24 Apr 2025 11:24:33 +0800 Ye Liu <ye.liu@linux.dev> wrote:
[...]
> Regarding compatibility across versions, this is definitely something worth
> paying attention to. Currently, the script is being adapted based on the
> latest drgn and kernel versions. If future changes to kernel structures
> occur, I plan to patch the script accordingly to maintain compatibility.
>
> That said, I’m very open to suggestions — do you have any ideas on how
> we could better detect or guard against these kinds of breakages
> proactively?
No, unfortunately :'( I'm a drgn newbie user and trying to learn ways to use
it better. I therefore thought this problem could also happen to me, and asked
the question to know if you or others have a good solution.
>
> Thanks again for raising this!
I'm so glad to hear this. :)
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-04-24 3:49 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-23 1:48 [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR Ye Liu
2025-04-23 9:45 ` Florian Weimer
2025-04-24 2:17 ` Ye Liu
2025-04-23 22:00 ` SeongJae Park
2025-04-24 1:55 ` Ye Liu
2025-04-24 2:51 ` SeongJae Park
2025-04-24 3:24 ` Ye Liu
2025-04-24 3:49 ` SeongJae Park
2025-04-24 3:27 ` Ye Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).