cgroups memory limit - erro de gravação: dispositivo ou recurso ocupado

2

Estou executando o CentOS 7 com o kernel 3.10.0-693.5.2.el7.x86_64 .
Eu uso cgroups para aplicar um limite de memória em processos. Durante o reinício do aplicativo, o limite de memória é duplicado para acomodar as necessidades de memória.

No entanto, às vezes, após a reinicialização, não é possível reduzir o limite de memória de troca para o valor original e o cgroup retorna um erro write error: Device or resource busy

Como

[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]#

Escrever um valor maior (como + 200MB) parece funcionar bem.

Eu não entendi porque isso acontece. Eu não encontrei nada na documentação do cgroup que se referiria a este erro. Eu suponho que tem que fazer algo com o atual uso de swap sendo maior que o limite.

Você tem alguma experiência com esses erros?

    
por michal kralik 20.12.2017 / 14:38

1 resposta

1

O que cat memory.memsw.usage_in_bytes diz? Você não pode definir o máximo abaixo do limite atual.

Olhando para as origens do Linux 3.10, modificar memsw.limit_in_bytes resulta em uma chamada para 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() é definido em: link

mem_cgroup_write() , por sua vez, chama mem_cgroup_resize_memsw_limit() quando o tipo é _MEMSWAP :

else if (type == _MEMSWAP)
    ret = mem_cgroup_resize_memsw_limit(memcg, val);

mem_cgroup_resize_memsw_limit() é definido em: link

Essa função chama res_counter_set_limit() :
link

A implementação dessa função é:

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;

Observe que ret é inicializado como -EBUSY (que corresponde à mensagem Device or resource busy que você está vendo) e é alterado para zero apenas se o uso atual for menor ou igual ao limite solicitado. Meu palpite é que no seu caso não é, então a função retorna -EBUSY .

Se res_counter_set_limit() retornar um valor diferente de zero para mem_cgroup_resize_memsw_limit() , então mem_cgroup_resize_limit() retornará o mesmo valor. mem_cgroup_resize_limit() retorna o valor para mem_cgroup_write() . Esse valor de retorno é propagado para o espaço do usuário e é por isso que você vê o erro que está vendo em echo .

A implementação é que as fontes atuais do kernel são um pouco diferentes, mas o comportamento é o mesmo. Você não pode ajustar o valor mínimo para um valor menor que o valor em uso.

    
por 05.08.2018 / 21:22