From 547fab7c38f0beb3985e49e4dd7de818d2218537 Mon Sep 17 00:00:00 2001 From: Cheng Jian Date: Fri, 18 Feb 2022 18:28:01 +0800 Subject: [PATCH] description/memory: remote pcp drain --- study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md index 1887fda..a36f9b2 100644 --- a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md +++ b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md @@ -703,10 +703,22 @@ Mel Gorman 发现了这一问题, 开发了 [Calculate pcp->high based on zone s * Remote per-cpu cache access +最初释放 PCP 是通过 IPI 来完成的, 并且经历了不断的修正和优化, 参见 v2.6.24-rc1 的[Drain per-cpu lists when high-order allocations fail](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e2c55dc87f4a398b9c4dcc702dbc23a07fe14e23), v2.6.25-rc1 的 [Page allocator: clean up pcp draining functions](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9f8f2172537de7af0b0fbd33502d18d52b1339bc), v3.4-rc1 的 [mm: only IPI CPUs to drain local pages if they exist](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=74046494ea68676d29ef6501a4bd950f08112a2c). 以及 v4.11-rc1 的 [mm, page_alloc: drain per-cpu pages from workqueue context](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0ccce3b924212e121503619df97cc0f17189b77b). + +然而即使经历了这么多年的修改, 这个解决方案并不完美. 最好的情况是, 它会导致每个目标 CPU 上的上下文切换来运行排除列表的回调. 但是, 如果目标 CPU 处于 tickless 模式, 或者它正在运行高优先级实时任务, 那么工作队列条目可能在很长一段时间内根本不运行. 因此, CPU 上的任何空闲页面都将被锁定在其本地列表中, 幸运的是, 大多数空闲页面可能就是锁定在本地列表中的. + +想要完美的解决这个问题, 就要在一个 CPU 上即可完成系统中所有 CPU 的 PCP 页面, 这就需要提供一种机制, 能够让一个 CPU 可以安全地访问 remote CPU 的 PCP 页面. + +[mm/page_alloc: Remote per-cpu page list drain support](https://lore.kernel.org/all/20211103170512.2745765-1-nsaenzju@redhat.com) 通过允许远程 CPU 的本地列表中获取页面来缓解这个问题. 尝试添加了自旋锁来控制对 per-CPU 列表的访问, 从根本上消除了它们的 per-CPUness; 这个解决方案是有效的, 但是它只是增加了创建 per-CPU 列表以避免的开销. 所以这些补丁没有进入内核. + +新算法使用了 RCU 的方式来完成 remote CPU 释放 PCP 页面的操作.
将 PCP 页面列表结构封装到 pcplists 中, 每个 CPU 现在都有两组列表来保存空闲页面: lp(local_page) 和 drain, 其中一组在任何给定的时间都在使用, 而另一组则保留在备用状态(并且是空的). 当系统想要释放所有 CPU 的 PCP 页面时, 就就通过 rcu_replace_pointer() 交换两个指针, 并通过 synchronize_rcu() 等待宽限期结束后对 PCP 页面进行释放. 通过 RCU 这种方式, 不用再通过以前 IPI 或者 workqueue 的方式在 per-cpu 上去完成, 而是通过一个 remote CPU 即可释放系统中所有 CPU 的 PCP 页面.
+其主要优点是它可以很好地解决问题, 避免了对基于配置的启发式方法的需求或不得不修改应用程序(即使用 Marcello Tosatti ATM 正在工作的隔离 prctrl). 参见 [Remote per-CPU page list draining](https://lwn.net/Articles/884448) + | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| | 2021/09/21 | Sebastian Andrzej Siewior | [mm/swap: Add static key dependent pagevec locking](https://patchwork.kernel.org/project/linux-mm/cover/20190424111208.24459-1-bigeasy@linutronix.de) | 本系列实现了swap 的代码路径中通过禁用抢占来同步它对 per-cpu pagevec 结构体的访问. 这是可行的, 需要从中断上下文访问的结构体是通过禁用中断来保护的.
有一种情况下, 需要访问远程 CPU 的 per-cpu 数据, 在 v1 版本中, 试图添加每个 cpu 的自旋锁来访问结构体. 这将增加 lockdep 覆盖率和从远程 CPU 的访问, 不需要 worker.
在 v2 中这是通过在远程 CPU 上启动一个 worker 并等待它完成来解决的.
关于无争用 spin_lock () 的代价, 以及避免每个 cpu worker 的好处很少, 因为它很少被使用. 然后听从社区的建议使用 static key use_pvec_lock, 在某些情况下(如 NOHZ_FULL 情况), 它支持每个 cpu 的锁定. | v1 ☐ | [PatchWork 0/4,v2](https://patchwork.kernel.org/project/linux-mm/cover/20190424111208.24459-1-bigeasy@linutronix.de) | | 2021/09/21 | Nicolas Saenz Julienne | [mm: Remote LRU per-cpu pagevec cache/per-cpu page list drain support](https://patchwork.kernel.org/project/linux-mm/cover/20210921161323.607817-1-nsaenzju@redhat.com) | 本系列介绍了 mm/swap.c 的每个 CPU LRU pagevec 缓存和 mm/page_alloc 的每个 CPU 页面列表的另一种锁定方案 remote_pcpu_cache_access, 这将允许远程 CPU 消耗它们.
目前, 只有一个本地 CPU 被允许更改其每个 CPU 列表, 并且当进程需要它时, 它会按需这样做 (通过在本地 CPU 上排队引流任务).
大多数系统会迅速处理这个问题, 但它会给 NOHZ_FULL CPU 带来问题, 这些 CPU 无法在不破坏其功能保证(延迟、带宽等) 的情况下接受任何类型的中断. 如果这些进程能够远程耗尽列表本身, 就可以与隔离的 CPU 共存, 但代价是更多的锁约束.
通过 static key remote_pcpu_cache_access 来控制该特性的开启与否, 对于非 nohz_full 用户来说, 默认禁用它, 这保证了最小的功能或性能退化. 而只有当 NOHZ_FULL 的初始化过程成功时, 该特性才会被启用. | v2 ☐ | [2021/09/21 PatchWork 0/6](https://patchwork.kernel.org/project/linux-mm/cover/20210921161323.607817-1-nsaenzju@redhat.com)
*-*-*-*-*-*-*-*
[2021/11/03 PatchWork v2,0/3](https://patchwork.kernel.org/project/linux-mm/cover/20211103170512.2745765-1-nsaenzju@redhat.com) | +| 2022/02/08 | Nicolas Saenz Julienne | [mm/page_alloc: Remote per-cpu lists drain support](https://lore.kernel.org/all/20220208100750.1189808-1-nsaenzju@redhat.com) | 参见 [Remote per-CPU page list draining](https://lwn.net/Articles/884448) | v1 ☐☑✓ | [LORE v1,0/2](https://lore.kernel.org/all/20220208100750.1189808-1-nsaenzju@redhat.com) | ### 2.2.6 ALLOC_NOFRAGMENT 优化 @@ -4336,6 +4348,8 @@ DAMON 利用两个核心机制 : **基于区域的采样**和**自适应区域 [FGKASLR Is An Exciting Linux Kernel Improvement To Look Forward To In 2022](https://www.phoronix.com/scan.php?page=news_item&px=Linux-FGKASLR-2022) +[FGKASLR Patches Revised A 10th Time For Improving Linux Kernel Security](https://www.phoronix.com/scan.php?page=news_item&px=FGKASLR-Linux-v10) + | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| | 2021/10/13 | Kees Cook | [x86: Various clean-ups in support of FGKASLR](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=ca136cac37eb51649d52d5bc4271c55e30ed354c) | FGKASLR 的一些的准备工作, 都是一些独立的改动. 比如:
1. 在 relocs 工具中支持[超过 64K 的节头](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a54c401ae66fc78f3f0002938b3465ebd6379009).
2. KASLR 中通过 kaslr_get_random_long() 提取随机种子时候, 通过 earlyprintk debug_putstr 输出了很多无用的调试信息, 允许将[参数 purpose 置 NULL](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0d054d4e82072bcfd5eb961536b09a9b3f5613fb)来使输出静默.
4. 修改 [ORC 查找表的大小]](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ca136cac37eb51649d52d5bc4271c55e30ed354c)以覆盖整个内核的代码段. | v1 ☑ [5.16-rc1](https://lkml.org/lkml/2021/11/2/26) | [LORE 0/4](https://lore.kernel.org/all/20211013175742.1197608-1-keescook@chromium.org) |