TenForward

技術ブログ。はてなダイアリーから移転しました

Linux 4.14 で導入された cpuset の cgroup v2 mode

(2019-02-23 少し追記しています)

4.14 kernel から cgroup の cpuset コントローラーに cpuset_v2_mode というオプションが使えるようになりました。

しばらく見ないうちに cpuset コントローラーをマウントするとファイルがたくさん増えていますが、このオプションを設定すると、従来からある cpuset.{cpus,mems} ファイルの動きが変わるようです。そしていつの間にか増えている cpuset.effective_{cpus,mems} ファイルと合わせて使って cpuset の制限を行うようです。

このオプションを設定したときの動きが、cgroup v2 の cpuset の動きになるようです(v2 の cpuset は現時点ではまだマージされていません)。

現在使える cpu や memory が effective で表示されており、それと cpuset.{cpus,mems} のマスクを取って、使える cpu, memory を導き出すようですね。

従来の cpuset(v1 mode)

# mount -t tmpfs cgroup /sys/fs/cgroup/
# mkdir /sys/fs/cgroup/cpuset
# mount -t cgroup -o cpuset cgroup /sys/fs/cgroup/cpuset/
# cd /sys/fs/cgroup/cpuset/
# mkdir test01
# cd test01
# echo "0-1" > cpuset.cpus
# echo "0" > cpuset.mems

この状態で test01 cgroup 内のファイルは、

# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0-1
cpuset.effective_cpus: 0-1

となっています。ここでおもむろに cpu をひとつオフラインにします。cpu1 です。

# echo 0 > /sys/devices/system/cpu/cpu1/online

すると、

# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0
cpuset.effective_cpus: 0

cpuset.cpuscpuset.effective_cpus0 になります。

ここで再度 cpu1 をオンラインにすると、

echo 1 > /sys/devices/system/cpu/cpu1/online
# cat /sys/devices/system/cpu/cpu1/online
1
# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0
cpuset.effective_cpus: 0

特に変化はありません。

cpuset_v2_mode 付きマウント(v2 mode)

マウントオプションとして cpuset_v2_mode を与えます。

# mount -t cgroup -o cpuset,cpuset_v2_mode cgroup /sys/fs/cgroup/cpuset/
# cat /proc/self/mounts | grep cpuset
cgroup /sys/fs/cgroup/cpuset cgroup rw,relatime,cpuset,cpuset_v2_mode 0 0

この状態では、さきほどと特に変化はありません。

# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0-1
cpuset.effective_cpus: 0-1

ここで cpu1 をオフラインにします。

# echo 0 > /sys/devices/system/cpu/cpu1/online

すると、

# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0-1
cpuset.effective_cpus: 0

cpuset.cpus はそのままで実際の cpuset.effective_cpus のみ値が変わります。

ここまで来ると動きは予想できますね。再度 cpu1 をオンラインにしてみます。

# echo 1 > /sys/devices/system/cpu/cpu1/online
# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0-1
cpuset.effective_cpus: 0-1

cgroup作成後にCPUが増えた時(2019-02-23 追記)

cgroup作成後にcpuが減って、また戻った場合の動きは見ましたが、cgroup作成後にonline の cpu が増えた場合にどうなるのかが気になったので試してみました。

# echo 0 > /sys/devices/system/cpu/cpu2/online
# mkdir test01
# cd test01
# cat cpuset.cpus

# cat cpuset.effective_cpus 
0-1
# echo "0-1" > cpuset.cpus 
# echo "0" > cpuset.mems 
# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0-1
cpuset.effective_cpus: 0-1
# echo 1 > /sys/devices/system/cpu/cpu2/online
# for f in $(ls cpuset.*cpus); do echo -n "$f: "; cat $f; done
cpuset.cpus: 0-1
cpuset.effective_cpus: 0-1

上の例のように CPU をひとつ(cpu2) offline にしておいて、cgroup を作成後、cpu2 を online にしても cpuset.effective_cpus の値は変化しません。

まとめ

CPU/メモリーの online, offline を切り替えると:

  • v1 mode: cpuset.{cpus,mems}cpuset.effective_{cpus,mems} の値も変化するが、その後再度状態が変わってもそのまま
  • v2 mode: cpuset.{cpus,mems} の値は変化しない。cpuset.effective_{cpus,mems} の値は実際に合わせて変化する

ただし、cpuset.effective_* の復元は cgroup 作成時の値まで。

おまけ(2019-02-23 追記)

ちなみにこのオプションが使えるようになったコミットは次のものですが、これはオプションの追加と、そのオプションが指定されているときの条件分岐を変更しているだけですので、処理自体はこの前にあらかじめ実装されているようですね。