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のドキュメントには何も見つかりませんでした。私はそれが現在のスワップ使用量が制限よりも高い状態で何かをしなければならないと思います。
そのようなエラーの経験はありますか?
_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
からのエラーが表示されるのはこのためです。
現在のカーネルソースの実装は少し異なりますが、動作は同じです。最小値を使用中の値よりも小さい値に調整することはできません。