6. 后续工作¶
此时,你已经遵循了前面给出的指导方针,并结合你自己的工程技能,发布了一系列完美的补丁。即使是经验丰富的内核开发人员也常犯的一个最大错误,就是认为他们的工作到此结束了。事实上,发布补丁标志着进入了流程的下一个阶段,可能还有相当多的工作要做。
很少有补丁在第一次发布时就完美无缺、毫无改进余地的。内核开发过程意识到了这一事实,因此,它高度重视对已发布代码的改进。作为该代码的作者,社区期望你与内核社区合作,确保你的代码达到内核的质量标准。不参与这个过程极有可能导致你的补丁无法被并入主线(mainline)。
6.1. 与评审人员合作¶
任何有分量的补丁在其他开发人员审查代码时都会引发大量的评论。对于许多开发人员来说,与评审人员合作可能是内核开发过程中最令人望而生畏的部分。不过,如果你牢记以下几点,事情就会变得容易得多:
如果你把补丁解释得很清楚,评审人员就会明白它的价值以及你为什么要费心编写它。但这种价值并不能阻止他们提出一个根本性的问题:五年或十年后,维护一个包含这段代码的内核会是什么样子?你可能会被要求做出的许多修改——从编码风格的调整到实质性的重写——都源于这样一种认知:即 Linux 在十年后仍将存在并处于开发中。
代码审查是一项辛苦的工作,而且是一项相对吃力不讨好的职业;人们记得是谁编写了内核代码,但对于审查代码的人来说,却没有什么持久的名声。因此,评审人员有时会变得脾气暴躁,尤其是当他们看到同样的错误被一遍又一遍地犯下时。如果你收到的评审意见看起来很愤怒、侮辱性或彻头彻尾的冒犯,请克制住以牙还牙的冲动。代码审查针对的是代码,而不是人,代码评审人员并没有对你进行人身攻击。
同样,代码评审人员也不是为了牺牲你的利益来推进其雇主的议程。内核开发人员通常期望在未来几年内继续从事内核工作,但他们也明白雇主可能会更换。几乎毫无例外,他们真心实意地在努力打造他们所能做出的最好的内核;他们并不是在试图给其雇主的竞争对手制造不便。
要做好心理准备,迎接那些看似愚蠢的编码风格修改请求,以及将部分代码提取到内核共享部分的请求。维护人员要做的工作之一就是保持代码外观的一致性。有时这意味着你驱动程序中用来绕过某个问题的巧妙黑客代码(hack),实际上需要变成一个通用的内核功能,以便下次使用。
归根结底,当评审人员向你发送评论时,你需要关注他们所提出的技术观察。不要让他们的表达方式或你自己的骄傲阻碍这一点。当你收到对补丁的评审意见时,请花时间去理解评审人员试图表达的意思。如果可能的话,修复评审人员要求你修复的问题。并回复评审人员:感谢他们,并说明你将如何回答他们的问题。
请注意,你不必同意评审人员建议的每一项修改。如果你认为评审人员误解了你的代码,请解释实际情况。如果你对建议的修改有技术上的反对意见,请描述出来并为你的解决方案辩护。如果你的解释合情合理,评审人员会接受它们。然而,如果你的解释证明不够有说服力,特别是当其他人开始赞同评审人员时,请花点时间重新考虑。人们很容易被自己针对某个问题的解决方案蒙蔽双眼,甚至意识不到某些地方从根本上出了问题,或者你根本没有解决正确的问题。
安德鲁·莫顿(Andrew Morton)曾建议,每一条未能促成代码修改的评审意见,都应该转化为额外的代码注释;这可以帮助未来的评审人员避免再次遇到最初提出的那些问题。
一个致命的错误是忽视评审意见,寄希望于它们会自行消失。它们是不会消失的。如果你在没有回应前一次收到的评论的情况下重新发布代码,你可能会发现你的补丁将一事无成。
说到重新发布代码:请记住,评审人员不会记得你上一次发布的代码的所有细节。因此,提醒评审人员注意以前提出的问题以及你是如何处理它们的,总是一个好主意;补丁的修改日志(changelog)是放置这类信息的绝佳地方。评审人员不应该去翻找邮件列表存档来熟悉上一次说过的话;如果你能帮他们顺利起步,当他们重新审视你的代码时,心情会更好。
如果你已经尽力把所有事情都做对了,但事情仍然毫无进展怎么办?大多数技术分歧都可以通过讨论来解决,但有时总得有人做出决定。如果你真诚地认为这个决定的方向对你很不公正,你总是可以尝试向更高层的权威申诉。截至本文撰写时,这个更高层的权威往往是安德鲁·莫顿(Andrew Morton)。安德鲁在内核开发社区中享有极高的威望;他经常能够打破看似陷入绝境的僵局。不过,向安德鲁申诉不能轻率行事,也不能在探讨完所有其他替代方案之前进行。当然,还要记住,他也可能不同意你的看法。
6.2. 接下来会发生什么¶
如果一个补丁被认为是对内核有益的添加,并且大部分评审问题已经得到解决,那么下一步通常是进入子系统维护人员的树(tree)。具体运作方式因子系统而异;每个维护人员都有自己的一套做事方式。特别是,可能会有多棵树——一棵可能专门用于计划在下一个合并窗口(merge window)中合并的补丁,另一棵则用于长期工作。
对于那些没有明显子系统树可用的区域的补丁(例如内存管理补丁),默认的树通常最终会是 -mm 树。影响多个子系统的补丁最终也可能会通过 -mm 树进行。
被纳入子系统树可以为补丁带来更高水平的可见性。现在,使用该树的其他开发人员将默认获得该补丁。子系统树通常也会向 linux-next 提供代码,使其内容对整个开发社区可见。此时,你很有可能会从新的一组评审人员那里获得更多评论;这些评论需要像上一轮一样进行回复。
在这一点上,根据你的补丁的性质,还可能会出现与其他人正在进行的工作发生冲突的情况。在最坏的情况下,严重的补丁冲突可能会导致某些工作被搁置,以便将剩余的补丁整理好并合并。其他时候,冲突解决将涉及与其他开发人员合作,并可能在不同的树之间移动一些补丁,以确保所有内容都能干净地应用。这项工作可能令人头疼,但知足常乐:在 linux-next 树出现之前,这些冲突通常只在合并窗口期间出现,并且必须仓促处理。现在它们可以在合并窗口打开之前从容解决。
总有一天,如果一切顺利,你会登录并看到你的补丁已经被合并到主线内核中了。恭喜!不过,在庆祝结束之后(并且你已将自己添加到 MAINTAINERS 文件中),值得记住一个重要的小事实:工作仍然没有完成。合并到主线会带来它自己的挑战。
首先,你的补丁的可见性再次增加了。可能会有新一轮来自以前不知道该补丁的开发人员的评论。忽略它们可能会很有诱惑力,因为你的代码是否被合并已经不成问题了。不过,请抵制这种诱惑;你仍然需要对有疑问或建议的开发人员做出响应。
不过,更重要的是:纳入主线会将你的代码交到更大的一群测试人员手中。即使你为尚未上市的硬件贡献了驱动程序,你也会惊讶于有多少人会将你的代码构建到他们的内核中。当然,有测试人员的地方,就会有错误报告。
最糟糕的错误报告是回归(regressions)。如果你的补丁引发了回归,你会发现有大量令人不舒服的目光盯着你;回归必须尽快修复。如果你不愿意或无法修复该回归(且也没有其他人为你代劳),你的补丁几乎肯定会在稳定期(stabilization period)被移除。除了否定了你为使补丁进入主线而做出的所有工作之外,因未能修复回归而被撤回补丁,很可能会让你在未来更难合并代码工作。
在处理完任何回归之后,可能还有其他普通的错误需要处理。稳定期是你修复这些错误并确保你的代码在主线内核版本中首次亮相尽可能稳固的最佳机会。所以,请回答错误报告,并在可能的情况下修复这些问题。这就是稳定期存在的意义;一旦旧补丁的问题得到妥善解决,你就可以开始编写很酷的新补丁了。
别忘了,还有其他一些里程碑也可能会产生错误报告:下一个主线稳定版本发布,知名发行商采用包含你补丁的内核版本时,等等。持续对这些报告做出响应是对自己工作保持基本自豪感的问题。不过,如果这还不足以构成动力,还值得考虑的是,开发社区会记住那些在代码合并后对代码失去兴趣的开发人员。当你下次发布补丁时,他们在评估时就会默认你以后不会来维护它。
6.3. 其他可能发生的事情¶
有一天,你可能会打开邮件客户端,看到有人发给你一个针对你的代码的补丁。毕竟,这就是将你的代码公开的优势之一。如果你同意该补丁,你可以将其转发给子系统维护人员(确保包含正确的 From: 行以便归属正确,并添加你自己的 signoff),或者发送 Acked-by: 回复,让原作者将其向上提交。
如果你不同意该补丁,请发送礼貌的回复解释原因。如果可能的话,告诉作者需要做出哪些修改才能使该补丁对你来说可以接受。合并遭到代码作者和维护人员反对的补丁会受到一定的阻力,但这种阻力是有限度的。如果你被视为无故阻挠优秀的工作,这些补丁最终还是会绕过你并进入主线。在 Linux 内核中,没有人对任何代码拥有绝对的否决权。也许除了 Linus 之外。
在极少数情况下,你可能会看到完全不同的情况:另一位开发人员针对你的问题发布了不同的解决方案。那时,这两个补丁中很可能有一个不会被合并,“我的补丁来得更早”不被认为是一个强有力的技术论据。如果其他人的补丁取代了你的补丁并进入了主线,实际上只有一个应对方法:为你的问题得到解决而感到高兴,然后继续你的工作。以这种方式被推开自己的工作可能会让人受伤和沮丧,但社区在忘记是谁的补丁真正被合并很久之后,仍会记住你的反应。