Hi Huang,
I still encounter some regressions for v3:
crash: invalid structure member offset: folio__flags_1
FILE: memory.c LINE: 20445 FUNCTION: folio_order()
[/root/crash-dev/crash] error trace: 9be19e => a12519 => a05a6f => adf8fd
Detaching from process 3369535
adf8fd: OFFSET_verify+164
Detaching from process 3369536
a05a6f: folio_order+156
Detaching from process 3369537
a12519: do_xarray_count+48
Detaching from process 3369538
9be19e: do_xarray_iter+334
Child exited with status 1
Thread 1 "crash" hit Breakpoint 1, folio_order
(folio=18446626868456917760) at memory.c:20445
20445 readmem(folio + OFFSET(folio__flags_1), KVADDR, &v, sizeof(ulong),
(gdb) bt
#0 folio_order (folio=18446626868456917760) at memory.c:20445
#1 0x0000000000a12519 in do_xarray_count (node=18446626868472885808,
slot=18446626868456917760, path=0x7fffffffbc40 "root/0/0",
index=1, private=0x7fffffffcf00) at filesys.c:4275
#2 0x00000000009be19e in do_xarray_iter (node=18446626868472885808,
height=1, path=0x7fffffffbc40 "root/0/0", index=0,
ops=0x7fffffffcee0) at tools.c:4761
#3 0x00000000009be225 in do_xarray_iter (node=18446626868472877048,
height=2, path=0x7fffffffc280 "root/0", index=0,
ops=0x7fffffffcee0) at tools.c:4768
#4 0x00000000009be225 in do_xarray_iter (node=18446626882156465584,
height=3, path=0x7fffffffc8b0 "root", index=0,
ops=0x7fffffffcee0) at tools.c:4768
#5 0x00000000009be653 in do_xarray_traverse
(ptr=18446744072594201576, is_root=1, ops=0x7fffffffcee0) at
tools.c:4843
#6 0x0000000000a128b1 in do_xarray (root=18446744072594201576,
flag=1, xp=0x0, type=0) at filesys.c:4409
#7 0x0000000000a1c8b7 in refresh_xarray_task_table () at task.c:2613
#8 0x0000000000a16ce5 in task_init () at task.c:670
#9 0x00000000009aa475 in main_loop () at main.c:799
#10 0x0000000000807b0d in captured_main (data=<optimized out>) at main.c:1374
#11 gdb_main (args=<optimized out>) at main.c:1407
#12 0x0000000000807b75 in gdb_main_entry (argc=2, argv=0x7fffffffd958)
at main.c:1434
#13 0x0000000000a61e08 in gdb_main_loop (argc=2, argv=0x7fffffffd958)
at gdb_interface.c:81
#14 0x00000000009aa2c0 in main (argc=3, argv=0x7fffffffd958) at main.c:732
(gdb) p offset_table.folio__flags_1
$1 = -1
I will share one vmcore for you to debug.
Thanks,
Tao Liu
On Thu, Feb 26, 2026 at 7:06 PM Huang Shijie <huangsj(a)hygon.cn> wrote:
We may meet a large folio at two cases:
1.) when height is 1, the real data layout may looks like this:
--------------------------------------------
crash> p *(struct xa_node*)0xffff889883a6a910
$5 = {
shift = 0 '\000',
offset = 0 '\000',
count = 64 '@',
nr_values = 0 '\000',
.................
slots = { 0xffffea0061d21000, 0x2, 0x2, 0x2,
0xffffea0121d85c00, 0x12, 0x12, 0x12,
0xffffea0121d9f400, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22,
0xffffea0121583800, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42,
0xffffea0121833e00, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
0x62,
0xffffea0121eb3800, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82,
0x82, 0x82, 0x82
},
.................
}
--------------------------------------------
The page orders for above folios:
0xffffea0061d21000 --> order 2
0xffffea0121d85c00 --> order 2
0xffffea0121d9f400 --> order 3
0xffffea0121583800 --> order 3
0xffffea0121833e00 --> order 3
0xffffea0121eb3800 --> order 5
2.) when height is not 1, the real data layout may looks like this:
--------------------------------------------
slot: { 0xffff8a2c866b745a, 0xffff8a2c866b16d2, 0xfffff9fcc4ea4000,
0xfffff9fcc4eb9000, ..}
--------------------------------------------
The 0xffff8a2c866b745a and 0xffff8a2c866b16d2 is a internal node, not a folio.
The page orders for above folios:
0xfffff9fcc4ea4000 --> order 6
Current code does not work correctly with large folio page cache.
This patch adds the large folio support with following:
1.) changed the do_xarray_iter() to detect the order of a folio,
and skip the proper dummy slots for a large folio.
2.) updated do_xarray_count/do_xarray_dump/do_xarray_dump_cb
with correct page number if we meet a large folio.
Signed-off-by: Huang Shijie <huangsj(a)hygon.cn>
---
filesys.c | 10 ++++++----
tools.c | 16 +++++++++++++---
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/filesys.c b/filesys.c
index 1e070a3..b6dab55 100644
--- a/filesys.c
+++ b/filesys.c
@@ -4222,7 +4222,7 @@ static void do_xarray_count(ulong node, ulong slot, const char
*path,
ulong index, void *private)
{
struct do_xarray_info *info = private;
- info->count++;
+ info->count += 1 << folio_order(slot);
}
static void do_xarray_search(ulong node, ulong slot, const char *path,
ulong index, void *private)
@@ -4239,8 +4239,10 @@ static void do_xarray_dump(ulong node, ulong slot, const char
*path,
ulong index, void *private)
{
struct do_xarray_info *info = private;
- fprintf(fp, "[%ld] %lx\n", index, slot);
- info->count++;
+ int order = folio_order(slot);
+
+ fprintf(fp, "[%ld] %lx, order:%d\n", index, slot, order);
+ info->count += 1 << order;
}
static void do_xarray_gather(ulong node, ulong slot, const char *path,
ulong index, void *private)
@@ -4274,7 +4276,7 @@ static void do_xarray_dump_cb(ulong node, ulong slot, const char
*path,
"operation failed: entry: %ld item: %lx\n",
info->count, slot);
}
- info->count++;
+ info->count += 1 << folio_order(slot);
}
/*
diff --git a/tools.c b/tools.c
index 69250c4..6b51423 100644
--- a/tools.c
+++ b/tools.c
@@ -4737,15 +4737,19 @@ do_xarray_iter(ulong node, uint height, char *path,
ulong index, struct xarray_ops *ops)
{
uint off;
+ uint order, is_folio;
if (!hq_enter(node))
error(FATAL,
"\nduplicate tree node: %lx\n", node);
- for (off = 0; off < XA_CHUNK_SIZE; off++) {
+ for (off = 0; off < XA_CHUNK_SIZE; off += 1 << order) {
ulong slot;
ulong shift = (height - 1) * XA_CHUNK_SHIFT;
+ order = 0;
+ is_folio = 0;
+
readmem(node + OFFSET(xa_node_slots) +
sizeof(void *) * off, KVADDR, &slot, sizeof(void *),
"xa_node.slots[off]", FAULT_ON_ERROR);
@@ -4754,10 +4758,16 @@ do_xarray_iter(ulong node, uint height, char *path,
if ((slot & XARRAY_TAG_MASK) == XARRAY_TAG_INTERNAL)
slot &= ~XARRAY_TAG_INTERNAL;
+ else if ((slot & XARRAY_TAG_MASK) == 0) {
+ if (ops->type == XARRAY_TYPE_PAGE_CACHE)
+ is_folio = 1;
+ }
- if (height == 1)
+ if (height == 1 || is_folio) {
ops->entry(node, slot, path, index | off, ops->private);
- else {
+ if (ops->type == XARRAY_TYPE_PAGE_CACHE)
+ order = folio_order(slot) % XA_CHUNK_SHIFT;
+ } else {
ulong child_index = index | (off << shift);
char child_path[BUFSIZE];
sprintf(child_path, "%s/%d", path, off);
--
2.43.0