关注了就能看到更多这么棒的文章哦~
Netgpu and the hazards of proprietary kernel modules
By Jonathan Corbet
July 31, 2020
https://lwn.net/Articles/827596/
表面上来看,netgpu patch set 增加了一个有价值的新功能:可以在网卡和 GPU 之间直接搬移网络数据,不再需要经过 host CPU。不过,很快就变成了一个反面例子:怎样会导致你的 patch 无法合入 kernel。以它目前的形式来说,是绝无可能合入 Linux kernel 的,并且也引发了人们对于目前 kernel 里面 module 的规则的强烈反对。这主要是来自一个根本性的错误:把 kernel 的工作建立在一个专有的(proprietary)kernel module 基础之上。
netgpu 的应用场景看起来是在机器学习领域,这种场景下会需要处理大量的数据,这就需要利用 GPU 来帮助提升性能。必须把从网络上过来的数据流传送给 GPU。这些数据会照常先放到主内存里面,然后传送给 GPU。这里有一次额外的 copy 动作,由于它占用了 memory-bus(总线)的带宽以及 CPU 时间,也就会对系统带来额外负担。
如果能让网卡把数据通过 PCI 总线直接写入 GPU 的内存,就可以大大减少这些额外开销。有此功能的网卡还可以把网络数据内容传送给 GPU memory,同时把 packet header(网络包头)写入普通内存。这样就可以让 kernel 里的网络协议栈代码照常处理这些协议了。netgpu patch 就是用来实现这类操作的,可以在损失一些功能的情况下来改进系统性能,具体来说,由于数据被直接送给 GPU memory 了,会导致那些需要分析 packet 中数据的应用场景很难实现了。
最近几年有许多工作都是为了实现这种 zero-copy、device-to-device 的数据传输的。因此人们本以为这个功能也会很快被接受。确实这部分代码一直在进行正常 review,直到人们讨论到 21 个 patch 中的最后一个,这里情况就开始不对了。这个 patch 就是 netgpu module 和 NVIDIA 的 proprietary GPU 驱动的接口实现,如果没有 NVIDIA 驱动文件的话,这个 patch 都无法编译。看到这里的时候,Greg Kroah-Hartman 就停了下来,抱怨说:
Ok, now you are just trolling us.
Nice job, I shouldn't have read the previous patches.
Please, go get a lawyer to sign-off on this patch, with their corporate email address on it. That's the only way we could possibly consider something like this.
接下来就是通常的那些尖刻刺耳的争论了,在讨论为什么这个 patch 会被提出来。patch 的作者 Jonathan Lemon 坚持认为 patch 的目的并不是专门为了给 NVIDIA 的 proprietary module 来增加功能:
This is not in support of a proprietary driver. As the cover letter notes, this is for data transfers between the NIC/GPU, while still utilizing the kernel protocol stack and leaving the application in control.
While the current GPU utilized is nvidia, there's nothing in the rest of the patches specific to Nvidia - an Intel or AMD GPU interface could be equally workable.
不过其他人不这么看,他们觉得这个代码很显然一开始就是围绕着 NVIDIA module 来实现的。Christoph Hellwig 认为所有想要合入 upstream 的 driver 都应该是基于现有的 P2PDMA framework 的,这个架构天生就是为了支持这些 device-to-device 的数据传输的。Jason Gunthorpe 也有同样的看法,他还认为这个 module 的整体设计就是由 NVIDIA 来选择的:
The design copied the nv_p2p api design directly into struct netgpu_functions and then aligned the rest of the parts to use it too. Yes, other GPU drivers could also be squeezed into this API, but if you'd never looked at the NVIDIA driver you'd never pick such a design. It is inherently disconnected from the [memory-management subsystem].
讨论冷却下来的时候,很明显可以看到这组 patch set 按照当前这种实现方法应该不会有机会合入了。还需要很多时间来把它改成基于 kernel 里的现有跨设备数据搬移机制上,例如 P2PDMA,DMA-buf subsystem 等等。现有的工作也许可以正常使用起来,但是很显然它走错了方向,是无法合入 mainline 的。
可惜的是,无论从哪个角度看,这个工作的目的都不是为了专门给 NVIDIA GPU 增加功能的。Lemon 看起来并不是 NVIDIA 的员工。这组 patch 里提供的是 Facebook 的邮件地址。只不过他们手边只有 NVIDIA 的 proprietary module,因此这个工作就变成围绕着 NVIDIA 设备来设计的了。如果一开始设计这个功能的时候就围绕着那些 free GPU driver 的话,所采取的那些决策就会走向不同的方向了,从而避免这些问题。
与此同时,为了今后大家能尽量避免犯这样的错误,Hellwig 提了一个 patch set 改动了 GPL-only symbol 的处理方式。当然碰巧这个改动也会让那些 proprietary module 更加难于开发。proprietary module 是无法使用 kernel 里那些以 GPL-only 方式 export 出来的 symbol 的,不过这里的保障措施上一直有一些漏洞。proprietary module 可以把自己分为两个部分,其中之一是一个很薄的一层专门用来作为 kernel 和 proprietary 代码的交互接口。只要这层代码是 GPL-licensed,那么就可以访问 GPL-only 的 symbol,从而导致 proprietary module 也就可以使用这些 symbol 了。
Hellwig 的 patch 并没有完全关闭这个漏洞,不过会让利用这个漏洞的过程更加困难。打上这个 patch 之后,任何从 proprietary module 也 import symbol 的 module 都会被标记成 proprietary,访问 GPL-only symbol 的时候会被拒绝。假如这个中间层 module 先访问了 GPL-only symbol,然后再 import proprietary module 的 symbol 的话,这个 import 动作就会被拒绝。这个新增限制就会导致 netgpu-NVIDIA interface module 无法加载,也就能防止今后大家再无意中这样实现代码了。不过它仍然还是有漏洞,如果中间层只是把它自己的 symbol 给 export 出去供 proprietary module 使用,但是并不会从 proprietary module 来 import 东西的话,就不受影响了。
自从 kernel 允许加载 module 开始,关于 proprietary module 的争论就没有停止过。2006 年时,开发社区很认真地讨论了是否把这种 module 彻底禁止。两年后,很多的 kernel developer 签署了一个联合声明认为 proprietary module 会对 Linux 用户、商业、以及整个生态系统都带来损害。不过直到现在,这些 module 仍然存在,看起来短期内也不会消失。像这次这种由于 proprietary module 导致很多工作走错了方向从而导致它几乎无法针对所有 GPU 来支持此功能的事情,恰恰说明了为什么社区认为这些 module 是有害的。
全文完
LWN文章遵循CC BY-SA 4.0许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~