Linux – Defragging RAM / OOM failure

embeddedlinuxmemory

This question is fairly lengthy, so I'll ask the questions at the top and then go through my method of coming to the questions:

  1. Did (Busybox based) rm not execute because there wasn't enough contiguous RAM?
  2. If so, is there a lightweight method of defragging the DMA – without resorting to a system restart?
  3. If not, what caused it? How can I prevent it from happening in the future?

After our test system had been running fairly intensively over the last few days – I telnet'd into the system and checked the test results. When I came to delete some data, the system returned the command line (as if the command had executed correctly). When I came to check the directory for another set of results, I saw the file still existed (using ls).

After this, I noticed more and more of my shell commands wern't performing as expected.

I'll start off with an output from dmesg after rm failed to execute correctly:

Allocation of length 61440 from process 6821 (rm) failed

DMA per-cpu:

CPU 0: hi: 0, btch: 1 usd: 0

Active_anon:0 active_file:1 inactive_anon:0
inactive_file:0 unevictable:6 dirty:0 writeback:0 unstable:0
free:821 slab:353 mapped:0 pagetables:0 bounce:0

DMA free:3284kB min:360kB low:448kB high:540kB active_anon:0kB inactive_anon:0kB active_file:4kB inactive_file:0kB unevictable:24kB present:8128kB pages_scanned:0 all_unreclaimable? no

lowmem_reserve[]: 0 0 0

DMA: 31*4kB 47*8kB 42*16kB 64*32kB 1*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3284kB

14 total pagecache pages

Unable to allocate RAM for process data, errno 12

Initially, I thought I was unable to run the program in the largest portion of contiguous memory. Meaning the DMA was too fragmented and I would have to find a way of getting the system to defragment the memory.

Then I did a quick math/sanity check and realised that the program should have been able to run in the sole 64kB contiguous memory slot. Rm was requesting 61440 bytes (60kB).

I did a good old "manual defrag" and rebooted the system. When I rebooted the sytem I output /proc/buddyinfo:

Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0

Which I suspect map to:

  • 2 x 4 kB
  • 8 x 8 kB
  • 3 x 16 kB
  • 12 x 32 kB
  • 1 x 128 kB
  • 1 x 512 kB

But if one sums the above list of values, it doesn't match up with the output of /proc/meminfo:

MemTotal:           6580 kB
MemFree:            3164 kB
Buffers:               0 kB
Cached:              728 kB
SwapCached:            0 kB
Active:              176 kB
Inactive:            524 kB
Active(anon):          0 kB
Inactive(anon):        0 kB
Active(file):        176 kB
Inactive(file):      524 kB`
Unevictable:           0 kB
Mlocked:               0 kB
MmapCopy:            844 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Slab:               1268 kB
SReclaimable:        196 kB
SUnreclaim:         1072 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        3288 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

To recap, my questions are:

  1. Did rm not execute because there wasn't enough contiguous RAM?
  2. If so, is there a lightweight method of defragging the DMA – without resorting to a system restart?
  3. If not, what caused it? How can I prevent it from happening in the future?

I am using Lantronix's XPort Pro (8MB, Linux OS) running uClinux version 2.6.30. The shell in use is hush.

Best Answer

On your question 2 (defragmenting memory), quoting from https://www.kernel.org/doc/Documentation/sysctl/vm.txt :

compact_memory

Available only when CONFIG_COMPACTION is set. When 1 is written to the file, all zones are compacted such that free memory is available in contiguous blocks where possible. This can be important for example in the allocation of huge pages although processes will also directly compact memory as required.

this implies that the following command (executed with root privileges and if the kernel option mentioned above was enabled)

echo 1 > /proc/sys/vm/compact_memory

should tell the kernel to attempt to defragment the memory as much as possible. Beware that e.g. on some RHEL6 versions, this can crash the kernel...

Related Question