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.
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.
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.
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:
| Order | Pages in a chunk | Size at 4096-byte pages |
|---|---|---|
| 0 | 1 | 4 KiB |
| 1 | 2 | 8 KiB |
| 2 | 4 | 16 KiB |
| 10 | 1024 | 4 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.
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.
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.
vm settings as a harmless follow-up. Those actions can disrupt workloads and can hide the exact conditions you are trying to diagnose.(2 ^ order) * PAGE_SIZE.