web-dev-qa-db-ja.com

cgroupsメモリ制限-書き込みエラー:デバイスまたはリソースがビジーです

CentOS 7をカーネル3.10.0-693.5.2.el7.x86_64で実行しています。
cgroupsを使用して、プロセスにメモリ制限を適用します。アプリケーションのローリング再起動時に、メモリの制限はメモリのニーズに対応するために2倍になります。

ただし、再起動後にスワップメモリ​​の制限を元の値に下げることができず、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のドキュメントには何も見つかりませんでした。私はそれが現在のスワップ使用量が制限よりも高い状態で何かをしなければならないと思います。

そのようなエラーの経験はありますか?

5
michal kralik

_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()は、型が__MEMSWAP_の場合にmem_cgroup_resize_memsw_limit()を呼び出します。

_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#L2

その関数の実装は次のとおりです。

_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からのエラーが表示されるのはこのためです。

現在のカーネルソースの実装は少し異なりますが、動作は同じです。最小値を使用中の値よりも小さい値に調整することはできません。

6
Andy Dalton