Read /proc/buddyinfo to Diagnose Fragmentation

A big allocation can fail even when free -h says there is plenty of memory left, and /proc/buddyinfo is the file that tells you why. This guide reads it safely, turns its columns into actual block sizes, and helps you decide whether a failed large allocation is down to fragmentation. The file is diagnostic only: nothing here compacts memory, changes allocator settings or restarts a service.

Budget ten minutes. You need a shell on a Linux system with procfs mounted. Checked on Linux 6.8.0-139-generic with a 4096-byte page size and Debian's manpages package 6.7-2. Your node count, zones and numbers will differ, and that is normal, not a red flag.

1. Confirm the file and the page size

Read the interface and the page size first. Both are ordinary, read-only checks that normally need no elevated privileges:

$ test -r /proc/buddyinfo && echo 'buddyinfo is readable'
buddyinfo is readable
$ getconf PAGESIZE
4096

The page size is the unit the order calculation is built on. Do not assume it from the CPU architecture, and do not copy the 4096 from this page onto another host. Keep the value from getconf next to whatever snapshot you are analysing.

Checkpoint: if /proc/buddyinfo is missing or unreadable, stop here. Check that procfs is mounted and that the running kernel actually exposes this file; installing some other user-space utility will not create a kernel proc file for you.

2. Capture one snapshot

Print the file as one small, timestamped sample:

$ date --iso-8601=seconds
2026-09-26T12:00:00+01:00
$ cat /proc/buddyinfo
Node 0, zone      DMA      0      0      0      0      0      0      0      0      1      1      2
Node 0, zone    DMA32  12237   2253   1562    545    548    229     91     72     30     42      6
Node 0, zone   Normal  55816  13702   6804   1675    326    320    399    672    378    173    112

One line per node and zone; here node 0 has DMA, DMA32 and Normal. The numbers after the zone name are counts of currently free chunks, grouped by allocator order. It is a point-in-time snapshot, not a running total, so a second read a moment later can already look different.

Nothing to clean up here, because reading the file changes no system state. If you need to compare an incident against normal activity, save several samples somewhere with sensible access controls rather than trusting one reading:

$ while sleep 5; do
    date --iso-8601=seconds
    cat /proc/buddyinfo
done

Press Ctrl-C to stop the loop. It only reads procfs, but do not leave an unbounded loop like this running unattended in a script.

3. Turn an order column into an actual size

Count the first number after a zone as order 0. The size at order n is:

(2 ^ n) * PAGE_SIZE

With a 4096-byte page, the first columns line up like this:

OrderPages in a chunkSize at 4096-byte pages
014 KiB
128 KiB
2416 KiB
1010244 MiB

The order is the column number counting from zero, not the position counting from one, so the final value on each line in the sample above is order 10. The 112 on the Normal line means 112 free chunks of 4 MiB each, not 112 MiB you could grab in one contiguous piece. The allocator can split a bigger buddy into smaller chunks, or merge two adjacent ones into a bigger chunk, at any time.

A count is not a guarantee an application can actually get that memory. Allocation constraints, migration type, reservations, addressability and timing all play a part too. Use buddyinfo to build a fragmentation hypothesis, then test it against the real workload and the real failure.

4. Look for high-order pressure

When chasing a request for a large physically contiguous area, start at the right-hand columns. A run of zeros at the higher orders, sitting next to plenty of lower-order chunks, fits fragmentation: the free memory exists, it is just not arranged into pieces big enough for that order.

Do not call a zone fragmented off the back of one zero in one snapshot. The order you need depends on the allocation, and the counters shift constantly as the system allocates and frees pages. Compare samples taken during the failure against samples from a healthy period:

$ for sample in 1 2 3; do
    printf '%s\n' "--- sample $sample ---"
    cat /proc/buddyinfo
    sleep 5
done

Compare the same node, zone and column across samples. A persistent lack of higher-order chunks is far more convincing than one zero on its own. Record the kernel version, page size and the workload behind the allocation request alongside the samples.

5. Cross-check with the other proc views

The manpage points to /proc/zoneinfo for more detail, including watermarks, managed-page counts and reserves that buddyinfo does not show:

$ less /proc/zoneinfo

For a finer-grained fragmentation view, check whether /proc/pagetypeinfo exists:

$ if test -r /proc/pagetypeinfo; then
    sed -n '1,80p' /proc/pagetypeinfo
else
    echo '/proc/pagetypeinfo is not available on this kernel'
fi

Pagetypeinfo breaks free-page counts down by migrate type and reports page-block detail, which can explain why pages that look plentiful in buddyinfo are not equally useful for a given allocation. The two files complement each other: never let a total free-memory figure stand in for the order-specific evidence you actually need.

Common traps

Done means