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

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

我正在运行带有 kernel 的 CentOS 7 3.10.0-693.5.2.el7.x86_64
我使用 cgroup 对进程应用内存限制。在应用程序滚动重新启动期间,内存限制加倍以满足内存需求。

然而,有时重新启动后,无法将交换内存限制降低到原始值,并且 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]#

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

我还没弄清楚为什么会出现这种情况。我在 cgroup 文档中没有找到任何引用此错误的内容。我认为它必须在当前交换使用量高于限制的情况下执行某些操作。

您有遇到此类错误的经验吗?

答案1

说什么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,
},

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);

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;

请注意,它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.

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

相关内容