LWN:新增misc cgroup!
共 3899字,需浏览 8分钟
·
2021-06-06 22:40
关注了就能看到更多这么棒的文章哦~
The misc control group
By Jake Edge
May 18, 2021
DeepL assisted translation
https://lwn.net/Articles/856438/
控制组(cgroups, control groups)是用来限制系统中的进程对共享资源的访问的。哪些资源呢?比如说用于指定虚拟机(VM)中的加密过的内存区域要使用的一个 ID 信息,例如 AMD 安全加密虚拟化(SEV,Secure Encrypted Virtualization)功能所使用的地址空间标识符(ASIDs,address-space identifiers)。Vipin Sharma 早在 9 月份的时候就着手为这些 ASIDs 增加一个 cgroup。不过后来收到反馈之后,他将这个想法扩展为一个可以跟踪和限制任何可以计数(count)的资源的 controller 了。这个 patch set 最终形成了 misc cgroup 的控制器,并且已经合入,会被包含在 Linux 5.13。
其基本思想是允许管理员(或云端管理系统)对 cgroup 中的进程所能使用的这些 ID 的数量实施限制。在云环境中,这些进程一般就是对应那些正在 KVM 下运行的虚拟机。在最初发布 ASIDs 的时候,Sean Christopherson 建议增大 controller 的管理范围来包含更多种类的加密 ID,而不仅仅局限于 AMD SEV 使用的 ID。英特尔也有一个类似的信任域扩展(TDX,Trust Domain Extension)功能,同样使用了 key ID,因此同样也是一个可能需要管理起来的有限资源。s390 架构也有类似的安全执行 ID(SEID,secure execution ID)。这些 ID 可能不如其他类似的 ID 那么稀缺,但是如果有一个 controller 来控制分配的话也是有好处的。
这些信息促使 Sharma 将原本计划实现的 controller 进行了扩展,变得更加通用以便让 TDX ID 和 SEID 也能用起来。到 1 月份的时候,"encryption ID controller" 这个 patch set 已经发出了第 4 个版本,但维护者 Tejun Heo 有点担心在 cgroup 子系统中增加这些特定硬件相关的控制开关:
我很不愿意接受跟特定厂商有关的接口,原因有几个,但其中最重要的是这些接口通常意味着之前没有充分做好抽象化,或者真实的需求没有充分分析和开发,而且这些接口在一段时间后往往会成为包袱。
他和 Sharma 在讨论中进行了不少交流,但最终 Heo 说,由于 encryption ID 的前景还不明确,他还是希望能换一个不同的方法来实现。与其让这个 controller 专门用于管理 encryption ID,不如把它变成一个用来管理某个 cgroup(或整个系统)中有数量限制的资源的通用 controller:"所以,最终结果上来说,与之前提出的代码并没有什么不同,只是让他变成了一个通用的 misc controller。"
Sharma 同意了这个计划,并在 2 月中旬发布了一个 misc controller 的 RFC 补丁。之后又发布了三个版本,不过 controller 的形式基本上再没有变过了。这些 patch 还增加了 SEV ASIDs 和相关的(但不是相同的概念)SEV Encrypted State(SEV-ES)IDs 的改动,把它们两个作为采用这种方式控制数量的资源。在具有相关功能的 AMD CPU 上,如果用 CONFIG_CGROUP_MISC 构建内核,那么 root control group 就会有一个 misc.capacity 文件,显示每个类别中的可用 ID 的数量:
$ cat misc.capacity
sev 50
sev_es 10
假如有个系统中有两个被此 controller 管理的资源,名称分别为 "res_a "和 "res_b",那么在 cgroup 目录结构中将会展示这两个值。其中 misc.capacity 这个 root file 是只读的,其中记录了整个系统中有多少数量的相关资源,另外有两个文件会出现在 non-root 的 cgroup 中,可以用来限制资源以及监控使用了多少:
$ cat misc.current
res_a 3
res_b 0
$ cat misc.max
res_a 10
res_b 4
从名字也可以看出,misc.current 指出了这个 group 当前的使用情况,而 misc.max 则指出了这个 group 中所允许的最大使用量被设置为多少。misc.max 与其他两个文件不同,它是一个可读可写的文件,所以如果要设置最大值的话可以这样写:
# echo res_a 1 > misc.max
# echo res_b max > misc.max
第一个命令会将 res_a 的最大值设置为 1,而第二个将 res_b 设置为这个 group 中所允许的最大值(由其父控制组进行限制的话就可能小于系统最大值)。
添加两种类型的 SEV ASID 的 patch 展示了如何向 controller 添加其他要管理的资源(比如 TDX ID 或 SEID)。先在 misc_res_types 这个 enum 中增加一项,并把相应的名字添加到 misc_res_names 数组中。在资源可被分配使用之前,必须先初始化一下来设置全系统有多少资源可用:
int misc_cg_set_capacity(enum misc_res_type type, unsigned long capacity);
当需要使用或者释放其中某个资源时,可以使用 charge(意指收费)以及 uncharge(意指不再收费) API:
int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg,
unsigned long amount);
void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg,
unsigned long amount);
有一点需要注意的是,按照 cgroup v2 的设计,在将一个进程迁移(migrate)到另一个不同的 cgroup 时并不改变统计信息。此进程之前分配获取到资源时候所在的 cgroup 会一直保持对这个进程的数据统计以及 charge 状态,直到资源被释放为止。调用者函数(caller)需要跟踪记录被 charge 的 cgroup,这样才能在后面对正确的 cgroup 进行 uncharge。在代码 review 过程中有讨论过要不要让 charge 关系跟随进程一起迁移。Jacob Pan 提出也把 charge 关系一起迁移,因为他正在考虑使用 misc controller 来限制通过 DMA 用于 I/O 的 ASIDs(IOASIDs)。Heo 明确指出不对 misc controller 进行 charge 关系的迁移:
请注意,cgroup2 总体上并不喜欢、支持 charge 关系的迁移,甚至连普通迁移也不赞同。我们在 cgroup1 上尝试了 memcg,结果很糟糕。文档中描述的预期使用场景是使用迁移来孵化一个 cgroup(或者甚至更理想的情况是使用新的 clone 系统调用来在指定的 cgroup 中启动进程),直到退出为止。所有现存的 controller 都假定是按这种使用模式来工作的,所以除非有一些非常有说服力的理由否则我应该不会赞同偏离这个方向的做法。
在进程获得 IOASIDs 之后,很可能没有什么真正使用场景需要迁移进程,所以 Pan 还是打算使用 misc contoller,至少目前是这样决定的。
事实上,正如 Heo 所说,misc 控制器有一点 "让步方案(cop-out)"的意思。他不相信这些硬件功能今后会 "永远" 存在,所以他不愿意将 cgroup 子系统跟它们永远关联起来:
我判断,这些底层的硬件特性还没有成熟到可以在它们上面建立合理的抽象。随着时间的推移,也许未来的发展会让硬件达到这样的程度,当然也许这些功能很快也就会消失于是人们都不会记得有这么个功能。
但是,不管是不是个让步方案,Misc controller 现在已经开始用起来了。看起来还会有其他几个地方可能打算使用这个 misc controller。在未来几个月里,很可能会出现更多的使用场景。对于简单的资源,也就是只需要对其数量进行跟踪和限制的话,那么 misc controller 可以很好地完成这项工作。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~