客户遇到一个oom问题,客户使用的是一个小内存的系统,在oom后触发的show mem里可以看到以下信息:
Normal free :3516kB boost:4096kB min:5120kB low:5496kB high:5872kB..
上述log是通过__show_mem -> show_free_areas打印出来的,可以看到,剩余内存约free:3516kB,而触发oom的panic申请者申请的内存类型是unmoveable的order 0的page。
从上面的信息可以看到,还是有剩余内存的,但是因为watermark_boost_factor(对应上述log的boost字段)的原因,导致min水位较高,从而申请不到内存。
客户的oom触发了panic,在crash工具中解析转储文件后,输入命令:
p watermark_boost_factor
可以看到,当前系统配置的watermark_boost_factor不为0。
通过命令:
p sysctl_panic_on_oom
确定客户开启了oom时强制触发panic的机制。
调整watermark_boost_factor为0后继续测试,以前频繁出现的oom不再出现,命令如下:
echo 0 > /proc/sys/vm/watermark_boost_factor
watermark_boost_factor的值会动态调节整体提升zone的min、low、high的水位,如果设置得过高,则会导致min水位过高,min水位之下的内存难以被使用到,也就是本题遇到的问题。
我们在小内存系统上一般会把watermark_boost_factor直接设置成0,以使用更多的内存,但是需要注意的是,这会让内存回收机制变得比较不敏感,可能会遇到内存回收不及时从而导致无法申请到大order的page的问题。因为kswapd触发内存回收的逻辑是空闲内存低于low水位开始,直到空闲内存高于high水位停止,watermark_boost_factor为0会使low水位变得比较低。