cgroups 内存限制 - 写入错误:设备或资源繁忙

mik*_*ike 5 memory centos swap cgroups

我正在使用内核运行 CentOS 7 3.10.0-693.5.2.el7.x86_64
我使用 cgroups 对进程应用内存限制。在应用程序滚动重启期间,内存限制加倍以适应内存需求。

但是有时在重新启动后无法将交换内存限制降低到原始值并且 cgroup 返回错误 write error: Device or resource busy

[root@us app]# echo "643825664" > memory.limit_in_bytes
[root@us app]# echo "673825664" > memory.memsw.limit_in_bytes
-bash: echo: write error: Device or resource busy
[root@us app]# echo "873825664" > memory.memsw.limit_in_bytes
[root@us app]#
Run Code Online (Sandbox Code Playgroud)

写入更大的值(例如 +200MB)似乎可以正常工作。

我还没有弄清楚为什么会发生这种情况。我在 cgroup 文档中没有找到任何涉及此错误的内容。我认为它必须在当前交换使用率高于限制的情况下做一些事情。

您对此类错误有任何经验吗?

And*_*ton 8

什么cat memory.memsw.usage_in_bytes发言权?您不能将最大值设置为低于当前限制。

查看 3.10 Linux 源代码,修改memsw.limit_in_bytes结果调用mem_cgroup_write()

{
    .name = "memsw.limit_in_bytes",
    .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
    .write_string = mem_cgroup_write,
    .read = mem_cgroup_read,
},
Run Code Online (Sandbox Code Playgroud)

mem_cgroup_write()定义在:https :
//elixir.bootlin.com/linux/v3.10/source/mm/memcontrol.c#L5199

mem_cgroup_write()mem_cgroup_resize_memsw_limit()当类型为时依次调用_MEMSWAP

else if (type == _MEMSWAP)
    ret = mem_cgroup_resize_memsw_limit(memcg, val);
Run Code Online (Sandbox Code Playgroud)

mem_cgroup_resize_memsw_limit()定义在:https :
//elixir.bootlin.com/linux/v3.10/source/mm/memcontrol.c#L4647

该函数调用res_counter_set_limit()https :
//elixir.bootlin.com/linux/v3.10/source/include/linux/res_counter.h#L200

该函数的实现是:

unsigned long flags;
int ret = -EBUSY;

spin_lock_irqsave(&cnt->lock, flags);
if (cnt->usage <= limit) {
    cnt->limit = limit;
    ret = 0;
}
spin_unlock_irqrestore(&cnt->lock, flags);
return ret;
Run Code Online (Sandbox Code Playgroud)

请注意,ret初始化为-EBUSY(对应于Device or resource busy您看到的消息),并且仅当当前使用量小于或等于请求的限制时才更改为零。我的猜测是,在你的情况下它不是,所以函数返回-EBUSY.

如果res_counter_set_limit()将非零值返回给mem_cgroup_resize_memsw_limit(),则mem_cgroup_resize_limit()依次返回相同的值。 mem_cgroup_resize_limit()将值返回到mem_cgroup_write()。该返回值会传播到用户空间,这就是为什么您会看到从echo.

实现是当前内核源代码有点不同,但行为是相同的。您不能将最小值调整为小于使用值的值。