报告问题

简明指南(又称 TL;DR)

您是否在同一个稳定版或长期支持版系列的原版内核中遇到了回归?该版本是否仍在支持中?那么请在 LKMLLinux 稳定版邮件列表归档中搜索匹配的报告以参与讨论。如果没有找到,请安装 该系列的最新版本。如果问题仍然存在,请将其报告给稳定版邮件列表 (stable@vger.kernel.org),并抄送回归邮件列表 (regressions@lists.linux.dev);理想情况下,也请抄送相关子系统的维护者和邮件列表。

在所有其他情况下,请尽力猜测是哪个内核部分导致了问题。检查 MAINTAINERS 文件,了解其开发人员希望如何被告知问题,大多数情况下是通过电子邮件并抄送邮件列表。检查目标归档中是否存在匹配的报告;也请搜索 LKML 和网络。如果没有找到可以参与的报告,请安装 最新的主线内核。如果问题在那里仍然存在,请发送报告。

问题在那里已修复,但您也希望在仍在支持的稳定版或长期支持版系列中解决它?那么请安装该系列的最新版本。如果问题仍然存在,请搜索主线中修复它的更改,并检查是否正在进行反向移植或已被放弃;如果两者都不是,请向处理该更改的人员询问。

一般说明:如上所述安装和测试内核时,请确保它是原版(换句话说:未打补丁且未使用附加模块)。还要确保它在健康的运行环境中构建和运行,并且在问题发生之前没有被污染。

如果您同时面临多个 Linux 内核问题,请分别报告。在撰写报告时,请包含所有与问题相关的信息,例如所使用的内核和发行版。如果是回归问题,请在报告中抄送回归邮件列表 (regressions@lists.linux.dev)。另请尝试使用二分法找出罪魁祸首;如果成功,请包含其提交 ID 并抄送签发链中的所有人。

报告发出后,请回答提出的任何问题,并在力所能及的范围内提供帮助。这包括通过偶尔使用新版本进行重新测试并在之后发送状态更新来保持事情的进展。

如何向内核维护者报告问题的逐步指南

上述 TL;DR 大致说明了如何向 Linux 内核开发人员报告问题。对于已经熟悉向自由/开源软件 (FLOSS) 项目报告问题的人来说,这可能就是所需的一切。对于其他人,本节提供了更详细的逐步方法。它仍然力求简洁易读,并省略了许多细节;这些细节在逐步指南下方的参考章节中进行了更详细的解释。

注意:本节比 TL;DR 涵盖了更多方面,并且步骤顺序略有不同。这符合您的利益,可以确保您及早发现一个看似 Linux 内核问题的问题实际上是否由其他原因引起。因此,这些步骤有助于确保您在此过程中投入的时间最终不会白费。

  • 您是否在使用硬件或软件供应商提供的 Linux 内核时遇到问题?那么在几乎所有情况下,您最好停止阅读本文档,而是向您的供应商报告问题,除非您愿意自己安装最新的 Linux 版本。请注意,后者通常是追踪和修复问题所必需的。

  • 使用您喜欢的互联网搜索引擎粗略搜索现有报告;此外,请查看 Linux 内核邮件列表 (LKML) 的归档。如果您找到匹配的报告,请加入讨论,而不是发送新的报告。

  • 查看您正在处理的问题是否符合回归、安全问题或非常严重的问题:这些是“高优先级问题”,在接下来的某些步骤中需要特殊处理。

  • 确保导致您所遇到问题的不是内核的周边环境。

  • 创建新的备份,并准备好系统修复和恢复工具。

  • 确保您的系统不会通过动态构建额外的内核模块来增强其内核,像 DKMS 这样的解决方案可能会在您不知情的情况下在本地执行此操作。

  • 检查问题发生时您的内核是否被“污染”,因为导致内核设置此标记的事件可能正是您所遇到问题的原因。

  • 粗略记录如何重现问题。如果您同时处理多个问题,请为每个问题创建单独的笔记,并确保它们在全新启动的系统上独立运行。这是必要的,因为每个问题都需要单独报告给内核开发人员,除非它们之间存在强烈的关联。

  • 如果您在稳定版或长期支持版系列中遇到了回归(例如,从 5.10.4 更新到 5.10.5 时出现问题),请向下滚动到“处理稳定版和长期支持版内核系列中的回归”一节。

  • 找出似乎导致问题的驱动程序或内核子系统。查明其开发人员期望如何以及在哪里接收报告。注意:大多数情况下这不会是 bugzilla.kernel.org,因为问题通常需要通过邮件发送给维护者和公共邮件列表。

  • 彻底搜索相关 bug 跟踪器或邮件列表的归档,寻找可能与您问题匹配的报告。如果您找到任何内容,请加入讨论,而不是发送新的报告。

完成这些准备后,您现在将进入主要部分。

  • 除非您已经运行最新的“主线”Linux 内核,否则最好安装它以便进行报告。在某些情况下,使用最新的“稳定版”Linux 进行测试和报告是可以接受的替代方案;在合并窗口期间,这实际上可能是最好的方法,但在那个开发阶段,无论如何暂停几天您的努力可能是一个更好的主意。无论您选择哪个版本,理想情况下都应使用“原版”构建。忽视这些建议将大大增加您的报告被拒绝或忽略的风险。

  • 确保您刚刚安装的内核在运行时不会“污染”自己。

  • 使用您刚刚安装的内核重现问题。如果问题没有出现,请向下滚动到仅在稳定版和长期支持版内核中出现的问题的说明。

  • 优化您的笔记:尝试找到并写下重现问题的最直接方法。确保最终结果包含所有重要细节,同时对于初次听说的人来说易于阅读和理解。如果您在此过程中学到了什么,请考虑再次搜索有关该问题的现有报告。

  • 如果您的故障涉及“panic”、“Oops”、“warning”或“BUG”,请考虑解码内核日志以找到触发错误的源代码行。

  • 如果您的问题是回归,请尽量缩小问题引入的时间范围。

  • 开始撰写报告,详细描述问题。务必提及几点:您为重现问题而安装的最新内核版本、所使用的 Linux 发行版以及您关于如何重现问题的笔记。理想情况下,请将内核的构建配置 (.config) 和 dmesg 的输出发布到网上并提供链接。包含或上传所有其他可能相关的信息,例如 Oops 的输出/截图或 lspci 的输出。完成这部分主要内容后,在其上方插入一个长度适中的段落,快速概述问题和影响。在此之上,再添加一个简短描述问题的句子,吸引人们继续阅读。现在,给报告一个描述性更短的标题或主题。然后您就可以按照 MAINTAINERS 文件告诉您的方式发送或提交报告了,除非您正在处理“高优先级问题”之一:这些问题需要特殊处理,具体说明见下方的“高优先级问题的特殊处理”一节。

  • 等待回应,并持续跟进,直到您能接受某种结果。因此,请公开并及时回应任何询问。测试提议的修复。进行主动测试:至少对新主线版本的每一个第一个发布候选版 (RC) 进行重新测试,并报告您的结果。如果事情停滞不前,请发送友善的提醒。如果您没有得到任何帮助或结果不尽如人意,请尝试自助。

在稳定版和长期支持版内核系列中报告回归

如果您遵循了上述流程并在稳定版或长期支持版内核系列中的回归问题处被引导到这里,那么本小节是为您准备的。如果您从 5.10.4 更新到 5.10.5 时出现问题(从 5.9.15 切换到 5.10.5 不符合条件),则您遇到了此类问题。开发人员希望尽快修复此类回归,因此有一个简化的报告流程。

  • 检查内核开发人员是否仍在维护您所关心的 Linux 内核版本系列:访问 kernel.org 的首页,并确保它提到了该特定版本系列的最新版本,且没有“[EOL]”标记。

  • 检查 Linux 稳定版邮件列表 的归档,查找现有报告。

  • 将该特定版本系列的最新版本作为原版内核安装。确保此内核未被污染且问题仍然存在,因为问题可能已在那里修复。如果您最初是在供应商内核中注意到此问题,请检查已知可正常工作的最后一个版本的原版构建是否也运行良好。

  • 向 Linux 稳定版邮件列表 (stable@vger.kernel.org) 发送一份简短的问题报告,并抄送 Linux 回归邮件列表 (regressions@lists.linux.dev);如果您怀疑是某个特定子系统引起的问题,请抄送其维护者和其邮件列表。大致描述问题,并理想地解释如何重现。提及出现问题的第一个版本和正常工作的最后一个版本。然后等待进一步的指示。

下面的参考章节更详细地解释了这些步骤。

报告仅在旧版内核系列中出现的问题

如果您尝试了如上所述的最新主线内核,但未能重现您的问题;同时您希望在仍在支持的稳定版或长期支持版系列或基于这些版本定期重构的供应商内核中看到问题得到修复。如果是这样,请遵循以下步骤。

  • 请做好准备,接下来的几个步骤可能无法在旧版本中解决问题:修复可能太大或风险太高,无法反向移植到那里。

  • 执行上面“处理稳定版和长期支持版内核系列中的回归”一节的前三个步骤。

  • 在 Linux 内核版本控制系统中搜索在主线中修复该问题的更改,因为其提交消息可能会告诉您该修复是否已计划进行反向移植。如果没有找到,请在适当的邮件列表中搜索讨论此类问题或同行评审可能修复的帖子;然后检查讨论,看看该修复是否被认为不适合反向移植。如果根本没有考虑反向移植,请加入最新的讨论,询问是否有可能。

  • 前面的步骤之一应该能找到解决方案。如果行不通,请向似乎导致问题的子系统的维护者寻求建议;抄送该特定子系统的邮件列表以及稳定版邮件列表。

下面的参考章节更详细地解释了这些步骤。

参考章节:向内核维护者报告问题

上面详细的指南简要概述了所有主要步骤,这对于大多数人来说应该足够了。但有时即使是经验丰富的用户也可能会想知道如何实际执行其中一个步骤。这就是本节的目的,它将提供有关上述每个步骤的更多详细信息。将此视为参考文档:可以从头到尾阅读。但它主要用于快速浏览,也是一个查找如何实际执行这些步骤的详细信息的地方。

在深入细节之前的一些一般性建议

  • Linux 内核开发人员深知这个过程很复杂,并且比其他自由/开源软件项目要求更多。我们很乐意使其更简单。但这需要在多个地方进行工作以及一些基础设施,这将需要持续维护;目前没有人主动承担这项工作,所以目前情况就是如此。

  • 与某些供应商的保修或支持合同,并不能让您有权向上游 Linux 内核社区的开发人员请求修复:此类合同完全超出 Linux 内核、其开发社区和本文档的范围。因此,在这种情况下,您不能要求此类合同保证的任何内容,即使处理该问题的开发人员为相关供应商工作也是如此。如果您想主张自己的权利,请使用供应商的支持渠道。这样做时,您可能希望提及您希望看到问题在上游 Linux 内核中得到修复;通过说明这是确保最终修复会被所有 Linux 发行版采纳的唯一方式来激励他们。

  • 如果您以前从未向自由/开源软件项目报告过问题,您应该考虑阅读 《如何有效报告 Bug》《提问的智慧》《如何提出好问题》

排除这些之后,下面是关于如何正确向 Linux 内核开发人员报告问题的详细信息。

确保您使用的是上游 Linux 内核

您是否在使用硬件或软件供应商提供的 Linux 内核时遇到问题?那么在几乎所有情况下,您最好停止阅读本文档,而是向您的供应商报告问题,除非您愿意自己安装最新的 Linux 版本。请注意,后者通常是追踪和修复问题所必需的。

和大多数程序员一样,Linux 内核开发人员不喜欢花时间处理那些甚至不会在他们当前代码中发生的问题报告。这只是浪费大家的时间,特别是您的时间。不幸的是,在内核方面这种情况很容易发生,并常常导致双方沮丧。这是因为几乎所有预装在设备(计算机、笔记本电脑、智能手机、路由器等)上的基于 Linux 的内核以及大多数由 Linux 发行版发布的内核都与 kernel.org 分发的官方 Linux 内核相去甚远:这些供应商的内核通常在 Linux 开发的角度来看非常古老,或被大量修改,常常两者兼有。

这些供应商内核大多不适合向 Linux 内核开发人员报告问题:您在使用其中一个内核时遇到的问题可能在数月甚至数年前就已被 Linux 内核开发人员修复;此外,供应商的修改和增强可能导致您所遇到的问题,即使它们看起来很小或完全不相关。这就是为什么您应该向供应商报告这些内核的问题。其开发人员应该研究该报告,如果发现是上游问题,应直接在上游修复或将报告转发到上游。实际上,这通常行不通,或者可能不是您想要的。因此,您可能需要考虑自行安装最新的 Linux 内核核心来绕过供应商。如果这对您来说是一个选择,请继续此过程,因为本指南稍后会解释如何在排除其他潜在问题原因后执行此操作。

请注意,上一段以“大多”开头,因为有时开发人员实际上愿意处理有关供应商内核中出现的问题报告。他们最终是否处理,很大程度上取决于开发人员和所涉问题。如果发行版仅对基于最新 Linux 版本的内核进行了少量修改,您的机会就相当大;例如,这通常适用于 Debian GNU/Linux Sid 或 Fedora Rawhide 发布的上游主线内核。一些开发人员也会接受关于发布最新稳定版内核的发行版中的问题报告,只要它们只是略微修改过;例如,Arch Linux、常规 Fedora 版本和 openSUSE Tumbleweed 通常就是这种情况。但请记住,您最好使用主线 Linux 并避免在此过程中使用稳定版内核,如“安装新内核进行测试”一节中更详细地概述的那样。

显然,您可以随意忽略所有这些建议,并向上游 Linux 开发人员报告旧的或经过大量修改的供应商内核的问题。但请注意,这些报告通常会被拒绝或忽略,因此请自行斟酌。但总比完全不报告问题要好:有时此类报告会直接或间接地帮助问题随着时间的推移得到修复。

搜索现有报告,首次运行

使用您喜欢的互联网搜索引擎粗略搜索现有报告;此外,请查看 Linux 内核邮件列表 (LKML) 的归档。如果您找到匹配的报告,请加入讨论,而不是发送新的报告。

报告一个别人已经提出的问题,通常会浪费所有相关人员的时间,尤其是作为报告者的您。因此,彻底检查是否有人已经报告了该问题符合您自身的利益。在此过程的此步骤中,进行粗略搜索是可以的:一旦您知道问题需要报告到何处,后续步骤会告诉您进行更详细的搜索。尽管如此,请不要急于执行报告流程的此步骤,它可以为您节省时间和麻烦。

首先,简单地使用您喜欢的搜索引擎在互联网上搜索。之后,搜索 Linux 内核邮件列表 (LKML) 归档

如果结果泛滥,请考虑告诉您的搜索引擎将搜索时间范围限制在过去一个月或一年。无论您在哪里搜索,请务必使用好的搜索词;也要尝试多次更改它们。这样做时,请尝试从他人的角度看待问题:这将帮助您想出其他可以用作搜索词的词语。此外,确保不要一次使用过多的搜索词。记住,搜索时可以包含或不包含内核驱动程序名称或受影响硬件组件名称等信息。但其确切的品牌名称(例如“华硕 ROG 猛禽 Radeon RX 5700 XT Gaming OC”)通常帮助不大,因为它过于具体。相反,尝试使用像型号系列(Radeon 5700 或 Radeon 5000)和主芯片代号(“Navi”或“Navi10”)这样的搜索词,可以带或不带其制造商(“AMD”)。

如果您发现有关您问题的现有报告,请加入讨论,因为您可能能够提供有价值的额外信息。即使修复已在准备中或已进入最后阶段,这也很重要,因为开发人员可能会寻找能够提供额外信息或测试拟议修复的人。请跳转到“报告发出后的职责”一节,了解如何正确参与的详细信息。

请注意,搜索 bugzilla.kernel.org 也可能是个好主意,因为它可能会提供有价值的见解或发现匹配的报告。如果您找到后者,请记住:大多数子系统期望在不同地方接收报告,如下文“检查您需要向何处报告问题”一节所述。因此,负责该问题的开发人员可能甚至不知道该 bugzilla 工单。因此,请检查该工单是否已按本文档所述报告了问题,如果没有,请考虑报告。

高优先级问题?

查看您正在处理的问题是否符合回归、安全问题或非常严重的问题:这些是“高优先级问题”,在接下来的某些步骤中需要特殊处理。

Linus Torvalds 和主要的 Linux 内核开发人员希望尽快修复一些问题,因此存在“高优先级问题”,它们在报告过程中会略有不同地处理。三种情况符合条件:回归、安全问题和非常严重的问题。

如果某个应用程序或实际用例在某个 Linux 内核上运行良好,但在使用类似配置编译的较新版本上运行变差或完全无法运行,则您遇到了回归。文档 《报告回归》 更详细地解释了这一点。它还提供了许多其他有关回归的信息,您可能需要了解;例如,它解释了如何将您的问题添加到已跟踪回归列表中,以确保它不会被遗漏。

什么构成安全问题由您自行判断。在继续之前,请考虑阅读 《安全 Bug》,因为它提供了如何最好地处理安全问题的额外详细信息。

当发生完全不可接受的糟糕情况时,问题就是“非常严重的问题”。例如,当 Linux 内核损坏其处理的数据或损害其运行的硬件时,就是这种情况。当内核突然停止工作并显示错误消息(“内核 panic”)或完全没有任何告别信息时,您也在处理一个严重问题。注意:不要混淆“panic”(内核自行停止的致命错误)和“Oops”(可恢复错误),因为后者发生后内核仍会继续运行。

确保健康的运行环境

确保导致您所遇到问题的不是内核的周边环境。

看起来很像内核问题的问题有时是由构建或运行时环境引起的。很难完全排除这个问题,但您应该将其最小化。

  • 在构建内核时使用经过验证的工具,因为编译器或 binutils 中的错误可能导致生成的内核行为异常。

  • 确保您的计算机组件在其设计规范内运行;这对于主处理器、主内存和主板尤为重要。因此,在面对潜在的内核问题时,请停止降压或超频。

  • 尽量确保不是有故障的硬件导致了您的问题。例如,损坏的主内存可能导致许多问题,表现为看起来像内核问题。

  • 如果您正在处理文件系统问题,您可能需要使用 fsck 检查相关文件系统,因为它可能以导致意外内核行为的方式损坏。

  • 处理回归问题时,请确保不是其他与内核更新同时发生的变化导致了问题。例如,问题可能由同时更新的其他软件引起。也可能发生硬件组件在您首次重启进入新内核时恰好损坏的情况。更新系统 BIOS 或更改 BIOS 设置中的某些内容也可能导致看起来很像内核回归的问题。

为紧急情况做准备

创建新的备份,并准备好系统修复和恢复工具。

提醒:您正在处理计算机,它们有时会做一些意想不到的事情,特别是当您操作其操作系统的内核等关键部分时。这正是您在此过程中将要做的事情。因此,请务必创建新的备份;同时确保您手头有所有修复或重新安装操作系统所需的工具,以及恢复备份所需的一切。

确保您的内核未被增强

确保您的系统不会通过动态构建额外的内核模块来增强其内核,像 DKMS 这样的解决方案可能会在您不知情的情况下在本地执行此操作。

如果您的内核以任何方式被增强,您的报告被忽略或拒绝的风险会大大增加。这就是为什么您应该删除或禁用 akmods 和 DKMS 等机制:这些机制会自动构建附加内核模块,例如当您安装新的 Linux 内核或首次启动它时。同时删除它们可能已安装的任何模块。然后重启再继续。

请注意,您可能没有意识到您的系统正在使用这些解决方案之一:当您安装 Nvidia 的专有图形驱动程序、VirtualBox 或其他需要 Linux 内核之外模块支持的软件时,它们通常会被静默设置。这就是为什么您可能需要卸载包含此类软件的软件包,以清除任何第三方内核模块。

检查“污染”标记

检查问题发生时您的内核是否被“污染”,因为导致内核设置此标记的事件可能正是您所遇到问题的原因。

当发生一些可能导致完全不相关的后续错误的情况时,内核会用一个“污染”(taint)标志来标记自身。如果您的内核被污染,您面临的问题可能就是此类错误。这就是为什么在投入更多时间到此流程之前,您应该尽早排除这种情况。这是此步骤在此的唯一原因,因为此流程稍后会告诉您安装最新的主线内核;届时您将需要再次检查污染标志,因为那时它才重要,因为报告将关注的是该内核。

在一个正在运行的系统上,检查内核是否被污染很容易:如果 cat /proc/sys/kernel/tainted 返回“0”,则内核未被污染,一切正常。在某些情况下,检查该文件是不可能的;这就是为什么内核在报告内部问题(“内核错误”)、可恢复错误(“内核 Oops”)或在停止操作前不可恢复错误(“内核 panic”)时,也会提及污染状态。在其中之一发生时打印的错误消息顶部附近查找,并搜索以“CPU:”开头的行。如果内核在发现问题时未被污染,它应该以“Not tainted”结尾;如果您看到“Tainted:”后跟着一些空格和一些字母,则它已被污染。

如果您的内核被污染,请查阅受污染的内核以找出原因。尝试消除原因。通常它由以下三件事之一引起:

  1. 发生了一个可恢复错误(一个“内核 Oops”),并且内核污染了自身,因为内核知道此后可能会出现奇怪的行为。在这种情况下,请检查您的内核或系统日志,并查找以以下内容开头的片段:

    Oops: 0000 [#1] SMP
    

    这是自启动以来的第一次 Oops,正如括号中的“#1”所示。此后发生的每个 Oops 和任何其他问题都可能是该第一次 Oops 的后续问题,即使两者看起来完全不相关。通过消除第一次 Oops 的原因并在之后重现问题来排除这种情况。有时简单地重启就足够了,有时更改配置后重启可以消除 Oops。但在此过程的此时不要投入太多时间,因为 Oops 的原因可能在您稍后将在此过程中安装的更新的 Linux 内核版本中已经修复。

  2. 您的系统使用安装了自己内核模块的软件,例如 Nvidia 的专有图形驱动程序或 VirtualBox。当内核从外部源(即使它们是开源的)加载此类模块时,它会污染自身:它们有时会在不相关的内核区域引起错误,从而可能导致您面临的问题。因此,当您想向 Linux 内核开发者报告问题时,您必须阻止这些模块加载。大多数情况下,最简单的方法是:暂时卸载此类软件,包括它们可能已安装的任何模块。然后重启。

  3. 当内核加载位于 Linux 内核源代码的 staging 目录中的模块时,它也会污染自身。这是一个特殊的代码区域(主要是驱动程序),尚未满足正常的 Linux 内核质量标准。当您报告此类模块的问题时,如果内核被污染,这显然是可以接受的;只需确保相关模块是污染的唯一原因。如果问题发生在不相关的区域,请重启并通过指定 foo.blacklist=1 作为内核参数(将“foo”替换为相关模块的名称)来暂时阻止模块加载。

记录如何重现问题

粗略记录如何重现问题。如果您同时处理多个问题,请为每个问题创建单独的笔记,并确保它们在全新启动的系统上独立运行。这是必要的,因为每个问题都需要单独报告给内核开发人员,除非它们之间存在强烈的关联。

如果您同时处理多个问题,则必须分别报告它们,因为它们可能由不同的开发人员处理。在一个报告中描述各种问题也使其他人很难将其拆分。因此,仅当问题非常紧密地纠缠在一起时,才将它们合并到一个报告中。

此外,在报告过程中,您将不得不测试问题是否发生在其他内核版本上。因此,如果您确切知道如何在全新启动的系统上快速重现问题,这将使您的工作更轻松。

注意:报告只发生过一次的问题通常是徒劳的,因为它们可能是由宇宙辐射导致的位翻转引起的。这就是为什么您应该在继续之前通过重现问题来排除这种情况。如果您经验足够丰富,可以区分由于硬件故障导致的一次性错误与极少发生且难以重现的内核问题,请随意忽略此建议。

稳定版或长期支持版内核中的退步

如果您在稳定版或长期支持版系列中遇到了回归(例如,从 5.10.4 更新到 5.10.5 时出现问题),请向下滚动到“处理稳定版和长期支持版内核系列中的回归”一节。

Linux 开发者非常希望修复稳定版和长期支持版内核版本线中的退步,因为此类问题比主要开发分支中的退步更不受欢迎,因为它们会迅速影响很多人。因此,开发者希望尽快了解此类问题,因此有简化的流程来报告它们。请注意,较新内核版本线中的退步(例如从 5.9.15 切换到 5.10.5 时出现问题)不符合条件。

检查您需要在何处报告您的问题

找出似乎导致问题的驱动程序或内核子系统。查明其开发人员期望如何以及在哪里接收报告。注意:大多数情况下这不会是 bugzilla.kernel.org,因为问题通常需要通过邮件发送给维护者和公共邮件列表。

将您的报告发送给正确的人至关重要,因为 Linux 内核是一个庞大的项目,其大多数开发人员只熟悉其中的一小部分。例如,相当多的程序员只关心一个驱动程序,例如一个 Wi-Fi 芯片的驱动程序;其开发者可能对远程或不相关的“子系统”的内部结构知之甚少或一无所知,例如 TCP 栈、PCIe/PCI 子系统、内存管理或文件系统。

问题是:Linux 内核缺乏一个中央错误跟踪器,您只需提交您的问题即可将其发送给需要了解的开发者。这就是为什么您必须自己找到报告问题的正确位置和方式。您可以在脚本的帮助下做到这一点(见下文),但它主要针对内核开发者和专家。对于其他人来说,MAINTAINERS 文件是更好的选择。

如何阅读 MAINTAINERS 文件

为了说明如何使用MAINTAINERS文件,让我们假设您的笔记本电脑中的 Wi-Fi 在更新内核后突然出现异常。在这种情况下,很可能是 Wi-Fi 驱动程序的问题。显然,它也可能是其所基于的一些代码,但除非您怀疑类似的情况,否则请坚持认为是驱动程序的问题。如果确实是其他问题,驱动程序的开发者会联系到正确的人。

遗憾的是,目前没有一种通用且简单的方法来检查哪个代码驱动着特定的硬件组件。

例如,在 Wi-Fi 驱动程序出现问题时,您可能需要查看 lspci -k 的输出,因为它列出了 PCI/PCIe 总线上的设备以及驱动它的内核模块。

[user@something ~]$ lspci -k
[...]
3a:00.0 Network controller: Qualcomm Atheros QCA6174 802.11ac Wireless Network Adapter (rev 32)
  Subsystem: Bigfoot Networks, Inc. Device 1535
  Kernel driver in use: ath10k_pci
  Kernel modules: ath10k_pci
[...]

但如果您的 Wi-Fi 芯片通过 USB 或其他内部总线连接,则此方法将不起作用。在这些情况下,您可能需要检查您的 Wi-Fi 管理器或 ip link 的输出。查找有问题的网络接口的名称,它可能类似于“wlp58s0”。这个名称可以这样使用来找到驱动它的模块:

[user@something ~]$ realpath --relative-to=/sys/module/ /sys/class/net/wlp58s0/device/driver/module
ath10k_pci

如果这些技巧没有让您取得任何进展,请尝试在网上搜索如何缩小到相关驱动程序或子系统。如果您不确定是哪个:只需尽力猜测,如果您猜错了,会有人帮助您。

一旦您知道驱动程序或子系统,您就会想在 MAINTAINERS 文件中搜索它。在“ath10k_pci”的情况下,您将找不到任何东西,因为名称太具体了。有时您需要在网上寻求帮助;但在这样做之前,尝试在搜索 MAINTAINERS 文件时使用稍短或修改过的名称,这样您可能会找到类似以下内容:

QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
Mail:          A. Some Human <shuman@example.com>
Mailing list:  ath10k@lists.infradead.org
Status:        Supported
Web-page:      https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
SCM:           git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
Files:         drivers/net/wireless/ath/ath10k/

请注意:如果您阅读 Linux 源代码树根目录下的纯 MAINTAINERS 文件,行描述将是缩写。“Mail:”例如将是“M:”,“Mailing list:”将是“L”,“Status:”将是“S:”。文件顶部附近的一个部分解释了这些和其他缩写。

首先查看“Status”行。理想情况下,它应该是“Supported”或“Maintained”。如果它显示“Obsolete”,那么您正在使用一些已被新解决方案取代的过时方法,您需要切换到新方法。有时代码只有在有动力时才会有人提供“Odd Fixes”。而“Orphan”则表示您完全不走运,因为代码已经没有人维护了。这只剩下这些选择:想办法接受这个问题,自己修复它,或者找到一位程序员愿意修复它。

检查状态后,查找以“bugs:”开头的行:它会告诉您在哪里找到特定子系统的错误跟踪器来提交您的问题。上面的示例没有这样的行。大多数部分都是这种情况,因为 Linux 内核开发完全通过邮件驱动。很少有子系统使用错误跟踪器,并且其中只有少数依赖 bugzilla.kernel.org。

在这种和许多其他情况下,您因此必须改为寻找以“Mail:”开头的行。这些行提到了特定代码维护者的姓名和电子邮件地址。此外,还要查找以“Mailing list:”开头的行,它告诉您该代码开发的公共邮件列表。您的报告稍后需要通过邮件发送到这些地址。此外,对于所有通过电子邮件发送的问题报告,请确保将 Linux 内核邮件列表 (LKML) <linux-kernel@vger.kernel.org> 添加到抄送。稍后通过邮件发送问题报告时,不要遗漏任何一个邮件列表!维护者都很忙,可能会将一些工作留给子系统特定列表上的其他开发人员;而 LKML 很重要,它提供了一个可以找到所有问题报告的地方。

借助脚本查找维护者

对于手头有 Linux 源代码的人来说,还有第二种方法可以找到合适的报告地点:脚本“scripts/get_maintainer.pl”,它试图找到所有要联系的人。它查询 MAINTAINERS 文件,并且需要使用相关源代码的路径进行调用。对于作为模块编译的驱动程序,通常可以使用如下命令找到它:

$ modinfo ath10k_pci | grep filename | sed 's!/lib/modules/.*/kernel/!!; s!filename:!!; s!\.ko\(\|\.xz\)!!'
drivers/net/wireless/ath/ath10k/ath10k_pci.ko

将其中一部分传递给脚本:

$ ./scripts/get_maintainer.pl -f drivers/net/wireless/ath/ath10k*
Some Human <shuman@example.com> (supporter:QUALCOMM ATHEROS ATH10K WIRELESS DRIVER)
Another S. Human <asomehuman@example.com> (maintainer:NETWORKING DRIVERS)
ath10k@lists.infradead.org (open list:QUALCOMM ATHEROS ATH10K WIRELESS DRIVER)
linux-wireless@vger.kernel.org (open list:NETWORKING DRIVERS (WIRELESS))
netdev@vger.kernel.org (open list:NETWORKING DRIVERS)
linux-kernel@vger.kernel.org (open list)

不要将您的报告发送给他们所有人。将其发送给维护者,脚本称之为“支持者:”;此外,还要抄送代码最具体的邮件列表以及 Linux 内核邮件列表 (LKML)。在这种情况下,您需要将报告发送给“Some Human <shuman@example.com>”,并抄送 ‘ath10k@lists.infradead.org’ 和 ‘linux-kernel@vger.kernel.org’。

注意:如果您使用 git 克隆了 Linux 源代码,您可能需要再次使用 --git 调用 get_maintainer.pl。脚本 then will look at the commit history to find which people recently worked on the code in question, as they might be able to help. But use these results with care, as it can easily send you in a wrong direction. That for example happens quickly in areas rarely changed (like old or unmaintained drivers): sometimes such code is modified during tree-wide cleanups by developers that do not care about the particular driver at all。

搜索现有报告,第二次运行

彻底搜索相关 bug 跟踪器或邮件列表的归档,寻找可能与您问题匹配的报告。如果您找到任何内容,请加入讨论,而不是发送新的报告。

正如前面提到的:报告他人已经提出的问题通常会浪费所有相关人员的时间,尤其是您作为报告者。这就是为什么您应该再次搜索现有报告,现在您知道它们需要报告到哪里了。如果是邮件列表,您通常会在 lore.kernel.org 上找到其存档。

但有些列表托管在不同的地方。例如,上一步中用作示例的 ath10k WiFi 驱动程序就是这种情况。但您通常可以在网上轻松找到这些列表的存档。例如,搜索“archive ath10k@lists.infradead.org”将引导您进入ath10k 邮件列表的信息页面,该页面顶部链接到其列表存档。遗憾的是,这个和不少其他列表缺少搜索存档的方式。在这种情况下,请使用常规的互联网搜索引擎,并在您的搜索词中添加类似“site:lists.infradead.org/pipermail/ath10k/”的内容,这将把结果限制在该 URL 的存档中。

此时再次检查互联网、LKML 以及可能存在的 bugzilla.kernel.org 也是明智之举。如果您的报告需要提交到错误跟踪器,您可能还需要检查子系统的邮件列表存档,因为有人可能只在那里报告了它。

有关如何搜索以及如果找到匹配报告如何处理的详细信息,请参阅上面的“搜索现有报告,第一次运行”。

在报告过程的这一步不要着急:花费 30 到 60 分钟甚至更多时间可以为您和他人节省大量时间和麻烦。

安装新的内核进行测试

除非您已经在运行最新的“主线”Linux 内核,否则最好安装它以进行报告。在某些情况下,使用最新的“稳定版”Linux 进行测试和报告是可接受的替代方案;在合并窗口期间,这实际上可能是最佳方法,但在该开发阶段,无论如何,暂停您的努力几天可能是一个更好的主意。无论您选择哪个版本,理想情况下都使用“原版”构建。忽略这些建议将大大增加您的报告被拒绝或忽略的风险。

正如第一步的详细解释中已经提到的:像大多数程序员一样,Linux 内核开发人员不喜欢花时间处理甚至在当前代码中都没有发生的问题报告。这只是浪费每个人的时间,尤其是您的时间。这就是为什么确认问题在报告之前仍然存在于最新的上游代码中符合每个人的利益。您可以自由地忽略此建议,但如前所述:这样做会大大增加您的问​​题报告被拒绝或简单地忽略的风险。

在内核范围内,“最新上游”通常意味着:

  • 安装主线内核;最新稳定版内核可能是一个选项,但大多数情况下最好避免。长期支持内核(有时称为“LTS 内核”)在此过程的此时不适用。下一小节将更详细地解释所有这些。

  • 接下来的小节描述了获取和安装此类内核的方法。它还概述了使用预编译内核是可以的,但最好是原版,这意味着:它是使用直接从 kernel.org 获取的 Linux 源代码构建的,并且没有任何修改或增强。

选择正确的版本进行测试

前往 kernel.org 找出您想用于测试的版本。忽略那个写着“最新版本”的大黄色按钮,向下一点看表格。在它的顶部,您会看到一行以 mainline 开头,它大多数时候会指向一个版本号类似“5.8-rc2”的预发布版。如果是这种情况,您将需要使用这个主线内核进行测试,因为所有修复都必须首先应用到那里。不要让那个“rc”吓到您,这些“开发内核”相当可靠——而且您已经按照上面的指示做好了备份,不是吗?

大约每九到十周就有两次,主线版本可能会指向一个正式发布版,版本号类似“5.7”。如果发生这种情况,请考虑暂停报告过程,直到下一个版本(5.8-rc1)的第一个预发布版出现在 kernel.org 上。这是因为 Linux 开发周期正处于其为期两周的“合并窗口”期。大部分更改和所有侵入性更改都在此期间合并到下一个版本。在此期间使用主线版本风险稍大。内核开发人员那时通常也相当忙碌,可能没有空闲时间处理问题报告。在合并窗口期间应用的众多更改之一也很有可能修复您面临的问题;这就是为什么您迟早需要使用更新的内核版本重新测试,正如本文档后面“报告发出后的职责”一节中概述的那样。

这就是为什么等待合并窗口结束可能是有意义的。但如果您处理的是不应该等待的事情,请不要这样做。在这种情况下,请考虑通过 git 获取最新的主线内核(见下文)或使用 kernel.org 上提供的最新稳定版本。如果主线版本由于某种原因目前对您不起作用,使用它也是可以接受的。总的来说:用它来重现问题也比完全不报告问题要好。

在合并窗口之外,最好避免使用最新的稳定版内核,因为所有修复都必须首先应用到主线版本。这就是检查最新的主线内核如此重要的原因:任何您希望在旧版本线中修复的问题都需要首先在主线版本中修复,然后才能反向移植,这可能需要几天或几周的时间。另一个原因:您所希望的修复可能对反向移植来说太困难或风险太大;因此,再次报告问题不太可能改变任何事情。

这些方面也是长期支持内核(有时称为“LTS 内核”)不适用于报告过程此部分的原因:它们与当前代码相距太远。因此,请先测试主线版本并继续执行后续过程:如果问题在主线版本中未发生,它将指导您如何在旧版本线中修复它(如果该修复程序在考虑范围内)。

如何获取新的 Linux 内核

使用预编译内核:这通常是测试最快、最简单、最安全的方式——特别是如果您不熟悉 Linux 内核。问题是:大多数由发行版或附加仓库提供的内核都是从修改过的 Linux 源代码构建的。因此它们不是原版的,因此通常不适合测试和问题报告:这些更改可能会导致您面临的问题或以某种方式影响它。

但如果您使用的是流行的 Linux 发行版,那您很幸运:对于其中不少发行版,您会在网上找到包含最新主线或稳定 Linux 的原版内核软件包的仓库。使用这些软件包是完全可以的,只需确保仓库描述中说明它们是原版的或者至少接近原版。此外,还要确保软件包包含 kernel.org 上提供的最新版本。如果软件包的版本比一周还旧,它们可能就不合适了,因为新的主线和稳定内核通常至少每周发布一次。

请注意,您可能需要在以后手动构建自己的内核:这有时是调试或测试修复所必需的,如本文档后面所述。另请注意,预编译内核可能缺少调试符号,这些符号在内核打印 panic、Oops、警告或 BUG 消息时需要解码;如果您计划解码这些,您最好自己编译一个内核(有关详细信息,请参阅本小节末尾和题为“解码故障消息”的部分)。

使用 git:开发人员和熟悉 git 的经验丰富的 Linux 用户通常最好直接从 kernel.org 上的官方开发仓库获取最新的 Linux 内核源代码。这些源代码可能比最新的主线预发布版稍早一些。不用担心:它们和正式的预发布版一样可靠,除非内核的开发周期目前正处于合并窗口中间。但即使如此,它们也相当可靠。

常规方式:不熟悉 git 的人通常最好从 kernel.org 下载 tarball 格式的源代码。

这里不描述如何实际构建内核,因为许多网站已经解释了必要的步骤。如果您是新手,可以考虑遵循那些建议使用 make localmodconfig 的操作指南,因为它会尝试获取您当前内核的配置,然后尝试为您的系统进行一些调整。这并不会让生成的内核变得更好,但可以更快地编译。

注意:如果您遇到内核的 panic、Oops、warning 或 BUG,请在配置内核时尝试启用 CONFIG_KALLSYMS。此外,还要启用 CONFIG_DEBUG_KERNEL 和 CONFIG_DEBUG_INFO;后者是两者中相关的那个,但只有启用前者才能达到。请注意,CONFIG_DEBUG_INFO 会相当大地增加构建内核所需的存储空间。但这值得,因为这些选项稍后将允许您精确定位触发您问题的确切代码行。下面的“解码故障消息”部分将更详细地解释这一点。

但请记住:如果问题难以重现,请务必记录下遇到的问题。发送一份未解码的报告总比完全不报告问题要好。

检查“污染”标志

确保您刚刚安装的内核在运行时不会“污染”自己。

正如上面已经详细概述的:当发生可能导致完全不相关的后续错误的情况时,内核会设置一个“污染”标志。这就是为什么您需要检查您刚刚安装的内核是否没有设置此标志。如果设置了,在几乎所有情况下,您都需要消除其原因,然后才能报告由此引发的问题。有关如何执行此操作的详细信息,请参阅上面的部分。

用新内核重现问题

使用您刚刚安装的内核重现问题。如果问题没有出现,请向下滚动到仅在稳定版和长期支持版内核中出现的问题的说明。

检查您刚刚安装的最新 Linux 内核版本是否出现该问题。如果问题已经修复,请考虑继续使用此版本线并放弃报告问题的计划。但请记住,只要 kernel.org 的稳定版和长期支持版(以及由此衍生的厂商内核)尚未修复此问题,其他用户可能仍会受到其困扰。如果您更喜欢使用其中一个版本或只是想帮助其用户,请参阅下面的“关于仅在旧内核版本线中发生的问题报告的详细信息”一节。

优化重现问题的描述

优化您的笔记:尝试找到并写下重现问题的最直接方法。确保最终结果包含所有重要细节,同时对于初次听说的人来说易于阅读和理解。如果您在此过程中学到了什么,请考虑再次搜索有关该问题的现有报告。

不必要的复杂报告会使他人难以理解您的报告。因此,请尝试找到一个易于描述且易于书面理解的重现方法。包含所有重要细节,但同时尽量保持简短。

在此以及之前的步骤中,您可能已经学到了一些关于您面临的问题。利用这些知识,再次搜索现有报告,看看是否有您可以加入的。

解码故障消息

如果您的故障涉及“panic”、“Oops”、“warning”或“BUG”,请考虑解码内核日志以找到触发错误的源代码行。

当内核检测到内部问题时,它会记录一些关于已执行代码的信息。这使得精确定位源代码中触发问题的确切行以及其如何被调用成为可能。但这只有在您配置内核时启用了 CONFIG_DEBUG_INFO 和 CONFIG_KALLSYMS 才能实现。如果您这样做了,请考虑解码来自内核日志的信息。这将使理解导致“panic”、“Oops”、“warning”或“BUG”的原因变得容易得多,从而增加了有人提供修复的机会。

解码可以使用 Linux 源代码树中的脚本完成。如果您正在运行您自己早些时候编译的内核,请像这样调用它:

[user@something ~]$ sudo dmesg | ./linux-5.10.5/scripts/decode_stacktrace.sh ./linux-5.10.5/vmlinux

如果您正在运行一个打包的原版内核,您可能需要安装带有调试符号的相应软件包。然后像这样调用脚本(如果您的发行版没有打包它,您可能需要从 Linux 源代码中获取它):

[user@something ~]$ sudo dmesg | ./linux-5.10.5/scripts/decode_stacktrace.sh \
 /usr/lib/debug/lib/modules/5.10.10-4.1.x86_64/vmlinux /usr/src/kernels/5.10.10-4.1.x86_64/

该脚本将处理如下所示的日志行,这些日志行显示了错误发生时内核正在执行的代码地址:

[   68.387301] RIP: 0010:test_module_init+0x5/0xffa [test_module]

解码后,这些行将如下所示:

[   68.387301] RIP: 0010:test_module_init (/home/username/linux-5.10.5/test-module/test-module.c:16) test_module

在这种情况下,执行的代码是从文件“~/linux-5.10.5/test-module/test-module.c”构建的,错误发生在“16”行中的指令处。

脚本将类似地解码以“Call trace”开头的段落中提及的地址,这些地址显示了问题发生函数的路径。此外,脚本还将显示内核正在执行的代码段的汇编输出。

注意,如果您无法完成此操作,只需跳过此步骤并在报告中说明原因。如果您幸运的话,可能不需要它。如果需要,可能会有人帮助您解决问题。另请注意,这只是解码内核堆栈跟踪的几种方法之一。有时可能需要不同的步骤才能检索相关细节。不用担心,如果您的案例需要,开发人员会告诉您该怎么做。

回归的特殊处理

如果您的问题是回归,请尽量缩小问题引入的时间范围。

Linux 首席开发者 Linus Torvalds 坚持认为 Linux 内核绝不能恶化,因此他认为回归是不可接受的,并希望它们能迅速得到修复。这就是为什么引入回归的更改如果其引起的问题无法通过其他方式迅速解决,通常会被立即回滚。因此,报告回归有点像打出一张王牌,以期迅速得到修复。但要实现这一点,导致回归的更改需要已知。通常,跟踪罪魁祸首是报告者的责任,因为维护者通常没有时间或设置来自己重现它。

为了找到这种变化,有一个称为“二分法”的过程,文档二分法寻找回归对此进行了详细描述。这个过程通常要求您构建大约十到二十个内核镜像,每次构建下一个镜像之前都要尝试重现问题。是的,这需要一些时间,但不用担心,它的工作速度比大多数人想象的要快得多。借助“二分查找”,这将引导您找到源代码管理系统中导致回归的那一次提交。一旦找到它,请在网上搜索该更改的主题、其提交 ID 和缩短的提交 ID(提交 ID 的前 12 个字符)。如果存在任何关于它的现有报告,这将引导您找到它们。

请注意,二分法需要一些专业知识,并非每个人都具备,并且需要相当大的努力,并非每个人都愿意投入。尽管如此,强烈建议您自己执行二分法。如果您确实不能或不想走这条路,至少找出哪个主线内核引入了回归。例如,如果从 5.5.15 切换到 5.8.4 时出现问题,那么至少尝试在该区域的所有主线版本(5.6、5.7 和 5.8)来检查它何时首次出现。除非您尝试在稳定版或长期支持版内核中查找回归,否则请避免测试版本号有三部分的版本(5.6.12、5.7.8),因为这会使结果难以解释,这可能使您的测试变得无用。一旦您找到引入回归的主要版本,请随意继续报告过程。但请记住:开发人员是否能够在不知道罪魁祸首的情况下提供帮助取决于具体问题。有时他们可能会从报告中识别出问题所在并修复它;其他时候,除非您执行二分法,否则他们将无法提供帮助。

在处理回归问题时,请确保您面临的问题确实是由内核引起的,而不是由其他原因引起的,如上文所述。

在整个过程中请记住:只有当旧内核和新内核使用相似的配置构建时,问题才符合回归的条件。这可以通过使用 make olddefconfig 来实现,正如 报告回归 中更详细的解释;该文档还提供了许多您可能需要了解的关于回归的其他信息。

编写并发送报告

通过详细描述问题来开始撰写报告。始终提及几件事:您为重现而安装的最新内核版本、所使用的 Linux 发行版以及您关于如何重现问题的注意事项。理想情况下,将内核的构建配置 (.config) 和 dmesg 的输出发布到网上某个地方并提供链接。包含或上传所有其他可能相关的信息,例如 Oops 的输出/屏幕截图或 lspci 的输出。写完主要部分后,在顶部插入一个正常长度的段落,快速概述问题和影响。在此之上再添加一句话,简要描述问题并吸引人们继续阅读。现在给它一个描述性的标题或主题,再次要更短。然后,您就可以按照 MAINTAINERS 文件告诉您的方式发送或提交报告了,除非您正在处理“高优先级问题”之一:它们需要特殊处理,这在下面“高优先级问题的特殊处理”中解释。

现在您已经准备好一切,是时候撰写报告了。如何撰写部分地由上面序言中链接的三个文档解释。因此,本文只提及一些要点以及 Linux 内核特有的事项。

有一点符合这两类:报告最关键的部分是标题/主题、第一句话和第一段。开发人员通常会收到大量的邮件。因此,他们通常只会花几秒钟快速浏览一封邮件,然后决定是继续还是仔细查看。因此:您的报告顶部部分越好,有人查看并帮助您的机会就越高。这就是为什么您现在应该忽略它们,先撰写详细报告。 ;-)

每个报告都应提及的事项

详细描述您的问题是如何在使用您安装的全新原版内核时发生的。尝试包含您之前编写和优化的逐步说明,这些说明概述了您以及理想情况下其他人如何重现问题;在极少数不可能的情况下,请尝试描述您为触发问题所做的操作。

还应包含其他人理解问题及其环境可能需要的所有相关信息。实际需要什么很大程度上取决于问题,但有些事情您应该始终包含:

  • 来自 cat /proc/version 的输出,其中包含 Linux 内核版本号及其构建时使用的编译器。

  • 机器运行的 Linux 发行版 (hostnamectl | grep "Operating System")

  • CPU 和操作系统的架构 (uname -mi)

  • 如果您正在处理回归问题并进行了二分法查找,请提及导致问题的更改的主题和提交 ID。

在许多情况下,向阅读您报告的人提供另外两件事也是明智之举:

  • 用于构建 Linux 内核的配置('.config' 文件)

  • dmesg 获取并写入文件的内核消息。确保它以类似“Linux version 5.8-1 (foobar@example.com) (gcc (GCC) 10.2.1, GNU ld version 2.34) #1 SMP Mon Aug 3 14:54:37 UTC 2020”的行开头。如果缺失,则第一次启动阶段的重要消息可能已被丢弃。在这种情况下,请考虑使用 journalctl -b 0 -k;或者您也可以重启,重现问题,然后立即调用 dmesg

这两个文件很大,因此将它们直接放入报告中不是个好主意。如果您在错误跟踪器中提交问题,请将它们作为附件附加到工单。如果您通过邮件报告问题,请不要附加它们,因为那会使邮件太大;而是执行以下操作之一:

  • 将文件上传到某个公开位置(您的网站、公共文件粘贴服务、专门为此目的在 bugzilla.kernel.org 上创建的工单等),并在您的报告中包含它们的链接。理想情况下,使用可以使文件保留多年的方式,因为它们可能在许多年后对某人有用;例如,如果五年或十年后,开发人员正在处理某个仅为修复您的问题而更改的代码,就可能发生这种情况。

  • 将文件放在一边,并说明您将在稍后的回复中单独发送它们。只记得在报告发出后实际这样做。;-)

可能需要提供的明智信息

根据问题,您可能需要添加更多背景数据。以下是一些通常建议提供的内容:

  • 如果您正在处理内核的“warning”、“OOPS”或“panic”,请将其包含在内。如果您无法复制粘贴,请尝试捕获 netconsole 跟踪或至少截取屏幕截图。

  • 如果问题可能与您的计算机硬件有关,请提及您使用的系统类型。例如,如果您遇到显卡问题,请提及制造商、显卡型号以及使用的芯片。如果是笔记本电脑,请提及其名称,但要确保其有意义。例如,“Dell XPS 13”就没有意义,因为它可能是 2012 年的型号;虽然它与现在销售的型号看起来差别不大,但除此之外,两者没有任何共同之处。因此,在这种情况下,请添加确切的型号,例如 2019 年推出的 XPS 13 型号为“9380”或“7390”。像“Lenovo Thinkpad T590”这样的名称也有些模糊:这款笔记本电脑有带独立显卡和不带独立显卡的版本,所以请尝试找到确切的型号名称或指定主要组件。

  • 提及正在使用的相关软件。如果加载模块有问题,您需要提及使用的 kmod、systemd 和 udev 版本。如果某个 DRM 驱动程序出现问题,您需要说明 libdrm 和 Mesa 的版本;还要指定您的 Wayland 合成器或 X-Server 及其驱动程序。如果您有文件系统问题,请提及相应文件系统实用程序的版本(e2fsprogs、btrfs-progs、xfsprogs 等)。

  • 收集可能感兴趣的内核额外信息。例如,lspci -nn 的输出将帮助其他人识别您使用的硬件。如果您遇到硬件问题,您甚至可能希望提供 sudo lspci -vvv 的输出,因为它提供了组件配置方式的见解。对于某些问题,包含诸如 /proc/cpuinfo/proc/ioports/proc/iomem/proc/modules/proc/scsi/scsi 等文件的内容可能很有用。一些子系统还提供收集相关信息的工具。其中一个工具是 alsa-info.sh由音频/声音子系统开发人员提供

这些示例应该能给您一些关于哪些数据可能值得附加的想法,但您需要自己思考哪些对其他人会有帮助。不用太担心遗漏什么,因为开发人员会要求您提供他们需要的额外细节。但从一开始就提供所有重要信息会增加有人会仔细查看的机会。

重要部分:报告的开头

现在您已经准备好报告的详细部分,让我们来看看最重要的部分:前几句话。因此,请回到顶部,在您刚刚写的部分之前添加类似“The detailed description:”的内容,并在顶部插入两个新行。现在写一个正常长度的段落,大致描述问题。省略所有无聊的细节,专注于读者需要了解的关键部分,以便理解整个情况;如果您认为此错误会影响大量用户,请提及这一点以引起人们的兴趣。

完成此操作后,在顶部再插入两行,并写一个一句话的摘要,快速解释报告的内容。之后,您必须更加抽象,为报告写一个更短的主题/标题。

现在您已经写好了这部分,花些时间优化它,因为它是您报告中最重要的部分:很多人只会阅读这部分,然后决定是否值得花时间阅读其余部分。

现在,按照 MAINTAINERS 文件告诉您的那样发送或提交报告,除非它是前面概述的那些“高优先级问题”之一:在这种情况下,请先阅读下一小节,然后再发送报告。

高优先级问题的特殊处理

高优先级问题的报告需要特殊处理。

严重问题:确保主题或工单标题以及第一段清楚地表明其严重性。

回归:使报告的主题以“[REGRESSION]”开头。

如果您成功地进行了二分法,请使用引入回归的更改的标题作为主题的第二部分。报告中还要提及罪魁祸首的提交 ID。如果二分法不成功,请在报告中提及最新测试的正常工作版本(例如 5.7)和问题出现的最早版本(例如 5.8-rc1)。

通过邮件发送报告时,抄送 Linux regressions 邮件列表 (regressions@lists.linux.dev)。如果报告需要提交到某个网络跟踪器,请继续进行。提交后,通过邮件将报告转发给 regressions 列表;抄送维护者和相关子系统的邮件列表。确保将转发的报告嵌入邮件正文,因此不要作为附件。还在邮件顶部添加简短说明,提及工单的 URL。

邮寄或转发报告时,如果二分法成功,请将罪魁祸首的作者添加到收件人列表中;还要抄送 signed-off-by 链中的每个人,您可以在其提交消息的末尾找到这些信息。

安全问题:对于这些问题,您需要评估公开披露细节是否会给其他用户带来短期风险。如果不是,只需按所述方式报告问题即可。对于具有此类风险的问题,您将需要稍微调整报告流程:

  • 如果 MAINTAINERS 文件指示您通过邮件报告问题,请不要抄送任何公共邮件列表。

  • 如果您应该在错误跟踪器中提交问题,请务必将工单标记为“私有”或“安全问题”。如果错误跟踪器不提供将报告保密的方式,请放弃并改为将您的报告作为私人邮件发送给维护者。

在这两种情况下,请务必将您的报告也发送到 MAINTAINERS 文件中“security contact”部分列出的地址。理想情况下,在发送报告时直接抄送他们。如果您在错误跟踪器中提交了报告,请将报告文本转发到这些地址;但在其顶部附上一个小说明,提及您已提交并附上工单链接。

有关更多信息,请参阅安全漏洞

报告发出后的职责

等待回应,并持续跟进,直到您能接受某种结果。因此,请公开并及时回应任何询问。测试提议的修复。进行主动测试:至少对新主线版本的每一个第一个发布候选版 (RC) 进行重新测试,并报告您的结果。如果事情停滞不前,请发送友善的提醒。如果您没有得到任何帮助或结果不尽如人意,请尝试自助。

如果您的报告写得好,并且您非常幸运,那么其中一位开发人员可能会立即发现问题所在;他们可能会编写一个补丁来修复它,测试它,并直接发送到主线进行集成,同时标记它以便稍后反向移植到需要的稳定版和长期支持版内核。那么您所需要做的就是回复“非常感谢”,并在修复版本发布后切换到该版本。

但这种理想情况很少发生。这就是为什么一旦报告发出,工作才刚刚开始。您将不得不做些什么取决于具体情况,但通常会是下面列出的事情。但在深入细节之前,请牢记在此过程的这部分需要注意的几点重要事项。

进一步互动的通用建议

始终公开回复:当您在错误跟踪器中提交问题时,请始终在那里回复,不要私下联系任何开发人员。对于邮件报告,回复任何收到的邮件时,请始终使用“回复全部”功能。这包括包含您可能想要添加到报告中的任何额外数据的邮件:转到您的邮件应用程序的“已发送”文件夹,并使用“回复全部”回复您包含报告的邮件。这种方法将确保公共邮件列表以及随着时间推移参与其中的所有人都能保持同步;它还会保持邮件主题的完整性,这对于邮件列表将所有相关邮件分组尤其重要。

只有两种情况下,错误跟踪器中的评论或“回复全部”是不合适的:

  • 有人告诉您私下发送某些内容。

  • 您被告知要发送某些内容,但发现其中包含需要保密的敏感信息。在这种情况下,可以私下发送给请求该信息的开发者。但请在工单或邮件中注明您已发送,以便其他人知道您已履行请求。

在寻求澄清或帮助之前进行研究:在此过程的这部分中,有人可能会告诉您做一些需要您尚未掌握技能的事情。例如,您可能会被要求使用一些您从未听说过的测试工具;或者您可能会被要求将补丁应用到 Linux 内核源代码以测试它是否有帮助。在某些情况下,发送回复询问如何操作是可以的。但在走这条路之前,尝试通过搜索互联网自己找到答案;或者考虑在其他地方寻求建议。例如,向朋友寻求帮助,或者将其发布到您通常会去的聊天室或论坛。

要有耐心:如果您真的幸运,您可能会在几小时内收到报告的回复。但大多数时候会需要更长的时间,因为维护者分布在全球各地,因此可能处于不同的时区——一个他们已经享受夜晚、远离键盘的时区。

一般来说,内核开发人员将在一到五个工作日内回复报告。有时会需要更长的时间,因为他们可能忙于合并窗口、其他工作、参加开发者大会,或者仅仅是享受漫长的暑假。

“高优先级问题”(参见上文解释)是例外:维护者应尽快处理它们;因此,您最多应等待一周(或如果紧急,只需两天)再发送友善的提醒。

有时维护者可能没有及时回复;有时可能会出现分歧,例如一个问题是否符合回归的条件。在这种情况下,请在邮件列表上提出您的担忧,并请求其他人公开或私下回复如何继续。如果这失败了,可能适合让更高权限的人员介入。如果是 Wi-Fi 驱动程序问题,那将是无线维护者;如果没有更高级别的维护者或所有其他方法都失败了,这可能是少数可以联系 Linus Torvalds 的情况之一。

主动测试:每当新的主线内核版本(“rc1”)的第一个预发布版本发布时,请检查问题是否已修复或是否有任何重要变化。在工单中或在您回复报告的邮件中提及结果(确保所有参与讨论的人都在抄送列表中)。这将表明您的承诺和您愿意提供帮助。它还会告诉开发人员问题是否仍然存在,并确保他们不会忘记它。偶尔进行其他一些重新测试(例如,使用 rc3、rc5 和最终版本)也是一个好主意,但只有当有相关变化或您无论如何都在撰写内容时才报告您的结果。

抛开所有这些一般性问题,让我们深入探讨如何帮助解决已报告的问题。

询问和测试请求

以下是您收到报告回复时应尽的职责:

检查您在与谁打交道:大多数时候,回复您报告的将是特定代码区域的维护者或开发人员。但由于问题通常是公开报告的,回复的人可能是任何人——包括那些想提供帮助,但最终可能会用他们的问题或请求完全误导您的人。这种情况很少发生,但这是许多原因之一,为什么快速进行互联网搜索以查看您正在与谁互动是明智之举。通过这样做,您还可以了解您的报告是否被正确的人听到,因为如果讨论在没有导致令人满意的解决方案的情况下逐渐平息,稍后可能需要提醒维护者(见下文)。

数据查询:您经常会被要求测试某些东西或提供额外的细节。请尽快提供所需的信息,因为您正在获得可能提供帮助的人的关注,等待时间越长,失去这种关注的风险就越大;如果您在几个工作日内未能提供信息,这种结果甚至很有可能发生。

测试请求:当您被要求测试诊断补丁或可能的修复时,也请尝试及时测试。但要正确地做,并确保不要急于求成:混淆很容易发生,并可能给所有相关人员带来很多困惑。一个常见的错误例如是认为一个提出的修复补丁已经应用,但实际上并没有。即使是经验丰富的测试人员偶尔也会发生这样的事情,但他们大多数时候会注意到,如果带有修复的内核表现得和没有修复的内核一样。

当没有实质性进展时该怎么办

一些报告将得不到负责任的 Linux 内核开发人员的任何回应;或者围绕该问题的讨论已经展开,但最终没有取得任何实质性成果。

在这些情况下,等待两周(最好是三周)再发送友善的提醒:也许维护者在您报告到达时暂时离开了键盘,或者有更重要的事情要处理。在撰写提醒时,请礼貌地询问是否还需要您做些什么来推动事情的进展。如果报告是通过邮件发出的,请在回复您最初邮件的第一行中这样做(见上文),并在下方包含原始报告的完整引用:这是少数几个“TOFU”(Text Over, Fullquote Under)是正确方法的例子之一,因为这样所有收件人都可以立即以正确的顺序掌握详细信息。

提醒后,再等三周等待回复。如果您仍然没有得到适当的回复,您应该首先重新考虑您的方法。您是否可能尝试联系了错误的人?报告是否冒犯性或混乱到人们决定完全远离它?排除这些因素的最佳方法是:将报告展示给一两个熟悉自由/开源软件(FLOSS)问题报告的人,并征求他们的意见。同时询问他们如何继续的建议。这可能意味着:准备一份更好的报告,并在发送之前请这些人审阅。这种方法完全可以;只需提及这是关于该问题的第二份改进报告,并包含指向第一份报告的链接。

如果报告得当,您可以发送第二次提醒;其中询问报告为何没有收到任何回复的原因。发送第二次提醒邮件的最佳时机是在新的 Linux 内核版本(“rc1”)的第一个预发布版本发布后不久,因为那时您无论如何都应该重新测试并提供状态更新(见上文)。

如果第二次提醒在一周内仍然没有收到任何回复,请尝试联系更高级别的维护者寻求建议:即使是忙碌的维护者,到那时也至少应该发送某种确认信息。

请记住为失望做好准备:维护者理想情况下应该对每个问题报告做出某种回应,但他们只负责修复前面概述的那些“高优先级问题”。所以,如果您收到类似“感谢您的报告,我目前有更重要的问题要处理,在可预见的将来没有时间研究这个问题”的回复,请不要过于沮丧。

也有可能在错误跟踪器或列表上经过一些讨论后,问题不再有任何进展,且提醒也无法促使任何人着手修复。这种情况可能令人沮丧,但在 Linux 内核开发中是可能发生的。本文档末尾的“为什么有些问题得不到任何回应或报告后仍未修复”解释了这种情况以及其他几个得不到帮助的原因。

如果您没有找到任何帮助,或者问题最终没有得到解决,请不要沮丧:Linux 内核是自由/开源软件(FLOSS),因此您仍然可以自助。例如,您可以尝试找到受影响的其他人,并与他们合作解决问题。这样的团队可以一起准备一份新的报告,其中提及您有多少人以及为什么您认为这应该得到修复。也许通过合作,您还可以缩小根本原因或引入回归的变更,这通常会使开发修复更容易。并且如果幸运的话,团队中可能有人对编程有所了解,并可能能够编写一个修复程序。

“报告稳定版和长期支持版内核线中的回归”参考

本小节详细说明了如果您在稳定版和长期支持版内核系列中遇到回归时需要执行的步骤。

确保特定版本线仍然获得支持

检查内核开发者是否仍在维护您所关心的 Linux 内核版本线:前往 kernel.org 的首页,确保它提到了该特定版本线的最新发布版本,并且没有“[EOL]”标签。

大多数内核版本线只支持大约三个月,因为维护它们更长时间工作量很大。因此,每年只会选择一个版本线,并至少支持两年(通常是六年)。这就是为什么您需要检查内核开发者是否仍在支持您关心的版本线。

请注意,如果 kernel.org 首页列出了两个稳定版本线,您应该考虑切换到较新的一个并忘记较旧的一个:对其的支持可能很快就会被放弃。然后它将获得“生命周期结束”(EOL)标记。达到该点的版本线仍会在 kernel.org 首页上提及一两周,但不再适合测试和报告。

搜索稳定版邮件列表

检查 Linux 稳定版邮件列表的存档,查找现有报告。

您面临的问题可能已经已知并已修复或即将修复。因此,请搜索 Linux 稳定版邮件列表的存档,查找与您问题类似的报告。如果找到任何匹配项,请考虑加入讨论,除非修复已经完成并计划很快应用。

用最新版本重现问题

将该特定版本系列的最新版本作为原版内核安装。确保此内核未被污染且问题仍然存在,因为问题可能已在那里修复。如果您最初是在供应商内核中注意到此问题,请检查已知可正常工作的最后一个版本的原版构建是否也运行良好。

在投入更多时间到这个流程之前,您需要检查您感兴趣的版本线的最新发布版是否已经修复了该问题。这个内核必须是原版的,并且在问题发生前不应该被污染,正如前面“安装一个新的内核进行测试”一节中详细概述的那样。

您是否最初是在厂商内核中注意到回归的?那么厂商应用的更改可能会干扰。您需要通过重新检查来排除这种情况。假设您从 5.10.4-vendor.42 更新到 5.10.5-vendor.43 时出现了问题。那么在按照上一段概述的方式测试最新的 5.10 版本后,检查 Linux 5.10.4 的原版构建是否也正常工作。如果那里也出现问题,那么该问题就不符合上游回归的条件,您需要返回到主要的分步指南来报告问题。

报告回归

发送一份简短的问题报告到 Linux stable 邮件列表 (stable@vger.kernel.org),并抄送 Linux regressions 邮件列表 (regressions@lists.linux.dev);如果你怀疑问题出在某个特定的子系统,请抄送其维护者及其邮件列表。大致描述问题,并最好解释如何重现。提及出现问题的第一个版本和工作正常的最后一个版本。然后等待进一步的指示。

当报告发生在稳定版或长期支持版内核系列(例如从 5.10.4 更新到 5.10.5)中的回归问题时,一份简短的报告足以快速地报告问题。因此,一份粗略的描述发给 stable 和 regressions 邮件列表就足够了;但如果你怀疑问题出在某个特定的子系统,也请抄送其维护者及其邮件列表,因为这会加快处理速度。

请注意,如果你能明确指出引入问题的确切版本,将对开发者有很大帮助。因此,如果在合理的时间范围内有可能,请尝试使用原版(vanilla)内核来找到该版本。假设你的发行版从 Linux 内核 5.10.5 更新到 5.10.8 时出现了问题。那么,按照上述指示,检查该版本系列中的最新内核,比如 5.10.9。如果它显示问题,尝试一个原版 5.10.5 以确保发行版应用的补丁没有干扰。如果问题在那里没有出现,尝试 5.10.7,然后(根据结果)尝试 5.10.8 或 5.10.6,以找到问题首次出现的版本。在报告中提及它,并说明 5.10.9 仍然存在问题。

前一段所概述的基本上是一种粗略的手动“二分查找”。一旦你的报告发出,你可能会被要求进行一次正规的二分查找,因为它能够精确定位导致问题的具体变更(这样就可以很容易地回滚以快速修复问题)。因此,如果时间允许,请考虑立即进行一次正规的二分查找。有关如何执行二分查找的详细信息,请参阅“回归问题的特别处理”部分和文档二分查找回归问题。如果二分查找成功,请将被认定为罪魁祸首的作者添加到收件人列表中;同时抄送其提交消息末尾“signed-off-by”链中的所有人。

“仅在旧内核版本系列中出现的问题报告”的参考资料

本节详细介绍了如果你无法使用主线内核重现问题,但希望在旧版本系列(即稳定版和长期支持版内核)中修复它时需要采取的步骤。

有些修复过于复杂

请做好准备,接下来的几个步骤可能无法在旧版本中解决问题:修复可能太大或风险太高,无法反向移植到那里。

即使是微小且看似明显的代码更改,有时也会引入新的、完全意想不到的问题。稳定版和长期支持版内核的维护者非常清楚这一点,因此只对这些内核应用符合关于 Linux -stable 发布版你所想知道的一切中概述的规则的更改。

例如,复杂或有风险的更改不符合条件,因此只应用到主线版本。其他修复很容易回溯到最新的稳定版和长期支持版内核,但集成到旧版本中风险太大。因此请注意,你所期望的修复可能属于那些不会回溯到你所关心的版本系列的类型。在这种情况下,你别无选择,只能接受这个问题或切换到较新的 Linux 版本,除非你想自己将修复程序打入你的内核。

通用准备工作

执行上面“仅在旧内核版本系列中出现的问题报告”部分中的前三个步骤。

你需要执行本指南另一部分中已描述的几个步骤。这些步骤将让你能够:

  • 检查内核开发者是否仍在维护你所关心的 Linux 内核版本系列。

  • 在 Linux stable 邮件列表中搜索已有的报告。

  • 检查最新发布版。

检查代码历史并搜索现有讨论

在 Linux 内核版本控制系统中搜索在主线中修复该问题的更改,因为其提交消息可能会告诉您该修复是否已计划进行反向移植。如果没有找到,请在适当的邮件列表中搜索讨论此类问题或同行评审可能修复的帖子;然后检查讨论,看看该修复是否被认为不适合反向移植。如果根本没有考虑反向移植,请加入最新的讨论,询问是否有可能。

在很多情况下,你处理的问题可能已在主线版本中出现,但已在那里得到修复。修复该问题的提交也需要回溯,才能解决问题。这就是为什么要搜索它或任何关于它的讨论。

  • 首先尝试在存储 Linux 内核源代码的 Git 仓库中查找该修复。你可以通过 kernel.org 上的网页界面或其镜像 GitHub 进行操作;如果你有本地克隆,也可以在命令行上使用 git log --grep=<pattern> 进行搜索。

    如果你找到了修复,请查看提交消息的末尾是否包含一个类似这样的“stable tag”:

    如果是这种情况,开发者已将该修复标记为可安全回溯到版本系列 5.4 及更高版本。大多数时候它会在两周内应用到那里,但有时会花费更长时间。

  • 如果该提交没有告诉你任何信息,或者你找不到修复,请再次查找关于该问题的讨论。使用你喜欢的互联网搜索引擎以及 Linux 内核开发者邮件列表的存档来搜索网络。另外,阅读上面“定位导致问题的内核区域”部分,并按照指示找到相关子系统:其错误跟踪器或邮件列表存档可能包含你正在寻找的答案。

  • 如果你看到一个提议的修复,请按照上述方式在版本控制系统中搜索它,因为提交可能会告诉你是否可以预期回溯。

    • 检查讨论中是否有任何迹象表明该修复可能风险太大而无法回溯到你所关心的版本系列。如果是这种情况,你必须接受这个问题,或者切换到应用了该修复的内核版本系列。

    • 如果该修复不包含 stable 标签并且没有讨论回溯,请加入讨论:提及你遇到问题的版本,并说明如果合适,你希望它得到修复。

寻求建议

前面的步骤之一应该能找到解决方案。如果行不通,请向似乎导致问题的子系统的维护者寻求建议;抄送该特定子系统的邮件列表以及稳定版邮件列表。

如果前三个步骤没有让你更接近解决方案,那么只剩下一种选择:寻求建议。通过邮件将邮件发送给问题似乎起源的子系统维护者;同时抄送该子系统的邮件列表以及稳定版邮件列表 (stable@vger.kernel.org)。

为什么有些问题报告后没有得到任何回应或仍未修复

向 Linux 开发者报告问题时,请注意只有“高优先级问题”(回归、安全问题、严重问题)才肯定会得到解决。维护者,或者如果所有其他方法都失败了,Linus Torvalds 本人会确保这一点。他们和其他内核开发者也会修复许多其他问题。但请注意,有时他们不能或不愿提供帮助;有时甚至没有人可以发送报告。

这最好用业余时间为 Linux 内核做出贡献的内核开发者来解释。内核中的许多驱动程序都是由这些程序员编写的,通常只是因为他们想让他们的硬件在他们喜欢的操作系统上可用。

这些程序员大多时候都会乐意修复其他人报告的问题。但没有人能强迫他们这样做,因为他们是自愿贡献的。

还有些情况是,这些开发者确实想修复一个问题,但不能:有时他们缺乏硬件编程文档来做到这一点。这通常发生在公开可用的文档过于肤浅,或者驱动程序是在逆向工程的帮助下编写的情况下。

迟早,业余开发者也会停止关心该驱动程序。也许他们的测试硬件坏了,被更 fancy 的东西取代了,或者已经老旧到除了计算机博物馆之外很难找到了。有时开发者会完全停止关心他们的代码和 Linux,因为他们生活中其他事情变得更重要了。在某些情况下,没有人愿意接管维护者这项工作——而且没有人能被强迫这样做,因为对 Linux 内核的贡献是自愿的。然而,被遗弃的驱动程序仍然留在内核中:它们对人们仍然有用,移除将是一种回归。

对于那些为 Linux 内核工作而获得报酬的开发者来说,情况并没有太大不同。现在大多数更改都是由他们贡献的。但他们的雇主迟早也会停止关心他们的代码,或者让程序员专注于其他事情。例如,硬件供应商主要通过销售新硬件赚钱;因此他们中很少有人投入大量时间和精力来维护一个他们几年前停止销售的产品的 Linux 内核驱动程序。企业 Linux 发行商通常会关心更长的时间,但在新版本中常常放弃对旧的和稀有硬件的支持,以限制范围。通常,一旦公司放弃了某些代码,业余贡献者会接手,但正如前面提到的:迟早他们也会放弃这些代码。

优先级是导致某些问题未被修复的另一个原因,因为维护者通常被迫设定优先级,因为用于 Linux 工作的时间有限。无论是业余时间,还是雇主授予开发者用于上游内核维护工作的时间,都是如此。有时维护者也会被报告淹没,即使驱动程序几乎完美运行。为了不完全陷入困境,程序员可能别无选择,只能对问题报告进行优先级排序,并拒绝其中的一些。

但不必对此过于担心,许多驱动程序都有活跃的维护者,他们非常乐意修复尽可能多的问题。

结语

与其他自由/开源软件相比,向 Linux 内核开发者报告问题是困难的:本文档的篇幅和复杂性以及字里行间的含义都说明了这一点。但目前情况就是如此。本文的主要作者希望通过记录现状,能为随着时间推移改善这种情况奠定一些基础。