二分查找回归

本文档描述了如何使用 git bisect 查找破坏某些内容的源代码更改——例如,在从 Linux 6.0 升级到 6.1 后,某些功能停止工作时。

文本侧重于该过程的要点。如果您是二分查找内核的新手,最好遵循 如何验证错误和二分查找回归:它从头到尾描述了所有内容,同时涵盖了即使是内核开发人员有时也会忘记的多个方面。这包括尽早检测到二分查找会浪费时间的情况,因为没有人会关心结果——例如,因为问题发生在内核将自己标记为“受污染”之后,发生在已放弃的版本中,已被修复,或由您或您的 Linux 发行版执行的 .config 更改引起。

使用二分法查找导致内核问题的更改

注意:以下过程假设您为二分查找准备好了一切。这包括拥有一个包含适当源代码的 Git 克隆,安装构建和安装内核所需的软件,以及存储在安全位置的 .config 文件(以下示例假设为“~/prepared_kernel_.config”),以便在每个二分查找步骤中用作原始基础;理想情况下,您还找到了一种完全可靠且直接的方法来重现回归。

  • 准备:开始二分查找,并告知 Git 您认为工作和中断的历史点,Git 称之为“good”和“bad”

    git bisect start
    git bisect good v6.0
    git bisect bad v6.1
    

    您也可以指定提交 ID,而不是像“v6.0”和“v6.1”这样的 Git 标签。

  1. 将您准备好的 .config 复制到构建目录,并根据 Git 检出进行测试的代码库的需求进行调整

    cp ~/prepared_kernel_.config .config
    make olddefconfig
    
  2. 现在构建、安装和引导内核。这可能会由于不相关的原因而失败,例如,当二分查找的当前阶段发生编译错误时,稍后的更改会解决该错误。在这种情况下,运行 git bisect skip 并返回到步骤 1。

  3. 检查您刚刚构建的内核中回归的功能是否正常工作。

    如果它正常工作,则执行

    git bisect good
    

    如果它已损坏,则运行

    git bisect bad
    

    请注意,即使一次出错也会使其余的二分查找完全偏离方向。为了防止以后不得不重新开始,因此您需要确保您告诉 Git 的内容是正确的;因此,如果您的重现器不可靠,通常明智的做法是多花几分钟进行测试。

    发出这两个命令中的一个后,Git 通常会检出另一个二分查找点,并打印类似“Bisecting: 675 revisions left to test after this (roughly 10 steps)”的内容。在这种情况下,返回到步骤 1。

    如果 Git 而是打印类似“cafecaca0c0dacafecaca0c0dacafecaca0c0da is the first bad commit”的内容,则您已完成二分查找。在这种情况下,请移至下面的下一个点。请注意,在显示该行之后,Git 将显示有关罪魁祸首的一些详细信息,包括其补丁描述;这很容易填满您的终端,因此您可能需要向上滚动才能看到提及罪魁祸首的提交 ID 的消息。

    如果您错过了 Git 的输出,您可以始终运行 git bisect log 以打印状态:它将显示还剩多少步骤或提及二分查找的结果。

  • 建议的补充任务:将二分查找日志和当前的 .config 文件放在一边以供错误报告使用;此外,告诉 Git 将源代码重置为二分查找之前的状态

    git bisect log > ~/bisection-log
    cp .config ~/bisection-config-culprit
    git bisect reset
    
  • 建议的可选任务:尝试在最新代码库之上恢复罪魁祸首,并检查是否修复了您的错误;如果是这样,它会验证二分查找,并使开发人员能够通过恢复来解决回归。

    要尝试此操作,请更新您的克隆并检出最新的主线。然后通过指定其提交 ID 来告诉 Git 恢复更改

    git revert --no-edit cafec0cacaca0
    

    Git 可能会拒绝此操作,例如,当二分查找落在合并提交上时。在这种情况下,放弃尝试。如果 Git 无法自行恢复罪魁祸首,因为稍后的更改依赖于它,则执行相同的操作——除非您二分查找的是稳定或长期内核系列,在这种情况下,您需要检出其最新的代码库并尝试在那里恢复。

    如果恢复成功,请构建并测试另一个内核,以检查恢复是否解决了您的回归。

这样,该过程就完成了。现在,按照 报告问题 中的描述报告回归。

二分查找 linux-next

如果您遇到仅在 linux-next 中发生的问题,请在 linux-next 分支 “stable” 和 “master” 之间进行二分查找。以下命令将为添加为名为“next”的远程的 linux-next 树启动该过程

git bisect start
git bisect good next/stable
git bisect bad next/master

“stable”分支指的是当前 linux-next 版本(在“master”分支中找到)所基于的 linux-mainline 的状态——因此,前者应该没有在 -next 中显示但在 Linus 的树中没有显示的任何问题。

这将在广泛的更改范围内进行二分查找,其中一些您可能在早期的 linux-next 版本中使用过,但没有问题。可悲的是,没有简单的方法可以避免检查它们:从一个 linux-next 版本到稍后的版本(例如在“next-20241020”和“next-20241021”之间)进行二分查找是不可能的,因为它们没有共同的历史。

其他阅读材料