cgroup v2にプロセスを追加しようとしたときのEBUSY

cgroup v2にプロセスを追加しようとしたときのEBUSY

私はcgroups v2Fedora 35カーネル5.15.5-200.fc35.x86_64)で遊んでいます。

問題なくテストcpuして制御できます。しかし、または私は困った。以下は、コントローラでこの問題を再現する方法の手順の一覧です(すべてのコマンドはrootとして実行されます)。cpusetpidsmemoryhugetlbiomemory

  1. ルートcgroupでメモリコントローラが有効になっていることを確認してください。

    # cat cgroup.subtree_control
    cpu io memory hugetlb pids
    
  2. 新しいcgroupを作成します。

    # mkdir example
    # cd example/
    
  3. メモリコントローラを有効にする:

    # echo "+memory" > cgroup.subtree_control 
    
  4. 制御グループにプロセスを追加します。

    # echo $$ > cgroup.procs 
    bash: echo: write error: Device or resource busy
    

最初にコントローラにプロセスを追加してからコントローラをアクティブにしようcgroupとすると、最後のステップで同じエラーが発生します。

私は何が間違っていましたか?

答え1

これは、cgroups v2の「内部プロセスなし」ルールによるものです。

   The "no internal processes" rule is in fact more subtle than
   stated above.  More precisely, the rule is that a (nonroot)
   cgroup can't both (1) have member processes, and (2) distribute
   resources into child cgroups—that is, have a nonempty
   cgroup.subtree_control file.  Thus, it is possible for a cgroup
   to have both member processes and child cgroups, but before
   controllers can be enabled for that cgroup, the member processes
   must be moved out of the cgroup (e.g., perhaps into the child
   cgroups).

   With the Linux 4.14 addition of "thread mode" (described below),
   the "no internal processes" rule has been relaxed in some cases.

源泉:cグループ(7)


カーネルソースコードも参照してください。

https://elixir.bootlin.com/linux/v5.19/source/kernel/cgroup/cgroup.c#L2586

**
 * cgroup_migrate_vet_dst - verify whether a cgroup can be migration destination
 * @dst_cgrp: destination cgroup to test
 *
 * On the default hierarchy, except for the mixable, (possible) thread root
 * and threaded cgroups, subtree_control must be zero for migration
 * destination cgroups with tasks so that child cgroups don't compete
 * against tasks.
 */
int cgroup_migrate_vet_dst(struct cgroup *dst_cgrp)
{
    // [..]

    /* apply no-internal-process constraint */
    if (dst_cgrp->subtree_control)
        return -EBUSY;

    return 0;
}

たとえば、次のように動作します。

# cd /sys/fs/cgroup
/sys/fs/cgroup # rmdir deleteme
/sys/fs/cgroup # mkdir deleteme
/sys/fs/cgroup # cd deleteme 
/sys/fs/cgroup/deleteme # mkdir leaf
/sys/fs/cgroup/deleteme # echo '+memory' > cgroup.subtree_control
/sys/fs/cgroup/deleteme # echo $$ > leaf/cgroup.procs
/sys/fs/cgroup/deleteme #

関連情報